Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 6 May 2007 20:21:57 +0000 (13:21 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 6 May 2007 20:21:57 +0000 (13:21 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild: (38 commits)
  kconfig: fix mconf segmentation fault
  kbuild: enable use of code from a different dir
  kconfig: error out if recursive dependencies are found
  kbuild: scripts/basic/fixdep segfault on pathological string-o-death
  kconfig: correct minor typo in Kconfig warning message.
  kconfig: fix path to modules.txt in Kconfig help
  usr/Kconfig: fix typo
  kernel-doc: alphabetically-sorted entries in index.html of 'htmldocs'
  kbuild: be more explicit on missing .config file
  kbuild: clarify the creation of the LOCALVERSION_AUTO string.
  kbuild: propagate errors from find in scripts/gen_initramfs_list.sh
  kconfig: refer to qt3 if we cannot find qt libraries
  kbuild: handle compressed cpio initramfs-es
  kbuild: ignore section mismatch warning for references from .paravirtprobe to .init.text
  kbuild: remove stale comment in modpost.c
  kbuild/mkuboot.sh: allow spaces in CROSS_COMPILE
  kbuild: fix make mrproper for Documentation/DocBook/man
  kbuild: remove kconfig binaries during make mrproper
  kconfig/menuconfig: do not hardcode '.config'
  kbuild: override build timestamp & version
  ...

1413 files changed:
CREDITS
Documentation/dontdiff
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/i386/boot.txt
Documentation/input/input-programming.txt
Documentation/kernel-parameters.txt
Documentation/pci.txt
Documentation/power/pci.txt
Documentation/scsi/aacraid.txt
Documentation/scsi/ncr53c8xx.txt
Documentation/spi/pxa2xx
Documentation/usb/usb-serial.txt
Documentation/x86_64/boot-options.txt
Documentation/x86_64/fake-numa-for-cpusets [new file with mode: 0644]
Documentation/x86_64/machinecheck
MAINTAINERS
Makefile
arch/alpha/boot/misc.c
arch/alpha/kernel/err_common.c
arch/alpha/kernel/err_ev6.c
arch/alpha/kernel/err_ev7.c
arch/alpha/kernel/vmlinux.lds.S
arch/arm/Kconfig
arch/arm/boot/compressed/head-at91rm9200.S
arch/arm/boot/compressed/misc.c
arch/arm/common/sa1111.c
arch/arm/common/via82c505.c
arch/arm/configs/ixp4xx_defconfig
arch/arm/configs/picotux200_defconfig [new file with mode: 0644]
arch/arm/kernel/Makefile
arch/arm/kernel/ecard.c
arch/arm/kernel/ecard.h [new file with mode: 0644]
arch/arm/kernel/head.S
arch/arm/kernel/irq.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/ptrace.h
arch/arm/kernel/signal.c
arch/arm/kernel/stacktrace.c [new file with mode: 0644]
arch/arm/kernel/stacktrace.h [new file with mode: 0644]
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/lib/backtrace.S
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/board-picotux200.c [new file with mode: 0644]
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-ebsa110/io.c
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-integrator/pci.c
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-iop13xx/Makefile
arch/arm/mach-iop13xx/io.c
arch/arm/mach-iop13xx/iq81340mc.c
arch/arm/mach-iop13xx/iq81340sc.c
arch/arm/mach-iop13xx/pci.c
arch/arm/mach-iop13xx/setup.c
arch/arm/mach-iop13xx/tpmi.c [new file with mode: 0644]
arch/arm/mach-iop32x/Kconfig
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/iq80321.c
arch/arm/mach-iop33x/Kconfig
arch/arm/mach-iop33x/iq80331.c
arch/arm/mach-iop33x/iq80332.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp2000/enp2611.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/Makefile
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/dsmg600-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/dsmg600-power.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/dsmg600-setup.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/ixdp425-pci.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-lh7a40x/irq-lh7a400.c
arch/arm/mach-lh7a40x/irq-lh7a404.c
arch/arm/mach-lh7a40x/irq-lpd7a40x.c
arch/arm/mach-ns9xxx/Kconfig
arch/arm/mach-ns9xxx/Makefile
arch/arm/mach-ns9xxx/board-jscc9p9360.c [new file with mode: 0644]
arch/arm/mach-ns9xxx/board-jscc9p9360.h [new file with mode: 0644]
arch/arm/mach-ns9xxx/mach-cc9p9360js.c [new file with mode: 0644]
arch/arm/mach-omap1/irq.c
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap1/time.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/ssp.c
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-amlm5900.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-n30.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-qt2410.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s3c2412/irq.c
arch/arm/mach-s3c2412/mach-smdk2413.c
arch/arm/mach-s3c2412/mach-vstms.c
arch/arm/mach-s3c2440/irq.c
arch/arm/mach-s3c2440/mach-anubis.c
arch/arm/mach-s3c2440/mach-nexcoder.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mach-s3c2440/mach-rx3715.c
arch/arm/mach-s3c2440/mach-smdk2440.c
arch/arm/mach-s3c2443/irq.c
arch/arm/mach-s3c2443/mach-smdk2443.c
arch/arm/mach-sa1100/clock.c
arch/arm/mach-sa1100/irq.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-shark/irq.c
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/pci.c
arch/arm/mm/alignment.c
arch/arm/mm/fault.c
arch/arm/mm/init.c
arch/arm/mm/ioremap.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/proc-xscale.S
arch/arm/oprofile/backtrace.c
arch/arm/plat-iop/io.c
arch/arm/plat-iop/pci.c
arch/arm/plat-iop/time.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/common.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/timer32k.c
arch/arm/plat-s3c24xx/clock.c
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/irq.c
arch/arm/plat-s3c24xx/s3c244x-irq.c
arch/arm/vfp/vfpdouble.c
arch/arm/vfp/vfpsingle.c
arch/arm26/boot/compressed/misc.c
arch/cris/arch-v32/vmlinux.lds.S
arch/frv/kernel/vmlinux.lds.S
arch/i386/Kconfig
arch/i386/Kconfig.cpu
arch/i386/Kconfig.debug
arch/i386/Makefile
arch/i386/Makefile.cpu
arch/i386/boot/Makefile
arch/i386/boot/compressed/misc.c
arch/i386/boot/setup.S
arch/i386/defconfig
arch/i386/kernel/Makefile
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/alternative.c
arch/i386/kernel/apic.c
arch/i386/kernel/apm.c
arch/i386/kernel/asm-offsets.c
arch/i386/kernel/cpu/Makefile
arch/i386/kernel/cpu/amd.c
arch/i386/kernel/cpu/bugs.c [new file with mode: 0644]
arch/i386/kernel/cpu/centaur.c
arch/i386/kernel/cpu/common.c
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/cpu/cyrix.c
arch/i386/kernel/cpu/intel.c
arch/i386/kernel/cpu/mcheck/k7.c
arch/i386/kernel/cpu/mcheck/mce.c
arch/i386/kernel/cpu/mcheck/p4.c
arch/i386/kernel/cpu/mtrr/generic.c
arch/i386/kernel/cpu/mtrr/main.c
arch/i386/kernel/cpu/nexgen.c
arch/i386/kernel/cpu/perfctr-watchdog.c [new file with mode: 0644]
arch/i386/kernel/cpu/proc.c
arch/i386/kernel/cpu/rise.c
arch/i386/kernel/cpu/transmeta.c
arch/i386/kernel/cpu/umc.c
arch/i386/kernel/doublefault.c
arch/i386/kernel/e820.c
arch/i386/kernel/efi.c
arch/i386/kernel/entry.S
arch/i386/kernel/head.S
arch/i386/kernel/i386_ksyms.c
arch/i386/kernel/i8253.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/ioport.c
arch/i386/kernel/irq.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/nmi.c
arch/i386/kernel/paravirt.c
arch/i386/kernel/process.c
arch/i386/kernel/quirks.c
arch/i386/kernel/reboot.c
arch/i386/kernel/reboot_fixups.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/sysenter.c
arch/i386/kernel/time.c
arch/i386/kernel/trampoline.S
arch/i386/kernel/traps.c
arch/i386/kernel/tsc.c
arch/i386/kernel/verify_cpu.S [new file with mode: 0644]
arch/i386/kernel/vmi.c
arch/i386/kernel/vmiclock.c [new file with mode: 0644]
arch/i386/kernel/vmitime.c [deleted file]
arch/i386/kernel/vmlinux.lds.S
arch/i386/kernel/vsyscall.lds.S
arch/i386/lib/bitops.c
arch/i386/lib/checksum.S
arch/i386/lib/getuser.S
arch/i386/lib/putuser.S
arch/i386/lib/usercopy.c
arch/i386/mach-generic/bigsmp.c
arch/i386/mach-generic/es7000.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/mm/fault.c
arch/i386/mm/highmem.c
arch/i386/mm/init.c
arch/i386/mm/pageattr.c
arch/i386/mm/pgtable.c
arch/i386/oprofile/nmi_int.c
arch/i386/pci/fixup.c
arch/i386/pci/i386.c
arch/i386/pci/init.c
arch/i386/pci/mmconfig-shared.c
arch/i386/power/cpu.c
arch/i386/power/suspend.c
arch/ia64/Kconfig
arch/ia64/sn/kernel/huberror.c
arch/ia64/sn/kernel/msi_sn.c
arch/ia64/sn/kernel/xpnet.c
arch/m32r/kernel/vmlinux.lds.S
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/kernel/vmlinux.lds.S
arch/mips/lib/iomap.c
arch/parisc/kernel/vmlinux.lds.S
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/suspend.c [new file with mode: 0644]
arch/powerpc/kernel/vio.c
arch/powerpc/kernel/vmlinux.lds.S
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/kernel/vmlinux.lds.S
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/kernel/vmlinux.lds.S
arch/s390/mm/fault.c
arch/sh/kernel/vmlinux.lds.S
arch/sh64/kernel/vmlinux.lds.S
arch/sh64/mach-cayman/iomap.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc64/Kconfig
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/smp.c
arch/sparc64/solaris/ioctl.c
arch/um/defconfig
arch/x86_64/Kconfig
arch/x86_64/Makefile
arch/x86_64/boot/Makefile
arch/x86_64/boot/compressed/Makefile
arch/x86_64/boot/compressed/head.S
arch/x86_64/boot/compressed/misc.c
arch/x86_64/boot/compressed/vmlinux.lds [new file with mode: 0644]
arch/x86_64/boot/compressed/vmlinux.scr
arch/x86_64/boot/setup.S
arch/x86_64/boot/video.S [deleted file]
arch/x86_64/defconfig
arch/x86_64/ia32/ia32_binfmt.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/ia32/syscall32.c
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/acpi/sleep.c
arch/x86_64/kernel/acpi/wakeup.S
arch/x86_64/kernel/aperture.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/asm-offsets.c
arch/x86_64/kernel/bugs.c [new file with mode: 0644]
arch/x86_64/kernel/cpufreq/Kconfig
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/early-quirks.c
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/functionlist [deleted file]
arch/x86_64/kernel/genapic.c
arch/x86_64/kernel/genapic_cluster.c [deleted file]
arch/x86_64/kernel/genapic_flat.c
arch/x86_64/kernel/head.S
arch/x86_64/kernel/head64.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/ioport.c
arch/x86_64/kernel/machine_kexec.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-calgary.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/pci-nommu.c
arch/x86_64/kernel/pci-swiotlb.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/signal.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/suspend.c
arch/x86_64/kernel/suspend_asm.S
arch/x86_64/kernel/syscall.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/trampoline.S
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/tsc.c
arch/x86_64/kernel/tsc_sync.c
arch/x86_64/kernel/verify_cpu.S [new file with mode: 0644]
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/kernel/vsyscall.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/k8topology.c
arch/x86_64/mm/numa.c
arch/x86_64/mm/pageattr.c
arch/x86_64/mm/srat.c
arch/xtensa/kernel/vmlinux.lds.S
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_idle.c
drivers/acpi/processor_perflib.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/pata_icside.c [new file with mode: 0644]
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/amd64-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/kvm/kvm.h
drivers/kvm/kvm_main.c
drivers/kvm/kvm_svm.h
drivers/kvm/kvm_vmx.h [deleted file]
drivers/kvm/mmu.c
drivers/kvm/paging_tmpl.h
drivers/kvm/svm.c
drivers/kvm/svm.h
drivers/kvm/vmx.c
drivers/kvm/x86_emulate.c
drivers/kvm/x86_emulate.h
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/at91_mci.c [deleted file]
drivers/mmc/au1xmmc.c [deleted file]
drivers/mmc/au1xmmc.h [deleted file]
drivers/mmc/card/Kconfig [new file with mode: 0644]
drivers/mmc/card/Makefile [new file with mode: 0644]
drivers/mmc/card/block.c [new file with mode: 0644]
drivers/mmc/card/queue.c [new file with mode: 0644]
drivers/mmc/card/queue.h [new file with mode: 0644]
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 [new file with mode: 0644]
drivers/mmc/core/sysfs.h [new file with mode: 0644]
drivers/mmc/host/Kconfig [new file with mode: 0644]
drivers/mmc/host/Makefile [new file with mode: 0644]
drivers/mmc/host/at91_mci.c [new file with mode: 0644]
drivers/mmc/host/au1xmmc.c [new file with mode: 0644]
drivers/mmc/host/au1xmmc.h [new file with mode: 0644]
drivers/mmc/host/imxmmc.c [new file with mode: 0644]
drivers/mmc/host/imxmmc.h [new file with mode: 0644]
drivers/mmc/host/mmci.c [new file with mode: 0644]
drivers/mmc/host/mmci.h [new file with mode: 0644]
drivers/mmc/host/omap.c [new file with mode: 0644]
drivers/mmc/host/pxamci.c [new file with mode: 0644]
drivers/mmc/host/pxamci.h [new file with mode: 0644]
drivers/mmc/host/sdhci.c [new file with mode: 0644]
drivers/mmc/host/sdhci.h [new file with mode: 0644]
drivers/mmc/host/tifm_sd.c [new file with mode: 0644]
drivers/mmc/host/wbsd.c [new file with mode: 0644]
drivers/mmc/host/wbsd.h [new file with mode: 0644]
drivers/mmc/imxmmc.c [deleted file]
drivers/mmc/imxmmc.h [deleted file]
drivers/mmc/mmc.c [deleted file]
drivers/mmc/mmc.h [deleted file]
drivers/mmc/mmc_block.c [deleted file]
drivers/mmc/mmc_queue.c [deleted file]
drivers/mmc/mmc_queue.h [deleted file]
drivers/mmc/mmc_sysfs.c [deleted file]
drivers/mmc/mmci.c [deleted file]
drivers/mmc/mmci.h [deleted file]
drivers/mmc/omap.c [deleted file]
drivers/mmc/pxamci.c [deleted file]
drivers/mmc/pxamci.h [deleted file]
drivers/mmc/sdhci.c [deleted file]
drivers/mmc/sdhci.h [deleted file]
drivers/mmc/tifm_sd.c [deleted file]
drivers/mmc/wbsd.c [deleted file]
drivers/mmc/wbsd.h [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/irda/pxaficp_ir.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/serial/amba-pl010.c
drivers/serial/atmel_serial.c
drivers/serial/atmel_serial.h
drivers/serial/imx.c
drivers/serial/pxa.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/host/ohci-pxa27x.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/console/vgacon.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/pxafb.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/cifs/CHANGES
fs/cifs/README
fs/cifs/TODO
fs/cifs/cifs_fs_sb.h
fs/cifs/cifs_unicode.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/netmisc.c
fs/cifs/readdir.c
fs/compat.c
fs/compat_ioctl.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/proc/vmcore.c
fs/sysfs/bin.c
fs/sysfs/file.c
include/acpi/acpi_bus.h
include/asm-alpha/mmu_context.h
include/asm-alpha/percpu.h
include/asm-alpha/scatterlist.h
include/asm-arm/arch-at91/at91_adc.h [new file with mode: 0644]
include/asm-arm/arch-at91/board.h
include/asm-arm/arch-ebsa110/io.h
include/asm-arm/arch-imx/imx-regs.h
include/asm-arm/arch-imx/mmc.h
include/asm-arm/arch-iop13xx/io.h
include/asm-arm/arch-iop13xx/iop13xx.h
include/asm-arm/arch-iop13xx/time.h
include/asm-arm/arch-iop32x/io.h
include/asm-arm/arch-iop32x/iop32x.h
include/asm-arm/arch-iop32x/memory.h
include/asm-arm/arch-iop33x/io.h
include/asm-arm/arch-iop33x/iop33x.h
include/asm-arm/arch-iop33x/memory.h
include/asm-arm/arch-ixp23xx/io.h
include/asm-arm/arch-ixp4xx/cpu.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/dma.h
include/asm-arm/arch-ixp4xx/dsmg600.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/entry-macro.S
include/asm-arm/arch-ixp4xx/gpio.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/hardware.h
include/asm-arm/arch-ixp4xx/io.h
include/asm-arm/arch-ixp4xx/irqs.h
include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
include/asm-arm/arch-netx/netx-regs.h
include/asm-arm/arch-ns9xxx/board.h
include/asm-arm/arch-ns9xxx/clock.h
include/asm-arm/arch-ns9xxx/hardware.h
include/asm-arm/arch-ns9xxx/processor.h
include/asm-arm/arch-ns9xxx/regs-sys.h
include/asm-arm/arch-pxa/i2c.h
include/asm-arm/arch-pxa/mmc.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/pxa27x_keyboard.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-ac97.h
include/asm-arm/arch-s3c2410/regs-udc.h
include/asm-arm/ecard.h
include/asm-arm/hardware/iop3xx.h
include/asm-arm/io.h
include/asm-arm/mach/map.h
include/asm-arm/mach/mmc.h
include/asm-arm/mmu_context.h
include/asm-arm/plat-s3c24xx/clock.h
include/asm-arm/plat-s3c24xx/cpu.h
include/asm-arm/ptrace.h
include/asm-arm/system.h
include/asm-arm/thread_info.h
include/asm-arm26/mmu_context.h
include/asm-avr32/mmu_context.h
include/asm-avr32/scatterlist.h
include/asm-cris/mmu_context.h
include/asm-frv/mmu_context.h
include/asm-frv/scatterlist.h
include/asm-generic/mm_hooks.h [new file with mode: 0644]
include/asm-generic/percpu.h
include/asm-generic/vmlinux.lds.h
include/asm-h8300/mmu_context.h
include/asm-h8300/scatterlist.h
include/asm-i386/Kbuild
include/asm-i386/agp.h
include/asm-i386/alternative.h
include/asm-i386/apic.h
include/asm-i386/bugs.h
include/asm-i386/cpufeature.h
include/asm-i386/current.h
include/asm-i386/desc.h
include/asm-i386/e820.h
include/asm-i386/elf.h
include/asm-i386/fixmap.h
include/asm-i386/genapic.h
include/asm-i386/highmem.h
include/asm-i386/hpet.h
include/asm-i386/i387.h
include/asm-i386/io.h
include/asm-i386/irq.h
include/asm-i386/irq_regs.h
include/asm-i386/irqflags.h
include/asm-i386/kexec.h
include/asm-i386/mach-bigsmp/mach_apic.h
include/asm-i386/mach-default/mach_apic.h
include/asm-i386/mach-es7000/mach_apic.h
include/asm-i386/mach-es7000/mach_mpparse.h
include/asm-i386/mach-generic/mach_apic.h
include/asm-i386/mach-numaq/mach_apic.h
include/asm-i386/mach-summit/mach_apic.h
include/asm-i386/mach-summit/mach_mpparse.h
include/asm-i386/mach-visws/mach_apic.h
include/asm-i386/mmu_context.h
include/asm-i386/module.h
include/asm-i386/msr-index.h [new file with mode: 0644]
include/asm-i386/msr.h
include/asm-i386/mtrr.h
include/asm-i386/nmi.h
include/asm-i386/page.h
include/asm-i386/paravirt.h
include/asm-i386/pda.h [deleted file]
include/asm-i386/percpu.h
include/asm-i386/pgalloc.h
include/asm-i386/pgtable-2level-defs.h
include/asm-i386/pgtable-2level.h
include/asm-i386/pgtable-3level-defs.h
include/asm-i386/pgtable-3level.h
include/asm-i386/pgtable.h
include/asm-i386/processor-flags.h [new file with mode: 0644]
include/asm-i386/processor.h
include/asm-i386/reboot.h [new file with mode: 0644]
include/asm-i386/reboot_fixups.h [new file with mode: 0644]
include/asm-i386/required-features.h [new file with mode: 0644]
include/asm-i386/scatterlist.h
include/asm-i386/segment.h
include/asm-i386/smp.h
include/asm-i386/system.h
include/asm-i386/timer.h
include/asm-i386/tlbflush.h
include/asm-i386/tsc.h
include/asm-i386/uaccess.h
include/asm-i386/vmi_time.h
include/asm-i386/voyager.h
include/asm-ia64/mmu_context.h
include/asm-ia64/scatterlist.h
include/asm-m32r/mmu_context.h
include/asm-m32r/scatterlist.h
include/asm-m68k/adb.h [deleted file]
include/asm-m68k/atarikb.h
include/asm-m68k/mmu_context.h
include/asm-m68knommu/mmu_context.h
include/asm-m68knommu/scatterlist.h
include/asm-mips/mmu_context.h
include/asm-mips/scatterlist.h
include/asm-parisc/mmu_context.h
include/asm-parisc/scatterlist.h
include/asm-powerpc/mmu_context.h
include/asm-powerpc/ps3av.h
include/asm-ppc/mmu_context.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-s390/mmu_context.h
include/asm-sh/mmu_context.h
include/asm-sh/scatterlist.h
include/asm-sh64/mmu_context.h
include/asm-sh64/scatterlist.h
include/asm-sparc/mmu_context.h
include/asm-sparc64/mmu_context.h
include/asm-sparc64/percpu.h
include/asm-sparc64/scatterlist.h
include/asm-um/mmu_context.h
include/asm-v850/mmu_context.h
include/asm-v850/scatterlist.h
include/asm-x86_64/Kbuild
include/asm-x86_64/agp.h
include/asm-x86_64/alternative.h
include/asm-x86_64/apic.h
include/asm-x86_64/bugs.h
include/asm-x86_64/const.h [new file with mode: 0644]
include/asm-x86_64/desc.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/fixmap.h
include/asm-x86_64/genapic.h
include/asm-x86_64/ipi.h
include/asm-x86_64/irqflags.h
include/asm-x86_64/mmu_context.h
include/asm-x86_64/mmzone.h
include/asm-x86_64/msr-index.h [new file with mode: 0644]
include/asm-x86_64/msr.h
include/asm-x86_64/mtrr.h
include/asm-x86_64/nmi.h
include/asm-x86_64/page.h
include/asm-x86_64/percpu.h
include/asm-x86_64/pgalloc.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/processor-flags.h [new file with mode: 0644]
include/asm-x86_64/processor.h
include/asm-x86_64/proto.h
include/asm-x86_64/scatterlist.h
include/asm-x86_64/segment.h
include/asm-x86_64/smp.h
include/asm-x86_64/suspend.h
include/asm-x86_64/system.h
include/asm-x86_64/timex.h
include/asm-x86_64/tlbflush.h
include/asm-x86_64/unistd.h
include/asm-xtensa/mmu_context.h
include/asm-xtensa/scatterlist.h
include/crypto/algapi.h
include/linux/Kbuild
include/linux/bootmem.h
include/linux/cpufreq.h
include/linux/crash_dump.h
include/linux/crypto.h
include/linux/device.h
include/linux/elf.h
include/linux/elfnote.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/init.h
include/linux/input-polldev.h [new file with mode: 0644]
include/linux/input.h
include/linux/interrupt.h
include/linux/kobject.h
include/linux/kvm.h
include/linux/lockd/lockd.h
include/linux/miscdevice.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/percpu.h
include/linux/poison.h
include/linux/reboot_fixups.h [deleted file]
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]
init/main.c
kernel/fork.c
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
kernel/power/snapshot.c
kernel/power/swap.c
lib/inflate.c
lib/iomap.c
lib/kobject.c
lib/parser.c
mm/highmem.c
mm/mmap.c
mm/slab.c
mm/vmalloc.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
scripts/mod/modpost.c
security/inode.c
sound/arm/pxa2xx-ac97.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
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c

diff --git a/CREDITS b/CREDITS
index d714030..c5f819b 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1745,8 +1745,9 @@ S: D-64295
 S: Germany
 
 N: Andi Kleen
-E: ak@muc.de
-D: network hacker, syncookies
+E: andi@firstfloor.org
+U: http://www.halobates.de
+D: network, x86, NUMA, various hacks
 S: Schwalbenstr. 96
 S: 85551 Ottobrunn
 S: Germany
index 63c2d0c..64e9f6c 100644 (file)
@@ -55,8 +55,8 @@ aic7*seq.h*
 aicasm
 aicdb.h*
 asm
-asm-offsets.*
-asm_offsets.*
+asm-offsets.h
+asm_offsets.h
 autoconf.h*
 bbootsect
 bin2c
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 38fe1f0..6498666 100644 (file)
@@ -2,7 +2,7 @@
                     ----------------------------
 
                    H. Peter Anvin <hpa@zytor.com>
-                       Last update 2007-01-26
+                       Last update 2007-03-06
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -35,9 +35,13 @@ Protocol 2.03:       (Kernel 2.4.18-pre1) Explicitly makes the highest possible
                initrd address available to the bootloader.
 
 Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
+
 Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
                Introduce relocatable_kernel and kernel_alignment fields.
 
+Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of
+               the boot command line
+
 
 **** MEMORY LAYOUT
 
@@ -133,6 +137,8 @@ Offset      Proto   Name            Meaning
 022C/4 2.03+   initrd_addr_max Highest legal initrd address
 0230/4 2.05+   kernel_alignment Physical addr alignment required for kernel
 0234/1 2.05+   relocatable_kernel Whether kernel is relocatable or not
+0235/3 N/A     pad2            Unused
+0238/4 2.06+   cmdline_size    Maximum size of the kernel command line
 
 (1) For backwards compatibility, if the setup_sects field contains 0, the
     real value is 4.
@@ -233,6 +239,12 @@ filled out, however:
        if your ramdisk is exactly 131072 bytes long and this field is
        0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
 
+  cmdline_size:
+       The maximum size of the command line without the terminating
+       zero. This means that the command line can contain at most
+       cmdline_size characters. With protocol version 2.05 and
+       earlier, the maximum size was 255.
+
 
 **** THE KERNEL COMMAND LINE
 
@@ -241,11 +253,10 @@ loader to communicate with the kernel.  Some of its options are also
 relevant to the boot loader itself, see "special command line options"
 below.
 
-The kernel command line is a null-terminated string currently up to
-255 characters long, plus the final null.  A string that is too long
-will be automatically truncated by the kernel, a boot loader may allow
-a longer command line to be passed to permit future kernels to extend
-this limit.
+The kernel command line is a null-terminated string. The maximum
+length can be retrieved from the field cmdline_size.  Before protocol
+version 2.06, the maximum was 255 characters.  A string that is too
+long will be automatically truncated by the kernel.
 
 If the boot protocol version is 2.02 or later, the address of the
 kernel command line is given by the header field cmd_line_ptr (see
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 84c3bd0..38d7db3 100644 (file)
@@ -64,6 +64,7 @@ parameter is applicable:
        GENERIC_TIME The generic timeofday code is enabled.
        NFS     Appropriate NFS support is enabled.
        OSS     OSS sound support is enabled.
+       PV_OPS  A paravirtualized kernel
        PARIDE  The ParIDE subsystem is enabled.
        PARISC  The PA-RISC architecture is enabled.
        PCI     PCI bus support is enabled.
@@ -695,8 +696,15 @@ and is between 256 and 4096 characters. It is defined in the file
        idebus=         [HW] (E)IDE subsystem - VLB/PCI bus speed
                        See Documentation/ide.txt.
 
-       idle=           [HW]
-                       Format: idle=poll or idle=halt
+       idle=           [X86]
+                       Format: idle=poll or idle=mwait
+                       Poll forces a polling idle loop that can slightly improves the performance
+                       of waking up a idle CPU, but will use a lot of power and make the system
+                       run hot. Not recommended.
+                       idle=mwait. On systems which support MONITOR/MWAIT but the kernel chose
+                       to not use it because it doesn't save as much power as a normal idle
+                       loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
+                       as idle=poll.
 
        ignore_loglevel [KNL]
                        Ignore loglevel setting - this will print /all/
@@ -1157,6 +1165,11 @@ and is between 256 and 4096 characters. It is defined in the file
 
        nomce           [IA-32] Machine Check Exception
 
+       noreplace-paravirt      [IA-32,PV_OPS] Don't patch paravirt_ops
+
+       noreplace-smp   [IA-32,SMP] Don't replace SMP instructions
+                       with UP alternatives
+
        noresidual      [PPC] Don't use residual data on PReP machines.
 
        noresume        [SWSUSP] Disables resume and restores original swap
@@ -1562,6 +1575,9 @@ and is between 256 and 4096 characters. It is defined in the file
        smart2=         [HW]
                        Format: <io1>[,<io2>[,...,<io8>]]
 
+       smp-alt-once    [IA-32,SMP] On a hotplug CPU system, only
+                       attempt to substitute SMP alternatives once at boot.
+
        snd-ad1816a=    [HW,ALSA]
 
        snd-ad1848=     [HW,ALSA]
@@ -1820,6 +1836,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        [USBHID] The interval which mice are to be polled at.
 
        vdso=           [IA-32,SH]
+                       vdso=2: enable compat VDSO (default with COMPAT_VDSO)
                        vdso=1: enable VDSO (default)
                        vdso=0: disable VDSO mapping
 
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 f9717fe..215e3b8 100644 (file)
@@ -62,7 +62,7 @@ static struct resource pxa_spi_nssp_resources[] = {
 
 static struct pxa2xx_spi_master pxa_nssp_master_info = {
        .ssp_type = PXA25x_NSSP, /* Type of SSP */
-       .clock_enable = CKEN9_NSSP, /* NSSP Peripheral clock */
+       .clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */
        .num_chipselect = 1, /* Matches the number of chips attached to NSSP */
        .enable_dma = 1, /* Enables NSSP DMA */
 };
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 85f51e5..6177d88 100644 (file)
@@ -149,7 +149,19 @@ NUMA
 
   numa=noacpi   Don't parse the SRAT table for NUMA setup
 
-  numa=fake=X   Fake X nodes and ignore NUMA setup of the actual machine.
+  numa=fake=CMDLINE
+               If a number, fakes CMDLINE nodes and ignores NUMA setup of the
+               actual machine.  Otherwise, system memory is configured
+               depending on the sizes and coefficients listed.  For example:
+                       numa=fake=2*512,1024,4*256,*128
+               gives two 512M nodes, a 1024M node, four 256M nodes, and the
+               rest split into 128M chunks.  If the last character of CMDLINE
+               is a *, the remaining memory is divided up equally among its
+               coefficient:
+                       numa=fake=2*512,2*
+               gives two 512M nodes and the rest split into two nodes.
+               Otherwise, the remaining system RAM is allocated to an
+               additional node.
 
   numa=hotadd=percent
                Only allow hotadd memory to preallocate page structures upto
diff --git a/Documentation/x86_64/fake-numa-for-cpusets b/Documentation/x86_64/fake-numa-for-cpusets
new file mode 100644 (file)
index 0000000..d1a985c
--- /dev/null
@@ -0,0 +1,66 @@
+Using numa=fake and CPUSets for Resource Management
+Written by David Rientjes <rientjes@cs.washington.edu>
+
+This document describes how the numa=fake x86_64 command-line option can be used
+in conjunction with cpusets for coarse memory management.  Using this feature,
+you can create fake NUMA nodes that represent contiguous chunks of memory and
+assign them to cpusets and their attached tasks.  This is a way of limiting the
+amount of system memory that are available to a certain class of tasks.
+
+For more information on the features of cpusets, see Documentation/cpusets.txt.
+There are a number of different configurations you can use for your needs.  For
+more information on the numa=fake command line option and its various ways of
+configuring fake nodes, see Documentation/x86_64/boot-options.txt.
+
+For the purposes of this introduction, we'll assume a very primitive NUMA
+emulation setup of "numa=fake=4*512,".  This will split our system memory into
+four equal chunks of 512M each that we can now use to assign to cpusets.  As
+you become more familiar with using this combination for resource control,
+you'll determine a better setup to minimize the number of nodes you have to deal
+with.
+
+A machine may be split as follows with "numa=fake=4*512," as reported by dmesg:
+
+       Faking node 0 at 0000000000000000-0000000020000000 (512MB)
+       Faking node 1 at 0000000020000000-0000000040000000 (512MB)
+       Faking node 2 at 0000000040000000-0000000060000000 (512MB)
+       Faking node 3 at 0000000060000000-0000000080000000 (512MB)
+       ...
+       On node 0 totalpages: 130975
+       On node 1 totalpages: 131072
+       On node 2 totalpages: 131072
+       On node 3 totalpages: 131072
+
+Now following the instructions for mounting the cpusets filesystem from
+Documentation/cpusets.txt, you can assign fake nodes (i.e. contiguous memory
+address spaces) to individual cpusets:
+
+       [root@xroads /]# mkdir exampleset
+       [root@xroads /]# mount -t cpuset none exampleset
+       [root@xroads /]# mkdir exampleset/ddset
+       [root@xroads /]# cd exampleset/ddset
+       [root@xroads /exampleset/ddset]# echo 0-1 > cpus
+       [root@xroads /exampleset/ddset]# echo 0-1 > mems
+
+Now this cpuset, 'ddset', will only allowed access to fake nodes 0 and 1 for
+memory allocations (1G).
+
+You can now assign tasks to these cpusets to limit the memory resources
+available to them according to the fake nodes assigned as mems:
+
+       [root@xroads /exampleset/ddset]# echo $$ > tasks
+       [root@xroads /exampleset/ddset]# dd if=/dev/zero of=tmp bs=1024 count=1G
+       [1] 13425
+
+Notice the difference between the system memory usage as reported by
+/proc/meminfo between the restricted cpuset case above and the unrestricted
+case (i.e. running the same 'dd' command without assigning it to a fake NUMA
+cpuset):
+                               Unrestricted    Restricted
+       MemTotal:               3091900 kB      3091900 kB
+       MemFree:                  42113 kB      1513236 kB
+
+This allows for coarse memory management for the tasks you assign to particular
+cpusets.  Since cpusets can form a hierarchy, you can create some pretty
+interesting combinations of use-cases for various classes of tasks for your
+memory management needs.
index 068a6d9..feaeaf6 100644 (file)
@@ -36,7 +36,12 @@ between all CPUs.
 
 check_interval
        How often to poll for corrected machine check errors, in seconds
-       (Note output is hexademical). Default 5 minutes.
+       (Note output is hexademical). Default 5 minutes.  When the poller
+       finds MCEs it triggers an exponential speedup (poll more often) on
+       the polling interval.  When the poller stops finding MCEs, it
+       triggers an exponential backoff (poll less often) on the polling
+       interval. The check_interval variable is both the initial and
+       maximum polling interval.
 
 tolerant
        Tolerance level. When a machine check exception occurs for a non
index af1c792..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
@@ -1605,7 +1617,7 @@ S:        Maintained
 
 HPET:  x86_64
 P:     Andi Kleen and Vojtech Pavlik
-M:     ak@muc.de and vojtech@suse.cz
+M:     andi@firstfloor.org and vojtech@suse.cz
 S:     Maintained
 
 HPET:  ACPI hpet.c
@@ -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
@@ -2623,6 +2652,19 @@ T:       git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
 T:     cvs cvs.parisc-linux.org:/var/cvs/linux-2.6
 S:     Maintained
 
+PARAVIRT_OPS INTERFACE
+P:     Jeremy Fitzhardinge
+M:     jeremy@xensource.com
+P:     Chris Wright
+M:     chrisw@sous-sol.org
+P:     Zachary Amsden
+M:     zach@vmware.com
+P:     Rusty Russell
+M:     rusty@rustcorp.com.au
+L:     virtualization@lists.osdl.org
+L:     linux-kernel@vger.kernel.org
+S:     Supported
+
 PC87360 HARDWARE MONITORING DRIVER
 P:     Jim Cromie
 M:     jim.cromie@gmail.com
@@ -3627,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
@@ -3847,6 +3889,15 @@ M:       eis@baty.hanse.de
 L:     linux-x25@vger.kernel.org
 S:     Maintained
 
+XEN HYPERVISOR INTERFACE
+P:     Jeremy Fitzhardinge
+M:     jeremy@xensource.com
+P:     Chris Wright
+M:     chrisw@sous-sol.org
+L:     virtualization@lists.osdl.org
+L:     xen-devel@lists.xensource.com
+S:     Supported
+
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
 P:     Tim Shimmin, David Chatterton
index 2910c2d..dfe559c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -491,7 +491,7 @@ endif
 include $(srctree)/arch/$(ARCH)/Makefile
 
 ifdef CONFIG_FRAME_POINTER
-CFLAGS         += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
+CFLAGS         += -fno-omit-frame-pointer -fno-optimize-sibling-calls
 else
 CFLAGS         += -fomit-frame-pointer
 endif
index 1d65adf..c00646b 100644 (file)
@@ -98,7 +98,7 @@ extern int end;
 static ulg free_mem_ptr;
 static ulg free_mem_ptr_end;
 
-#define HEAP_SIZE 0x2000
+#define HEAP_SIZE 0x3000
 
 #include "../../../lib/inflate.c"
 
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 4cc44bd..cf1e6fc 100644 (file)
@@ -69,7 +69,7 @@ SECTIONS
   . = ALIGN(8);
   SECURITY_INIT
 
-  . = ALIGN(64);
+  . = ALIGN(8192);
   __per_cpu_start = .;
   .data.percpu : { *(.data.percpu) }
   __per_cpu_end = .;
index e7baca2..0d8fac3 100644 (file)
@@ -29,6 +29,10 @@ config GENERIC_TIME
        bool
        default n
 
+config GENERIC_CLOCKEVENTS
+       bool
+       default n
+
 config MMU
        bool
        default y
@@ -67,6 +71,14 @@ config GENERIC_HARDIRQS
        bool
        default y
 
+config STACKTRACE_SUPPORT
+       bool
+       default y
+
+config LOCKDEP_SUPPORT
+       bool
+       default y
+
 config TRACE_IRQFLAGS_SUPPORT
        bool
        default y
@@ -162,6 +174,8 @@ config ARCH_VERSATILE
        select ARM_AMBA
        select ARM_VIC
        select ICST307
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        help
          This enables support for ARM Ltd Versatile board.
 
@@ -255,6 +269,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.
 
@@ -262,6 +277,7 @@ config ARCH_IXP4XX
        bool "IXP4xx-based"
        depends on MMU
        select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        help
          Support for Intel's IXP4XX (XScale) family of processors.
 
@@ -363,6 +379,7 @@ config ARCH_LH7A40X
 config ARCH_OMAP
        bool "TI OMAP"
        select GENERIC_GPIO
+       select GENERIC_TIME
        help
          Support for TI's OMAP platform (OMAP1 and OMAP2).
 
@@ -513,6 +530,8 @@ endmenu
 
 menu "Kernel Features"
 
+source "kernel/time/Kconfig"
+
 config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
        depends on EXPERIMENTAL && REALVIEW_MPCORE
@@ -572,6 +591,7 @@ config PREEMPT
 
 config NO_IDLE_HZ
        bool "Dynamic tick timer"
+       depends on !GENERIC_CLOCKEVENTS
        help
          Select this option if you want to disable continuous timer ticks
          and have them programmed to occur as required. This option saves
@@ -669,6 +689,7 @@ config LEDS_TIMER
        bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
                            MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
        depends on LEDS
+       depends on !GENERIC_CLOCKEVENTS
        default y if ARCH_EBSA110
        help
          If you say Y here, one of the system LEDs (the green one on the
index d68b9ac..11782cc 100644 (file)
                cmp     r7, r3
                beq     99f
 
+               @ picotux 200 : 963
+               mov     r3,     #(MACH_TYPE_PICOTUX2XX & 0xff)
+               orr     r3, r3, #(MACH_TYPE_PICOTUX2XX & 0xff00)
+               cmp     r7, r3
+               beq     99f
+
                @ Ajeco 1ARM : 1075
                mov     r3,     #(MACH_TYPE_ONEARM & 0xff)
                orr     r3, r3, #(MACH_TYPE_ONEARM & 0xff00)
index 283891c..9b44402 100644 (file)
@@ -239,7 +239,7 @@ extern int end;
 static ulg free_mem_ptr;
 static ulg free_mem_ptr_end;
 
-#define HEAP_SIZE 0x2000
+#define HEAP_SIZE 0x3000
 
 #include "../../../../lib/inflate.c"
 
index fe3f059..798bbfc 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
index ba2e629..79a8206 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
index fabf74c..db850a5 100644 (file)
@@ -117,11 +117,13 @@ CONFIG_ARCH_ADI_COYOTE=y
 CONFIG_ARCH_IXDP425=y
 CONFIG_MACH_IXDPG425=y
 CONFIG_MACH_IXDP465=y
+CONFIG_MACH_KIXRP435=y
 CONFIG_ARCH_IXCDP1100=y
 CONFIG_ARCH_PRPMC1100=y
 CONFIG_MACH_NAS100D=y
 CONFIG_ARCH_IXDP4XX=y
 CONFIG_CPU_IXP46X=y
+CONFIG_CPU_IXP43X=y
 # CONFIG_MACH_GTWX5715 is not set
 
 #
diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig
new file mode 100644 (file)
index 0000000..339c489
--- /dev/null
@@ -0,0 +1,1386 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc4
+# Wed Mar 28 16:19:50 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+CONFIG_ARCH_AT91RM9200=y
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+# CONFIG_ARCH_AT91SAM9263 is not set
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_MACH_ONEARM is not set
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_ATEB9200 is not set
+# CONFIG_MACH_KB9200 is not set
+CONFIG_MACH_PICOTUX2XX=y
+# CONFIG_MACH_KAFA is not set
+
+#
+# AT91 Board Options
+#
+
+#
+# AT91 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91RM9200_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=m
+CONFIG_I2C_ISA=m
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+# CONFIG_SENSORS_ABITUGURU is not set
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+CONFIG_SENSORS_SMSC47B397=m
+# CONFIG_SENSORS_VT1211 is not set
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91RM9200=m
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="utf-8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index bb28087..593b565 100644 (file)
@@ -7,8 +7,8 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
 # Object file lists.
 
 obj-y          := compat.o entry-armv.o entry-common.o irq.o \
-                  process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
-                  time.o traps.o
+                  process.o ptrace.o semaphore.o setup.o signal.o \
+                  sys_arm.o stacktrace.o time.o traps.o
 
 obj-$(CONFIG_ISA_DMA_API)      += dma.o
 obj-$(CONFIG_ARCH_ACORN)       += ecard.o 
index f1c0fb9..bdbd7da 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/kthread.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
@@ -50,6 +51,8 @@
 #include <asm/mach/irq.h>
 #include <asm/tlbflush.h>
 
+#include "ecard.h"
+
 #ifndef CONFIG_ARCH_RPC
 #define HAVE_EXPMASK
 #endif
@@ -123,7 +126,7 @@ static void ecard_task_reset(struct ecard_request *req)
 
        res = ec->slot_no == 8
                ? &ec->resource[ECARD_RES_MEMC]
-               : ec->type == ECARD_EASI
+               : ec->easi
                  ? &ec->resource[ECARD_RES_EASI]
                  : &ec->resource[ECARD_RES_IOCSYNC];
 
@@ -178,7 +181,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
                        index += 1;
                }
        } else {
-               unsigned long base = (ec->type == ECARD_EASI
+               unsigned long base = (ec->easi
                         ? &ec->resource[ECARD_RES_EASI]
                         : &ec->resource[ECARD_RES_IOCSYNC])->start;
                void __iomem *pbase = (void __iomem *)base;
@@ -263,8 +266,6 @@ static int ecard_init_mm(void)
 static int
 ecard_task(void * unused)
 {
-       daemonize("kecardd");
-
        /*
         * Allocate a mm.  We're not a lazy-TLB kernel task since we need
         * to set page table entries where the user space would be.  Note
@@ -727,7 +728,7 @@ static int ecard_prints(char *buffer, ecard_t *ec)
        char *start = buffer;
 
        buffer += sprintf(buffer, "  %d: %s ", ec->slot_no,
-                         ec->type == ECARD_EASI ? "EASI" : "    ");
+                         ec->easi ? "EASI" : "    ");
 
        if (ec->cid.id == 0) {
                struct in_chunk_dir incd;
@@ -814,7 +815,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
        }
 
        ec->slot_no = slot;
-       ec->type = type;
+       ec->easi = type == ECARD_EASI;
        ec->irq = NO_IRQ;
        ec->fiq = NO_IRQ;
        ec->dma = NO_DMA;
@@ -825,6 +826,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
        ec->dev.bus = &ecard_bus_type;
        ec->dev.dma_mask = &ec->dma_mask;
        ec->dma_mask = (u64)0xffffffff;
+       ec->dev.coherent_dma_mask = ec->dma_mask;
 
        if (slot < 4) {
                ec_set_resource(ec, ECARD_RES_MEMC,
@@ -907,7 +909,7 @@ static ssize_t ecard_show_device(struct device *dev, struct device_attribute *at
 static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct expansion_card *ec = ECARD_DEV(dev);
-       return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
+       return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC");
 }
 
 static struct device_attribute ecard_dev_attrs[] = {
@@ -1058,13 +1060,14 @@ ecard_probe(int slot, card_type_t type)
  */
 static int __init ecard_init(void)
 {
-       int slot, irqhw, ret;
-
-       ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
-       if (ret < 0) {
-               printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n",
-                      ret);
-               return ret;
+       struct task_struct *task;
+       int slot, irqhw;
+
+       task = kthread_run(ecard_task, NULL, "kecardd");
+       if (IS_ERR(task)) {
+               printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n",
+                      PTR_ERR(task));
+               return PTR_ERR(task);
        }
 
        printk("Probing expansion cards\n");
diff --git a/arch/arm/kernel/ecard.h b/arch/arm/kernel/ecard.h
new file mode 100644 (file)
index 0000000..d7c2dac
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  ecard.h
+ *
+ *  Copyright 2007 Russell King
+ *
+ * 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.
+ */
+
+/* Definitions internal to ecard.c - for it's use only!!
+ *
+ * External expansion card header as read from the card
+ */
+struct ex_ecid {
+       unsigned char   r_irq:1;
+       unsigned char   r_zero:1;
+       unsigned char   r_fiq:1;
+       unsigned char   r_id:4;
+       unsigned char   r_a:1;
+
+       unsigned char   r_cd:1;
+       unsigned char   r_is:1;
+       unsigned char   r_w:2;
+       unsigned char   r_r1:4;
+
+       unsigned char   r_r2:8;
+
+       unsigned char   r_prod[2];
+
+       unsigned char   r_manu[2];
+
+       unsigned char   r_country;
+
+       unsigned char   r_fiqmask;
+       unsigned char   r_fiqoff[3];
+
+       unsigned char   r_irqmask;
+       unsigned char   r_irqoff[3];
+};
+
+/*
+ * Chunk directory entry as read from the card
+ */
+struct ex_chunk_dir {
+       unsigned char r_id;
+       unsigned char r_len[3];
+       unsigned long r_start;
+       union {
+               char string[256];
+               char data[1];
+       } d;
+#define c_id(x)                ((x)->r_id)
+#define c_len(x)       ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16))
+#define c_start(x)     ((x)->r_start)
+};
index 66db0a9..1d35eda 100644 (file)
@@ -257,7 +257,9 @@ __create_page_tables:
         * Map some ram to cover our .data and .bss areas.
         */
        orr     r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
+       .if     (KERNEL_RAM_PADDR & 0x00f00000)
        orr     r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
+       .endif
        add     r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> 18
        str     r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
        ldr     r6, =(_end - 1)
@@ -274,7 +276,9 @@ __create_page_tables:
         */
        add     r0, r4, #PAGE_OFFSET >> 18
        orr     r6, r7, #(PHYS_OFFSET & 0xff000000)
-       orr     r6, r6, #(PHYS_OFFSET & 0x00e00000)
+       .if     (PHYS_OFFSET & 0x00f00000)
+       orr     r6, r6, #(PHYS_OFFSET & 0x00f00000)
+       .endif
        str     r6, [r0]
 
 #ifdef CONFIG_DEBUG_LL
index e101846..11dcd52 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
@@ -109,7 +108,7 @@ static struct irq_desc bad_irq_desc = {
  * come via this function.  Instead, they should provide their
  * own 'handler'
  */
-asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
        struct irq_desc *desc = irq_desc + irq;
index 782af3c..5d6e652 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
@@ -28,6 +27,7 @@
 #include <linux/cpu.h>
 #include <linux/elfcore.h>
 #include <linux/pm.h>
+#include <linux/tick.h>
 
 #include <asm/leds.h>
 #include <asm/processor.h>
@@ -160,9 +160,11 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
                leds_event(led_idle_start);
+               tick_nohz_stop_sched_tick();
                while (!need_resched())
                        idle();
                leds_event(led_idle_end);
+               tick_nohz_restart_sched_tick();
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
index 9254ba2..13af400 100644 (file)
@@ -457,13 +457,10 @@ void ptrace_cancel_bpt(struct task_struct *child)
 
 /*
  * Called by kernel/ptrace.c when detaching..
- *
- * Make sure the single step bit is not set.
  */
 void ptrace_disable(struct task_struct *child)
 {
-       child->ptrace &= ~PT_SINGLESTEP;
-       ptrace_cancel_bpt(child);
+       single_step_disable(child);
 }
 
 /*
@@ -712,9 +709,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        else
                                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                        child->exit_code = data;
-                       /* make sure single-step breakpoint is gone. */
-                       child->ptrace &= ~PT_SINGLESTEP;
-                       ptrace_cancel_bpt(child);
+                       single_step_disable(child);
                        wake_up_process(child);
                        ret = 0;
                        break;
@@ -725,9 +720,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                 * exit.
                 */
                case PTRACE_KILL:
-                       /* make sure single-step breakpoint is gone. */
-                       child->ptrace &= ~PT_SINGLESTEP;
-                       ptrace_cancel_bpt(child);
+                       single_step_disable(child);
                        if (child->exit_state != EXIT_ZOMBIE) {
                                child->exit_code = SIGKILL;
                                wake_up_process(child);
@@ -742,7 +735,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        ret = -EIO;
                        if (!valid_signal(data))
                                break;
-                       child->ptrace |= PT_SINGLESTEP;
+                       single_step_enable(child);
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                        child->exit_code = data;
                        /* give it a chance to run. */
@@ -786,8 +779,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        break;
 
                case PTRACE_SET_SYSCALL:
+                       task_thread_info(child)->syscall = data;
                        ret = 0;
-                       child->ptrace_message = data;
                        break;
 
 #ifdef CONFIG_CRUNCH
@@ -824,7 +817,7 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
        ip = regs->ARM_ip;
        regs->ARM_ip = why;
 
-       current->ptrace_message = scno;
+       current_thread_info()->syscall = scno;
 
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
@@ -841,5 +834,5 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
        }
        regs->ARM_ip = ip;
 
-       return current->ptrace_message;
+       return current_thread_info()->syscall;
 }
index f7cad13..def3b61 100644 (file)
@@ -7,6 +7,45 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/ptrace.h>
+
 extern void ptrace_cancel_bpt(struct task_struct *);
 extern void ptrace_set_bpt(struct task_struct *);
 extern void ptrace_break(struct task_struct *, struct pt_regs *);
+
+/*
+ * make sure single-step breakpoint is gone.
+ */
+static inline void single_step_disable(struct task_struct *task)
+{
+       task->ptrace &= ~PT_SINGLESTEP;
+       ptrace_cancel_bpt(task);
+}
+
+static inline void single_step_enable(struct task_struct *task)
+{
+       task->ptrace |= PT_SINGLESTEP;
+}
+
+/*
+ * Send SIGTRAP if we're single-stepping
+ */
+static inline void single_step_trap(struct task_struct *task)
+{
+       if (task->ptrace & PT_SINGLESTEP) {
+               ptrace_cancel_bpt(task);
+               send_sig(SIGTRAP, task, 1);
+       }
+}
+
+static inline void single_step_clear(struct task_struct *task)
+{
+       if (task->ptrace & PT_SINGLESTEP)
+               ptrace_cancel_bpt(task);
+}
+
+static inline void single_step_set(struct task_struct *task)
+{
+       if (task->ptrace & PT_SINGLESTEP)
+               ptrace_set_bpt(task);
+}
index 3843d3b..54cdf1a 100644 (file)
@@ -9,7 +9,6 @@
  */
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/ptrace.h>
 #include <linux/personality.h>
 #include <linux/freezer.h>
 
@@ -285,11 +284,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
        if (restore_sigframe(regs, frame))
                goto badframe;
 
-       /* Send SIGTRAP if we're single-stepping */
-       if (current->ptrace & PT_SINGLESTEP) {
-               ptrace_cancel_bpt(current);
-               send_sig(SIGTRAP, current, 1);
-       }
+       single_step_trap(current);
 
        return regs->ARM_r0;
 
@@ -324,11 +319,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
        if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
                goto badframe;
 
-       /* Send SIGTRAP if we're single-stepping */
-       if (current->ptrace & PT_SINGLESTEP) {
-               ptrace_cancel_bpt(current);
-               send_sig(SIGTRAP, current, 1);
-       }
+       single_step_trap(current);
 
        return regs->ARM_r0;
 
@@ -644,14 +635,12 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
        if (try_to_freeze())
                goto no_signal;
 
-       if (current->ptrace & PT_SINGLESTEP)
-               ptrace_cancel_bpt(current);
+       single_step_clear(current);
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                handle_signal(signr, &ka, &info, oldset, regs, syscall);
-               if (current->ptrace & PT_SINGLESTEP)
-                       ptrace_set_bpt(current);
+               single_step_set(current);
                return 1;
        }
 
@@ -705,8 +694,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                        restart_syscall(regs);
                }
        }
-       if (current->ptrace & PT_SINGLESTEP)
-               ptrace_set_bpt(current);
+       single_step_set(current);
        return 0;
 }
 
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..77ef35e
--- /dev/null
@@ -0,0 +1,73 @@
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+
+#include "stacktrace.h"
+
+int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
+                   int (*fn)(struct stackframe *, void *), void *data)
+{
+       struct stackframe *frame;
+
+       do {
+               /*
+                * Check current frame pointer is within bounds
+                */
+               if ((fp - 12) < low || fp + 4 >= high)
+                       break;
+
+               frame = (struct stackframe *)(fp - 12);
+
+               if (fn(frame, data))
+                       break;
+
+               /*
+                * Update the low bound - the next frame must always
+                * be at a higher address than the current frame.
+                */
+               low = fp + 4;
+               fp = frame->fp;
+       } while (fp);
+
+       return 0;
+}
+
+#ifdef CONFIG_STACKTRACE
+struct stack_trace_data {
+       struct stack_trace *trace;
+       unsigned int skip;
+};
+
+static int save_trace(struct stackframe *frame, void *d)
+{
+       struct stack_trace_data *data = d;
+       struct stack_trace *trace = data->trace;
+
+       if (data->skip) {
+               data->skip--;
+               return 0;
+       }
+
+       trace->entries[trace->nr_entries++] = frame->lr;
+
+       return trace->nr_entries >= trace->max_entries;
+}
+
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+       struct stack_trace_data data;
+       unsigned long fp, base;
+
+       data.trace = trace;
+       data.skip = trace->skip;
+
+       if (task) {
+               base = (unsigned long)task_stack_page(task);
+               fp = 0; /* FIXME */
+       } else {
+               base = (unsigned long)task_stack_page(current);
+               asm("mov %0, fp" : "=r" (fp));
+       }
+
+       walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
+}
+#endif
diff --git a/arch/arm/kernel/stacktrace.h b/arch/arm/kernel/stacktrace.h
new file mode 100644 (file)
index 0000000..e9fd20c
--- /dev/null
@@ -0,0 +1,9 @@
+struct stackframe {
+       unsigned long fp;
+       unsigned long sp;
+       unsigned long lr;
+       unsigned long pc;
+};
+
+int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
+                   int (*fn)(struct stackframe *, void *), void *data);
index f61decb..d0540e4 100644 (file)
@@ -327,6 +327,7 @@ void restore_time_delta(struct timespec *delta, struct timespec *rtc)
 }
 EXPORT_SYMBOL(restore_time_delta);
 
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * Kernel system timer support.
  */
@@ -340,8 +341,9 @@ void timer_tick(void)
        update_process_times(user_mode(get_irq_regs()));
 #endif
 }
+#endif
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
 static int timer_suspend(struct sys_device *dev, pm_message_t state)
 {
        struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
index 2409560..f05e66b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/signal.h>
 #include <linux/spinlock.h>
 #include <linux/personality.h>
-#include <linux/ptrace.h>
 #include <linux/kallsyms.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -45,7 +44,18 @@ static int __init user_debug_setup(char *str)
 __setup("user_debug=", user_debug_setup);
 #endif
 
-void dump_backtrace_entry(unsigned long where, unsigned long from)
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
+
+static inline int in_exception_text(unsigned long ptr)
+{
+       extern char __exception_text_start[];
+       extern char __exception_text_end[];
+
+       return ptr >= (unsigned long)&__exception_text_start &&
+              ptr < (unsigned long)&__exception_text_end;
+}
+
+void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
 #ifdef CONFIG_KALLSYMS
        printk("[<%08lx>] ", where);
@@ -55,6 +65,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from)
 #else
        printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
 #endif
+
+       if (in_exception_text(where))
+               dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
 }
 
 /*
@@ -266,13 +279,14 @@ void unregister_undef_hook(struct undef_hook *hook)
        spin_unlock_irqrestore(&undef_lock, flags);
 }
 
-asmlinkage void do_undefinstr(struct pt_regs *regs)
+asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 {
        unsigned int correction = thumb_mode(regs) ? 2 : 4;
        unsigned int instr;
        struct undef_hook *hook;
        siginfo_t info;
        void __user *pc;
+       unsigned long flags;
 
        /*
         * According to the ARM ARM, PC is 2 or 4 bytes ahead,
@@ -291,7 +305,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
                get_user(instr, (u32 __user *)pc);
        }
 
-       spin_lock_irq(&undef_lock);
+       spin_lock_irqsave(&undef_lock, flags);
        list_for_each_entry(hook, &undef_hook, node) {
                if ((instr & hook->instr_mask) == hook->instr_val &&
                    (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
@@ -301,7 +315,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
                        }
                }
        }
-       spin_unlock_irq(&undef_lock);
+       spin_unlock_irqrestore(&undef_lock, flags);
 
 #ifdef CONFIG_DEBUG_USER
        if (user_debug & UDBG_UNDEFINED) {
index ddbdad4..6be6729 100644 (file)
@@ -59,7 +59,7 @@ SECTIONS
                        usr/built-in.o(.init.ramfs)
                __initramfs_end = .;
 #endif
-               . = ALIGN(64);
+               . = ALIGN(4096);
                __per_cpu_start = .;
                        *(.data.percpu)
                __per_cpu_end = .;
@@ -83,6 +83,9 @@ SECTIONS
 
        .text : {                       /* Real text segment            */
                _text = .;              /* Text and read-only data      */
+                       __exception_text_start = .;
+                       *(.exception.text)
+                       __exception_text_end = .;
                        *(.text)
                        SCHED_TEXT
                        LOCK_TEXT
index 7423008..84dc890 100644 (file)
@@ -17,8 +17,8 @@
 @ fp is 0 or stack frame
 
 #define frame  r4
-#define next   r5
-#define save   r6
+#define sv_fp  r5
+#define sv_pc  r6
 #define mask   r7
 #define offset r8
 
@@ -31,108 +31,106 @@ ENTRY(c_backtrace)
 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
                mov     pc, lr
 #else
-
                stmfd   sp!, {r4 - r8, lr}      @ Save an extra register so we have a location...
-               tst     r1, #0x10               @ 26 or 32-bit?
-               moveq   mask, #0xfc000003
-               movne   mask, #0
-               tst     mask, r0
-               movne   r0, #0
-               movs    frame, r0
-1:             moveq   r0, #-2
-               ldmeqfd sp!, {r4 - r8, pc}
-
-2:             stmfd   sp!, {pc}               @ calculate offset of PC in STMIA instruction
-               ldr     r0, [sp], #4
-               adr     r1, 2b - 4
+               movs    frame, r0               @ if frame pointer is zero
+               beq     no_frame                @ we have no stack frames
+
+               tst     r1, #0x10               @ 26 or 32-bit mode?
+               moveq   mask, #0xfc000003       @ mask for 26-bit
+               movne   mask, #0                @ mask for 32-bit
+
+1:             stmfd   sp!, {pc}               @ calculate offset of PC stored
+               ldr     r0, [sp], #4            @ by stmfd for this CPU
+               adr     r1, 1b
                sub     offset, r0, r1
 
-3:             tst     frame, mask             @ Check for address exceptions...
-               bne     1b
+/*
+ * Stack frame layout:
+ *             optionally saved caller registers (r4 - r10)
+ *             saved fp
+ *             saved sp
+ *             saved lr
+ *    frame => saved pc
+ *             optionally saved arguments (r0 - r3)
+ * saved sp => <next word>
+ *
+ * Functions start with the following code sequence:
+ *                  mov   ip, sp
+ *                  stmfd sp!, {r0 - r3} (optional)
+ * corrected pc =>  stmfd sp!, {..., fp, ip, lr, pc}
+ */
+for_each_frame:        tst     frame, mask             @ Check for address exceptions
+               bne     no_frame
+
+1001:          ldr     sv_pc, [frame, #0]      @ get saved pc
+1002:          ldr     sv_fp, [frame, #-12]    @ get saved fp
 
-1001:          ldr     next, [frame, #-12]     @ get fp
-1002:          ldr     r2, [frame, #-4]        @ get lr
-1003:          ldr     r3, [frame, #0]         @ get pc
-               sub     save, r3, offset        @ Correct PC for prefetching
-               bic     save, save, mask
-1004:          ldr     r1, [save, #0]          @ get instruction at function
-               mov     r1, r1, lsr #10
-               ldr     r3, .Ldsi+4
-               teq     r1, r3
-               subeq   save, save, #4
-               mov     r0, save
-               bic     r1, r2, mask
+               sub     sv_pc, sv_pc, offset    @ Correct PC for prefetching
+               bic     sv_pc, sv_pc, mask      @ mask PC/LR for the mode
+
+1003:          ldr     r2, [sv_pc, #-4]        @ if stmfd sp!, {args} exists,
+               ldr     r3, .Ldsi+4             @ adjust saved 'pc' back one
+               teq     r3, r2, lsr #10         @ instruction
+               subne   r0, sv_pc, #4           @ allow for mov
+               subeq   r0, sv_pc, #8           @ allow for mov + stmia
+
+               ldr     r1, [frame, #-4]        @ get saved lr
+               mov     r2, frame
+               bic     r1, r1, mask            @ mask PC/LR for the mode
                bl      dump_backtrace_entry
 
-               ldr     r0, [frame, #-8]        @ get sp
-               sub     r0, r0, #4
-1005:          ldr     r1, [save, #4]          @ get instruction at function+4
-               mov     r3, r1, lsr #10
-               ldr     r2, .Ldsi+4
-               teq     r3, r2                  @ Check for stmia sp!, {args}
-               addeq   save, save, #4          @ next instruction
-               bleq    .Ldumpstm
-
-               sub     r0, frame, #16
-1006:          ldr     r1, [save, #4]          @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
-               mov     r3, r1, lsr #10
-               ldr     r2, .Ldsi
-               teq     r3, r2
-               bleq    .Ldumpstm
-
-               /*
-                * A zero next framepointer means we're done.
-                */
-               teq     next, #0
-               ldmeqfd sp!, {r4 - r8, pc}
-
-               /*
-                * The next framepointer must be above the
-                * current framepointer.
-                */
-               cmp     next, frame
-               mov     frame, next
-               bhi     3b
-               b       1007f
+               ldr     r1, [sv_pc, #-4]        @ if stmfd sp!, {args} exists,
+               ldr     r3, .Ldsi+4
+               teq     r3, r1, lsr #10
+               ldreq   r0, [frame, #-8]        @ get sp
+               subeq   r0, r0, #4              @ point at the last arg
+               bleq    .Ldumpstm               @ dump saved registers
 
-/*
- * Fixup for LDMDB.  Note that this must not be in the fixup section.
- */
-1007:          ldr     r0, =.Lbad
+1004:          ldr     r1, [sv_pc, #0]         @ if stmfd sp!, {..., fp, ip, lr, pc}
+               ldr     r3, .Ldsi               @ instruction exists,
+               teq     r3, r1, lsr #10
+               subeq   r0, frame, #16
+               bleq    .Ldumpstm               @ dump saved registers
+
+               teq     sv_fp, #0               @ zero saved fp means
+               beq     no_frame                @ no further frames
+
+               cmp     sv_fp, frame            @ next frame must be
+               mov     frame, sv_fp            @ above the current frame
+               bhi     for_each_frame
+
+1006:          adr     r0, .Lbad
                mov     r1, frame
                bl      printk
-               ldmfd   sp!, {r4 - r8, pc}
-               .ltorg
+no_frame:      ldmfd   sp!, {r4 - r8, pc}
                
                .section __ex_table,"a"
                .align  3
-               .long   1001b, 1007b
-               .long   1002b, 1007b
-               .long   1003b, 1007b
-               .long   1004b, 1007b
-               .long   1005b, 1007b
-               .long   1006b, 1007b
+               .long   1001b, 1006b
+               .long   1002b, 1006b
+               .long   1003b, 1006b
+               .long   1004b, 1006b
                .previous
 
 #define instr r4
 #define reg   r5
 #define stack r6
 
-.Ldumpstm:     stmfd   sp!, {instr, reg, stack, r7, r8, lr}
+.Ldumpstm:     stmfd   sp!, {instr, reg, stack, r7, lr}
                mov     stack, r0
                mov     instr, r1
-               mov     reg, #9
+               mov     reg, #10
                mov     r7, #0
 1:             mov     r3, #1
                tst     instr, r3, lsl reg
                beq     2f
                add     r7, r7, #1
-               teq     r7, #4
-               moveq   r7, #0
-               moveq   r3, #'\n'
-               movne   r3, #' '
-               ldr     r2, [stack], #-4
-               mov     r1, reg
+               teq     r7, #6
+               moveq   r7, #1
+               moveq   r1, #'\n'
+               movne   r1, #' '
+               ldr     r3, [stack], #-4
+               mov     r2, reg
                adr     r0, .Lfp
                bl      printk
 2:             subs    reg, reg, #1
@@ -140,14 +138,13 @@ ENTRY(c_backtrace)
                teq     r7, #0
                adrne   r0, .Lcr
                blne    printk
-               mov     r0, stack
-               ldmfd   sp!, {instr, reg, stack, r7, r8, pc}
+               ldmfd   sp!, {instr, reg, stack, r7, pc}
 
-.Lfp:          .asciz  " r%d = %08X%c"
+.Lfp:          .asciz  "%cr%d:%08x"
 .Lcr:          .asciz  "\n"
 .Lbad:         .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
                .align
-.Ldsi:         .word   0x00e92dd8 >> 2
-               .word   0x00e92d00 >> 2
+.Ldsi:         .word   0xe92dd800 >> 10        @ stmfd sp!, {... fp, ip, lr, pc}
+               .word   0xe92d0000 >> 10        @ stmfd sp!, {}
 
 #endif
index c03ea8e..1dd8ea4 100644 (file)
@@ -26,8 +26,6 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000.
  * Note also that it is intended that __get_user_bad is not global.
  */
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
 #include <asm/errno.h>
 
        .global __get_user_1
index 4593e9c..8620afe 100644 (file)
@@ -26,8 +26,6 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000
  * Note also that it is intended that __put_user_bad is not global.
  */
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
 #include <asm/errno.h>
 
        .global __put_user_1
index bf0d962..e238ad8 100644 (file)
@@ -81,6 +81,13 @@ config MACH_KB9200
          Select this if you are using KwikByte's KB920x board.
          <http://kwikbyte.com/KB9202_description_new.htm>
 
+config MACH_PICOTUX2XX
+       bool "picotux 200"
+       depends on ARCH_AT91RM9200
+       help
+         Select this if you are using a picotux 200.
+         <http://www.picotux.com/>
+
 config MACH_KAFA
        bool "Sperry-Sun KAFA board"
        depends on ARCH_AT91RM9200
index 05de6cd..a412ae1 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_MACH_CARMEVA)    += board-carmeva.o
 obj-$(CONFIG_MACH_KB9200)      += board-kb9202.o
 obj-$(CONFIG_MACH_ATEB9200)    += board-eb9200.o
 obj-$(CONFIG_MACH_KAFA)                += board-kafa.o
+obj-$(CONFIG_MACH_PICOTUX2XX)  += board-picotux200.o
 
 # AT91SAM9260 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
index 2ddcdd6..2cad2bf 100644 (file)
@@ -117,6 +117,21 @@ static struct clk pioD_clk = {
        .pmc_mask       = 1 << AT91RM9200_ID_PIOD,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk ssc0_clk = {
+       .name           = "ssc0_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_SSC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc1_clk = {
+       .name           = "ssc1_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_SSC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc2_clk = {
+       .name           = "ssc2_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_SSC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk tc0_clk = {
        .name           = "tc0_clk",
        .pmc_mask       = 1 << AT91RM9200_ID_TC0,
@@ -161,7 +176,9 @@ static struct clk *periph_clocks[] __initdata = {
        &udc_clk,
        &twi_clk,
        &spi_clk,
-       // ssc 0 .. ssc2
+       &ssc0_clk,
+       &ssc1_clk,
+       &ssc2_clk,
        &tc0_clk,
        &tc1_clk,
        &tc2_clk,
index 6ea41d8..e47381e 100644 (file)
@@ -119,6 +119,11 @@ static struct clk spi1_clk = {
        .pmc_mask       = 1 << AT91SAM9260_ID_SPI1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk ssc_clk = {
+       .name           = "ssc_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_SSC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk tc0_clk = {
        .name           = "tc0_clk",
        .pmc_mask       = 1 << AT91SAM9260_ID_TC0,
@@ -193,7 +198,7 @@ static struct clk *periph_clocks[] __initdata = {
        &twi_clk,
        &spi0_clk,
        &spi1_clk,
-       // ssc
+       &ssc_clk,
        &tc0_clk,
        &tc1_clk,
        &tc2_clk,
index 784d1e6..dfe8c39 100644 (file)
@@ -97,6 +97,21 @@ static struct clk spi1_clk = {
        .pmc_mask       = 1 << AT91SAM9261_ID_SPI1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk ssc0_clk = {
+       .name           = "ssc0_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_SSC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc1_clk = {
+       .name           = "ssc1_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_SSC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc2_clk = {
+       .name           = "ssc2_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_SSC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk tc0_clk = {
        .name           = "tc0_clk",
        .pmc_mask       = 1 << AT91SAM9261_ID_TC0,
@@ -135,7 +150,9 @@ static struct clk *periph_clocks[] __initdata = {
        &twi_clk,
        &spi0_clk,
        &spi1_clk,
-       // ssc 0 .. ssc2
+       &ssc0_clk,
+       &ssc1_clk,
+       &ssc2_clk,
        &tc0_clk,
        &tc1_clk,
        &tc2_clk,
index e150476..8e78199 100644 (file)
@@ -430,9 +430,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
  *  LCD Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
 static u64 lcdc_dmamask = 0xffffffffUL;
-static struct at91fb_info lcdc_data;
+static struct atmel_lcdfb_info lcdc_data;
 
 static struct resource lcdc_resources[] = {
        [0] = {
@@ -455,7 +455,7 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-       .name           = "at91-fb",
+       .name           = "atmel_lcdfb",
        .id             = 0,
        .dev            = {
                                .dma_mask               = &lcdc_dmamask,
@@ -466,7 +466,7 @@ static struct platform_device at91_lcdc_device = {
        .num_resources  = ARRAY_SIZE(lcdc_resources),
 };
 
-void __init at91_add_device_lcdc(struct at91fb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 {
        if (!data) {
                return;
@@ -499,7 +499,7 @@ void __init at91_add_device_lcdc(struct at91fb_info *data)
        platform_device_register(&at91_lcdc_device);
 }
 #else
-void __init at91_add_device_lcdc(struct at91fb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
 #endif
 
 
index 0e89a7f..00e27b1 100644 (file)
@@ -87,6 +87,11 @@ static struct clk mmc1_clk = {
        .pmc_mask       = 1 << AT91SAM9263_ID_MCI1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk can_clk = {
+       .name           = "can_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_CAN,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk twi_clk = {
        .name           = "twi_clk",
        .pmc_mask       = 1 << AT91SAM9263_ID_TWI,
@@ -102,16 +107,46 @@ static struct clk spi1_clk = {
        .pmc_mask       = 1 << AT91SAM9263_ID_SPI1,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk ssc0_clk = {
+       .name           = "ssc0_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_SSC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc1_clk = {
+       .name           = "ssc1_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_SSC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ac97_clk = {
+       .name           = "ac97_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_AC97C,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk tcb_clk = {
        .name           = "tcb_clk",
        .pmc_mask       = 1 << AT91SAM9263_ID_TCB,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk pwmc_clk = {
+       .name           = "pwmc_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_PWMC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk macb_clk = {
        .name           = "macb_clk",
        .pmc_mask       = 1 << AT91SAM9263_ID_EMAC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
+static struct clk dma_clk = {
+       .name           = "dma_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_DMA,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twodge_clk = {
+       .name           = "2dge_clk",
+       .pmc_mask       = 1 << AT91SAM9263_ID_2DGE,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
 static struct clk udc_clk = {
        .name           = "udc_clk",
        .pmc_mask       = 1 << AT91SAM9263_ID_UDP,
@@ -142,20 +177,21 @@ static struct clk *periph_clocks[] __initdata = {
        &usart2_clk,
        &mmc0_clk,
        &mmc1_clk,
-       // can
+       &can_clk,
        &twi_clk,
        &spi0_clk,
        &spi1_clk,
-       // ssc0 .. ssc1
-       // ac97
+       &ssc0_clk,
+       &ssc1_clk,
+       &ac97_clk,
        &tcb_clk,
-       // pwmc
+       &pwmc_clk,
        &macb_clk,
-       // 2dge
+       &twodge_clk,
        &udc_clk,
        &isi_clk,
        &lcdc_clk,
-       // dma
+       &dma_clk,
        &ohci_clk,
        // irq0 .. irq1
 };
index b77121f..2b2e18a 100644 (file)
@@ -572,6 +572,130 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
 #endif
 
 
+/* --------------------------------------------------------------------
+ *  AC97
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SND_AT91_AC97) || defined(CONFIG_SND_AT91_AC97_MODULE)
+static u64 ac97_dmamask = 0xffffffffUL;
+static struct atmel_ac97_data ac97_data;
+
+static struct resource ac97_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_BASE_AC97C,
+               .end    = AT91SAM9263_BASE_AC97C + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_AC97C,
+               .end    = AT91SAM9263_ID_AC97C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9263_ac97_device = {
+       .name           = "ac97c",
+       .id             = 1,
+       .dev            = {
+                               .dma_mask               = &ac97_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &ac97_data,
+       },
+       .resource       = ac97_resources,
+       .num_resources  = ARRAY_SIZE(ac97_resources),
+};
+
+void __init at91_add_device_ac97(struct atmel_ac97_data *data)
+{
+       if (!data)
+               return;
+
+       at91_set_A_periph(AT91_PIN_PB0, 0);     /* AC97FS */
+       at91_set_A_periph(AT91_PIN_PB1, 0);     /* AC97CK */
+       at91_set_A_periph(AT91_PIN_PB2, 0);     /* AC97TX */
+       at91_set_A_periph(AT91_PIN_PB3, 0);     /* AC97RX */
+
+       /* reset */
+       if (data->reset_pin)
+               at91_set_gpio_output(data->reset_pin, 0);
+
+       ac97_data = *ek_data;
+       platform_device_register(&at91sam9263_ac97_device);
+}
+#else
+void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LCD Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static u64 lcdc_dmamask = 0xffffffffUL;
+static struct atmel_lcdfb_info lcdc_data;
+
+static struct resource lcdc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9263_LCDC_BASE,
+               .end    = AT91SAM9263_LCDC_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9263_ID_LCDC,
+               .end    = AT91SAM9263_ID_LCDC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91_lcdc_device = {
+       .name           = "atmel_lcdfb",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &lcdc_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &lcdc_data,
+       },
+       .resource       = lcdc_resources,
+       .num_resources  = ARRAY_SIZE(lcdc_resources),
+};
+
+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+{
+       if (!data)
+               return;
+
+       at91_set_A_periph(AT91_PIN_PC1, 0);     /* LCDHSYNC */
+       at91_set_A_periph(AT91_PIN_PC2, 0);     /* LCDDOTCK */
+       at91_set_A_periph(AT91_PIN_PC3, 0);     /* LCDDEN */
+       at91_set_B_periph(AT91_PIN_PB9, 0);     /* LCDCC */
+       at91_set_A_periph(AT91_PIN_PC6, 0);     /* LCDD2 */
+       at91_set_A_periph(AT91_PIN_PC7, 0);     /* LCDD3 */
+       at91_set_A_periph(AT91_PIN_PC8, 0);     /* LCDD4 */
+       at91_set_A_periph(AT91_PIN_PC9, 0);     /* LCDD5 */
+       at91_set_A_periph(AT91_PIN_PC10, 0);    /* LCDD6 */
+       at91_set_A_periph(AT91_PIN_PC11, 0);    /* LCDD7 */
+       at91_set_A_periph(AT91_PIN_PC14, 0);    /* LCDD10 */
+       at91_set_A_periph(AT91_PIN_PC15, 0);    /* LCDD11 */
+       at91_set_A_periph(AT91_PIN_PC16, 0);    /* LCDD12 */
+       at91_set_B_periph(AT91_PIN_PC12, 0);    /* LCDD13 */
+       at91_set_A_periph(AT91_PIN_PC18, 0);    /* LCDD14 */
+       at91_set_A_periph(AT91_PIN_PC19, 0);    /* LCDD15 */
+       at91_set_A_periph(AT91_PIN_PC22, 0);    /* LCDD18 */
+       at91_set_A_periph(AT91_PIN_PC23, 0);    /* LCDD19 */
+       at91_set_A_periph(AT91_PIN_PC24, 0);    /* LCDD20 */
+       at91_set_B_periph(AT91_PIN_PC17, 0);    /* LCDD21 */
+       at91_set_A_periph(AT91_PIN_PC26, 0);    /* LCDD22 */
+       at91_set_A_periph(AT91_PIN_PC27, 0);    /* LCDD23 */
+
+       lcdc_data = *data;
+       platform_device_register(&at91_lcdc_device);
+}
+#else
+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+#endif
+
+
 /* --------------------------------------------------------------------
  *  LEDs
  * -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
new file mode 100644 (file)
index 0000000..49cfe7a
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * linux/arch/arm/mach-at91/board-picotux200.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2007 Kleinhenz Elektronik GmbH
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata picotux200_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 2,
+       .tty_map        = { 4, 1, -1, -1, -1 }          /* ttyS0, ..., ttyS4 */
+};
+
+static void __init picotux200_map_io(void)
+{
+       /* Initialize processor: 18.432 MHz crystal */
+       at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&picotux200_uart_config);
+}
+
+static void __init picotux200_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata picotux200_eth_data = {
+       .phy_irq_pin    = AT91_PIN_PC4,
+       .is_rmii        = 1,
+};
+
+static struct at91_usbh_data __initdata picotux200_usbh_data = {
+       .ports          = 1,
+};
+
+// static struct at91_udc_data __initdata picotux200_udc_data = {
+//     .vbus_pin       = AT91_PIN_PD4,
+//     .pullup_pin     = AT91_PIN_PD5,
+// };
+
+static struct at91_mmc_data __initdata picotux200_mmc_data = {
+       .det_pin        = AT91_PIN_PB27,
+       .slot_b         = 0,
+       .wire4          = 1,
+       .wp_pin         = AT91_PIN_PA17,
+};
+
+// static struct spi_board_info picotux200_spi_devices[] = {
+//     {       /* DataFlash chip */
+//             .modalias       = "mtd_dataflash",
+//             .chip_select    = 0,
+//             .max_speed_hz   = 15 * 1000 * 1000,
+//     },
+// #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+//     {       /* DataFlash card */
+//             .modalias       = "mtd_dataflash",
+//             .chip_select    = 3,
+//             .max_speed_hz   = 15 * 1000 * 1000,
+//     },
+// #endif
+// };
+
+#define PICOTUX200_FLASH_BASE  AT91_CHIPSELECT_0
+#define PICOTUX200_FLASH_SIZE  0x400000
+
+static struct physmap_flash_data picotux200_flash_data = {
+       .width  = 2,
+};
+
+static struct resource picotux200_flash_resource = {
+       .start          = PICOTUX200_FLASH_BASE,
+       .end            = PICOTUX200_FLASH_BASE + PICOTUX200_FLASH_SIZE - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device picotux200_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &picotux200_flash_data,
+                       },
+       .resource       = &picotux200_flash_resource,
+       .num_resources  = 1,
+};
+
+static void __init picotux200_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* Ethernet */
+       at91_add_device_eth(&picotux200_eth_data);
+       /* USB Host */
+       at91_add_device_usbh(&picotux200_usbh_data);
+       /* USB Device */
+       // at91_add_device_udc(&picotux200_udc_data);
+       // at91_set_multi_drive(picotux200_udc_data.pullup_pin, 1);     /* pullup_pin is connected to reset */
+       /* I2C */
+       at91_add_device_i2c();
+       /* SPI */
+       // at91_add_device_spi(picotux200_spi_devices, ARRAY_SIZE(picotux200_spi_devices));
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+       /* DataFlash card */
+       at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
+       /* MMC */
+       at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
+       at91_add_device_mmc(0, &picotux200_mmc_data);
+#endif
+       /* NOR Flash */
+       platform_device_register(&picotux200_flash);
+}
+
+MACHINE_START(PICOTUX2XX, "picotux 200")
+       /* Maintainer: Kleinhenz Elektronik GmbH */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91rm9200_timer,
+       .map_io         = picotux200_map_io,
+       .init_irq       = picotux200_init_irq,
+       .init_machine   = picotux200_board_init,
+MACHINE_END
index 57fb449..65fa532 100644 (file)
@@ -104,9 +104,9 @@ static struct spi_board_info ek_spi_devices[] = {
        },
 #endif
 #endif
-#if defined(CONFIG_SND_AT73C213)
+#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
        {       /* AT73C213 DAC */
-               .modalias       = "snd_at73c213",
+               .modalias       = "at73c213",
                .chip_select    = 0,
                .max_speed_hz   = 10 * 1000 * 1000,
                .bus_num        = 1,
@@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct __initdata at91_eth_data ek_macb_data = {
+static struct at91_eth_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA7,
        .is_rmii        = 1,
 };
@@ -140,7 +140,7 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
 {
        *num_partitions = ARRAY_SIZE(ek_nand_partition);
        return ek_nand_partition;
@@ -188,6 +188,8 @@ static void __init ek_board_init(void)
        at91_add_device_eth(&ek_macb_data);
        /* MMC */
        at91_add_device_mmc(0, &ek_mmc_data);
+       /* I2C */
+       at91_add_device_i2c();
 }
 
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
index b7e7724..bcf7153 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
 #include <linux/dm9000.h>
 
 #include <asm/hardware.h>
@@ -194,6 +195,41 @@ static struct at91_nand_data __initdata ek_nand_data = {
 #endif
 };
 
+/*
+ * ADS7846 Touchscreen
+ */
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+
+static int ads7843_pendown_state(void)
+{
+       return !at91_get_gpio_value(AT91_PIN_PC2);      /* Touchscreen PENIRQ */
+}
+
+static struct ads7846_platform_data ads_info = {
+       .model                  = 7843,
+       .x_min                  = 150,
+       .x_max                  = 3830,
+       .y_min                  = 190,
+       .y_max                  = 3830,
+       .vref_delay_usecs       = 100,
+       .x_plate_ohms           = 450,
+       .y_plate_ohms           = 250,
+       .pressure_max           = 15000,
+       .debounce_max           = 1,
+       .debounce_rep           = 0,
+       .debounce_tol           = (~0),
+       .get_pendown_state      = ads7843_pendown_state,
+};
+
+static void __init ek_add_device_ts(void)
+{
+       at91_set_B_periph(AT91_PIN_PC2, 1);     /* External IRQ0, with pullup */
+       at91_set_gpio_input(AT91_PIN_PA11, 1);  /* Touchscreen BUSY signal */
+}
+#else
+static void __init ek_add_device_ts(void) {}
+#endif
+
 /*
  * SPI devices
  */
@@ -204,6 +240,16 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 15 * 1000 * 1000,
                .bus_num        = 0,
        },
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+       {
+               .modalias       = "ads7846",
+               .chip_select    = 2,
+               .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
+               .bus_num        = 0,
+               .platform_data  = &ads_info,
+               .irq            = AT91SAM9261_ID_IRQ0,
+       },
+#endif
 #if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
        {       /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
                .modalias       = "mtd_dataflash",
@@ -211,9 +257,9 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 15 * 1000 * 1000,
                .bus_num        = 0,
        },
-#elif defined(CONFIG_SND_AT73C213)
+#elif defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
        {       /* AT73C213 DAC */
-               .modalias       = "snd_at73c213",
+               .modalias       = "at73c213",
                .chip_select    = 3,
                .max_speed_hz   = 10 * 1000 * 1000,
                .bus_num        = 0,
@@ -241,6 +287,8 @@ static void __init ek_board_init(void)
 #if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
        /* SPI */
        at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+       /* Touchscreen */
+       ek_add_device_ts();
 #else
        /* MMC */
        at91_add_device_mmc(0, &ek_mmc_data);
index 8fdce11..f574585 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -85,6 +86,40 @@ static struct at91_udc_data __initdata ek_udc_data = {
 };
 
 
+/*
+ * ADS7846 Touchscreen
+ */
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+static int ads7843_pendown_state(void)
+{
+       return !at91_get_gpio_value(AT91_PIN_PA15);     /* Touchscreen PENIRQ */
+}
+
+static struct ads7846_platform_data ads_info = {
+       .model                  = 7843,
+       .x_min                  = 150,
+       .x_max                  = 3830,
+       .y_min                  = 190,
+       .y_max                  = 3830,
+       .vref_delay_usecs       = 100,
+       .x_plate_ohms           = 450,
+       .y_plate_ohms           = 250,
+       .pressure_max           = 15000,
+       .debounce_max           = 1,
+       .debounce_rep           = 0,
+       .debounce_tol           = (~0),
+       .get_pendown_state      = ads7843_pendown_state,
+};
+
+static void __init ek_add_device_ts(void)
+{
+       at91_set_B_periph(AT91_PIN_PA15, 1);    /* External IRQ1, with pullup */
+       at91_set_gpio_input(AT91_PIN_PA31, 1);  /* Touchscreen BUSY signal */
+}
+#else
+static void __init ek_add_device_ts(void) {}
+#endif
+
 /*
  * SPI devices.
  */
@@ -97,6 +132,16 @@ static struct spi_board_info ek_spi_devices[] = {
                .bus_num        = 0,
        },
 #endif
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+       {
+               .modalias       = "ads7846",
+               .chip_select    = 3,
+               .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
+               .bus_num        = 0,
+               .platform_data  = &ads_info,
+               .irq            = AT91SAM9263_ID_IRQ1,
+       },
+#endif
 };
 
 
@@ -111,6 +156,14 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
 };
 
 
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata ek_macb_data = {
+       .is_rmii        = 1,
+};
+
+
 /*
  * NAND flash
  */
@@ -148,6 +201,14 @@ static struct at91_nand_data __initdata ek_nand_data = {
 };
 
 
+/*
+ * AC97
+ */
+static struct atmel_ac97_data ek_ac97_data = {
+       .reset_pin      = AT91_PIN_PA13,
+};
+
+
 static void __init ek_board_init(void)
 {
        /* Serial */
@@ -157,11 +218,20 @@ static void __init ek_board_init(void)
        /* USB Device */
        at91_add_device_udc(&ek_udc_data);
        /* SPI */
+       at91_set_gpio_output(AT91_PIN_PE20, 1);         /* select spi0 clock */
        at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+       /* Touchscreen */
+       ek_add_device_ts();
        /* MMC */
        at91_add_device_mmc(1, &ek_mmc_data);
+       /* Ethernet */
+       at91_add_device_eth(&ek_macb_data);
        /* NAND */
        at91_add_device_nand(&ek_nand_data);
+       /* I2C */
+       at91_add_device_i2c();
+       /* AC97 */
+       at91_add_device_ac97(&ek_ac97_data);
 }
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
index db38afb..bbf0d33 100644 (file)
@@ -102,6 +102,26 @@ EXPORT_SYMBOL(__readb);
 EXPORT_SYMBOL(__readw);
 EXPORT_SYMBOL(__readl);
 
+void readsw(void __iomem *addr, void *data, int len)
+{
+       void __iomem *a = __isamem_convert_addr(addr);
+
+       BUG_ON((unsigned long)addr & 1);
+
+       __raw_readsw(a, data, len);
+}
+EXPORT_SYMBOL(readsw);
+
+void readsl(void __iomem *addr, void *data, int len)
+{
+       void __iomem *a = __isamem_convert_addr(addr);
+
+       BUG_ON((unsigned long)addr & 3);
+
+       __raw_readsl(a, data, len);
+}
+EXPORT_SYMBOL(readsl);
+
 void __writeb(u8 val, void __iomem *addr)
 {
        void __iomem *a = __isamem_convert_addr(addr);
@@ -137,6 +157,26 @@ EXPORT_SYMBOL(__writeb);
 EXPORT_SYMBOL(__writew);
 EXPORT_SYMBOL(__writel);
 
+void writesw(void __iomem *addr, void *data, int len)
+{
+       void __iomem *a = __isamem_convert_addr(addr);
+
+       BUG_ON((unsigned long)addr & 1);
+
+       __raw_writesw(a, data, len);
+}
+EXPORT_SYMBOL(writesw);
+
+void writesl(void __iomem *addr, void *data, int len)
+{
+       void __iomem *a = __isamem_convert_addr(addr);
+
+       BUG_ON((unsigned long)addr & 3);
+
+       __raw_writesl(a, data, len);
+}
+EXPORT_SYMBOL(writesl);
+
 #define SUPERIO_PORT(p) \
        (((p) >> 3) == (0x3f8 >> 3) || \
         ((p) >> 3) == (0x2f8 >> 3) || \
index f174d1a..9d7515c 100644 (file)
@@ -27,6 +27,10 @@ struct clk {
        u32             enable_mask;
 };
 
+static struct clk clk_uart = {
+       .name           = "UARTCLK",
+       .rate           = 14745600,
+};
 static struct clk clk_pll1 = {
        .name           = "pll1",
 };
@@ -50,6 +54,7 @@ static struct clk clk_usb_host = {
 
 
 static struct clk *clocks[] = {
+       &clk_uart,
        &clk_pll1,
        &clk_f,
        &clk_h,
index 1463330..d0dc51e 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
index 394ec92..af7d3ff 100644 (file)
@@ -23,7 +23,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
index fb8c6d9..af9ebcc 100644 (file)
@@ -22,7 +22,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
index 4185e05..da1609d 100644 (file)
@@ -7,5 +7,6 @@ obj-$(CONFIG_ARCH_IOP13XX) += setup.o
 obj-$(CONFIG_ARCH_IOP13XX) += irq.o
 obj-$(CONFIG_ARCH_IOP13XX) += pci.o
 obj-$(CONFIG_ARCH_IOP13XX) += io.o
+obj-$(CONFIG_ARCH_IOP13XX) += tpmi.o
 obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
 obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o
index e79a1b6..5b22fde 100644 (file)
@@ -41,7 +41,7 @@ void * __iomem __iop13xx_io(unsigned long io_addr)
 EXPORT_SYMBOL(__iop13xx_io);
 
 void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
-       unsigned long flags)
+       unsigned int mtype)
 {
        void __iomem * retval;
 
@@ -61,9 +61,9 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
                                 (cookie - IOP13XX_PCIE_LOWER_MEM_RA));
                break;
        case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
-               retval = __ioremap(IOP13XX_PBI_LOWER_MEM_PA +
-                                 (cookie - IOP13XX_PBI_LOWER_MEM_RA),
-                                 size, flags);
+               retval = __arm_ioremap(IOP13XX_PBI_LOWER_MEM_PA +
+                                      (cookie - IOP13XX_PBI_LOWER_MEM_RA),
+                                      size, mtype);
                break;
        case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
                retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
@@ -75,7 +75,7 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
                retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
                break;
        default:
-               retval = __ioremap(cookie, size, flags);
+               retval = __arm_ioremap(cookie, size, mtype);
        }
 
        return retval;
index a519d70..268a8d8 100644 (file)
@@ -75,11 +75,14 @@ static void __init iq81340mc_init(void)
 {
        iop13xx_platform_init();
        iq81340mc_pci_init();
+       iop13xx_add_tpmi_devices();
 }
 
 static void __init iq81340mc_timer_init(void)
 {
-       iop_init_time(400000000);
+       unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
+       printk(KERN_DEBUG "%s: bus frequency: %lu\n", __FUNCTION__, bus_freq);
+       iop_init_time(bus_freq);
 }
 
 static struct sys_timer iq81340mc_timer = {
index 0e71fbc..a51ffd2 100644 (file)
@@ -77,11 +77,14 @@ static void __init iq81340sc_init(void)
 {
        iop13xx_platform_init();
        iq81340sc_pci_init();
+       iop13xx_add_tpmi_devices();
 }
 
 static void __init iq81340sc_timer_init(void)
 {
-       iop_init_time(400000000);
+       unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
+       printk(KERN_DEBUG "%s: bus frequency: %lu\n", __FUNCTION__, bus_freq);
+       iop_init_time(bus_freq);
 }
 
 static struct sys_timer iq81340sc_timer = {
index 89ec70e..d1d0d32 100644 (file)
@@ -88,9 +88,9 @@ void iop13xx_map_pci_memory(void)
 
                                if (end) {
                                        iop13xx_atux_mem_base =
-                                       (u32) __ioremap_pfn(
+                                       (u32) __arm_ioremap_pfn(
                                        __phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA)
-                                       , 0, iop13xx_atux_mem_size, 0);
+                                       , 0, iop13xx_atux_mem_size, MT_DEVICE);
                                        if (!iop13xx_atux_mem_base) {
                                                printk("%s: atux allocation "
                                                       "failed\n", __FUNCTION__);
@@ -114,9 +114,9 @@ void iop13xx_map_pci_memory(void)
 
                                if (end) {
                                        iop13xx_atue_mem_base =
-                                       (u32) __ioremap_pfn(
+                                       (u32) __arm_ioremap_pfn(
                                        __phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA)
-                                       , 0, iop13xx_atue_mem_size, 0);
+                                       , 0, iop13xx_atue_mem_size, MT_DEVICE);
                                        if (!iop13xx_atue_mem_base) {
                                                printk("%s: atue allocation "
                                                       "failed\n", __FUNCTION__);
@@ -1023,7 +1023,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
                                  << IOP13XX_ATUX_PCIXSR_FUNC_NUM;
                __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR);
 
-               res[0].start = IOP13XX_PCIX_LOWER_IO_PA;
+               res[0].start = IOP13XX_PCIX_LOWER_IO_PA + IOP13XX_PCIX_IO_BUS_OFFSET;
                res[0].end   = IOP13XX_PCIX_UPPER_IO_PA;
                res[0].name  = "IQ81340 ATUX PCI I/O Space";
                res[0].flags = IORESOURCE_IO;
@@ -1033,7 +1033,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
                res[1].name  = "IQ81340 ATUX PCI Memory Space";
                res[1].flags = IORESOURCE_MEM;
                sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET;
-               sys->io_offset = IOP13XX_PCIX_IO_OFFSET;
+               sys->io_offset = IOP13XX_PCIX_LOWER_IO_PA;
                break;
        case IOP13XX_INIT_ATU_ATUE:
                /* Note: the function number field in the PCSR is ro */
@@ -1044,7 +1044,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
 
                __raw_writel(pcsr, IOP13XX_ATUE_PCSR);
 
-               res[0].start = IOP13XX_PCIE_LOWER_IO_PA;
+               res[0].start = IOP13XX_PCIE_LOWER_IO_PA + IOP13XX_PCIE_IO_BUS_OFFSET;
                res[0].end   = IOP13XX_PCIE_UPPER_IO_PA;
                res[0].name  = "IQ81340 ATUE PCI I/O Space";
                res[0].flags = IORESOURCE_IO;
@@ -1054,7 +1054,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
                res[1].name  = "IQ81340 ATUE PCI Memory Space";
                res[1].flags = IORESOURCE_MEM;
                sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET;
-               sys->io_offset = IOP13XX_PCIE_IO_OFFSET;
+               sys->io_offset = IOP13XX_PCIE_LOWER_IO_PA;
                sys->map_irq = iop13xx_pcie_map_irq;
                break;
        default:
index 9a46bcd..bc48715 100644 (file)
@@ -258,15 +258,11 @@ void __init iop13xx_platform_init(void)
 
        if (init_uart == IOP13XX_INIT_UART_DEFAULT) {
                switch (iop13xx_dev_id()) {
-               /* enable both uarts on iop341 and iop342 */
+               /* enable both uarts on iop341 */
                case 0x3380:
                case 0x3384:
                case 0x3388:
                case 0x338c:
-               case 0x3382:
-               case 0x3386:
-               case 0x338a:
-               case 0x338e:
                        init_uart |= IOP13XX_INIT_UART_0;
                        init_uart |= IOP13XX_INIT_UART_1;
                        break;
diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c
new file mode 100644 (file)
index 0000000..d3dc278
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * iop13xx tpmi device resources
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+/* assumes CONTROLLER_ONLY# is never asserted in the ESSR register */
+#define IOP13XX_TPMI_MMR(dev)  IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
+#define IOP13XX_TPMI_MEM(dev)  IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
+#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
+#define IOP13XX_TPMI_MMR_SIZE      (SZ_4K - 1)
+#define IOP13XX_TPMI_MEM_SIZE      (255)
+#define IOP13XX_TPMI_MEM_CTRL      (SZ_1K - 1)
+#define IOP13XX_TPMI_RESOURCE_MMR  0
+#define IOP13XX_TPMI_RESOURCE_MEM  1
+#define IOP13XX_TPMI_RESOURCE_CTRL 2
+#define IOP13XX_TPMI_RESOURCE_IRQ  3
+
+static struct resource iop13xx_tpmi_0_resources[] = {
+       [IOP13XX_TPMI_RESOURCE_MMR] = {
+               .start = IOP13XX_TPMI_MMR(4), /* tpmi0 starts at dev == 4 */
+               .end = IOP13XX_TPMI_MMR(4) + IOP13XX_TPMI_MMR_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_MEM] = {
+               .start = IOP13XX_TPMI_MEM(0),
+               .end = IOP13XX_TPMI_MEM(0) + IOP13XX_TPMI_MEM_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_CTRL] = {
+               .start = IOP13XX_TPMI_CTRL(0),
+               .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_IRQ] = {
+               .start = IRQ_IOP13XX_TPMI0_OUT,
+               .end = IRQ_IOP13XX_TPMI0_OUT,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_tpmi_1_resources[] = {
+       [IOP13XX_TPMI_RESOURCE_MMR] = {
+               .start = IOP13XX_TPMI_MMR(1),
+               .end = IOP13XX_TPMI_MMR(1) + IOP13XX_TPMI_MMR_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_MEM] = {
+               .start = IOP13XX_TPMI_MEM(1),
+               .end = IOP13XX_TPMI_MEM(1) + IOP13XX_TPMI_MEM_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_CTRL] = {
+               .start = IOP13XX_TPMI_CTRL(1),
+               .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_IRQ] = {
+               .start = IRQ_IOP13XX_TPMI1_OUT,
+               .end = IRQ_IOP13XX_TPMI1_OUT,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_tpmi_2_resources[] = {
+       [IOP13XX_TPMI_RESOURCE_MMR] = {
+               .start = IOP13XX_TPMI_MMR(2),
+               .end = IOP13XX_TPMI_MMR(2) + IOP13XX_TPMI_MMR_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_MEM] = {
+               .start = IOP13XX_TPMI_MEM(2),
+               .end = IOP13XX_TPMI_MEM(2) + IOP13XX_TPMI_MEM_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_CTRL] = {
+               .start = IOP13XX_TPMI_CTRL(2),
+               .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_IRQ] = {
+               .start = IRQ_IOP13XX_TPMI2_OUT,
+               .end = IRQ_IOP13XX_TPMI2_OUT,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_tpmi_3_resources[] = {
+       [IOP13XX_TPMI_RESOURCE_MMR] = {
+               .start = IOP13XX_TPMI_MMR(3),
+               .end = IOP13XX_TPMI_MMR(3) + IOP13XX_TPMI_MMR_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_MEM] = {
+               .start = IOP13XX_TPMI_MEM(3),
+               .end = IOP13XX_TPMI_MEM(3) + IOP13XX_TPMI_MEM_SIZE,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_CTRL] = {
+               .start = IOP13XX_TPMI_CTRL(3),
+               .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
+       [IOP13XX_TPMI_RESOURCE_IRQ] = {
+               .start = IRQ_IOP13XX_TPMI3_OUT,
+               .end = IRQ_IOP13XX_TPMI3_OUT,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
+static struct platform_device iop13xx_tpmi_0_device = {
+       .name = "iop-tpmi",
+       .id = 0,
+       .num_resources = 4,
+       .resource = iop13xx_tpmi_0_resources,
+       .dev = {
+               .dma_mask          = &iop13xx_tpmi_mask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+       },
+};
+
+static struct platform_device iop13xx_tpmi_1_device = {
+       .name = "iop-tpmi",
+       .id = 1,
+       .num_resources = 4,
+       .resource = iop13xx_tpmi_1_resources,
+       .dev = {
+               .dma_mask          = &iop13xx_tpmi_mask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+       },
+};
+
+static struct platform_device iop13xx_tpmi_2_device = {
+       .name = "iop-tpmi",
+       .id = 2,
+       .num_resources = 4,
+       .resource = iop13xx_tpmi_2_resources,
+       .dev = {
+               .dma_mask          = &iop13xx_tpmi_mask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+       },
+};
+
+static struct platform_device iop13xx_tpmi_3_device = {
+       .name = "iop-tpmi",
+       .id = 3,
+       .num_resources = 4,
+       .resource = iop13xx_tpmi_3_resources,
+       .dev = {
+               .dma_mask          = &iop13xx_tpmi_mask,
+               .coherent_dma_mask = DMA_64BIT_MASK,
+       },
+};
+
+__init void iop13xx_add_tpmi_devices(void)
+{
+       unsigned short device_id;
+
+       /* tpmi's not present on iop341 or iop342 */
+       if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
+               /* ATUE must be present */
+               device_id = __raw_readw(IOP13XX_ATUE_DID);
+       else
+               /* ATUX must be present */
+               device_id = __raw_readw(IOP13XX_ATUX_DID);
+
+       switch (device_id) {
+       /* iop34[1|2] 0-tpmi */
+       case 0x3380:
+       case 0x3384:
+       case 0x3388:
+       case 0x338c:
+       case 0x3382:
+       case 0x3386:
+       case 0x338a:
+       case 0x338e:
+               return;
+       /* iop348 1-tpmi */
+       case 0x3310:
+       case 0x3312:
+       case 0x3314:
+       case 0x3318:
+       case 0x331a:
+       case 0x331c:
+       case 0x33c0:
+       case 0x33c2:
+       case 0x33c4:
+       case 0x33c8:
+       case 0x33ca:
+       case 0x33cc:
+       case 0x33b0:
+       case 0x33b2:
+       case 0x33b4:
+       case 0x33b8:
+       case 0x33ba:
+       case 0x33bc:
+       case 0x3320:
+       case 0x3322:
+       case 0x3324:
+       case 0x3328:
+       case 0x332a:
+       case 0x332c:
+               platform_device_register(&iop13xx_tpmi_0_device);
+               return;
+       default:
+               platform_device_register(&iop13xx_tpmi_0_device);
+               platform_device_register(&iop13xx_tpmi_1_device);
+               platform_device_register(&iop13xx_tpmi_2_device);
+               platform_device_register(&iop13xx_tpmi_3_device);
+               return;
+       }
+}
index 9dd49cf..9bb02b6 100644 (file)
@@ -34,6 +34,14 @@ config MACH_N2100
          Say Y here if you want to run your kernel on the Thecus n2100
          NAS appliance.
 
+config IOP3XX_ATU
+        bool "Enable the PCI Controller"
+        default y
+        help
+          Say Y here if you want the IOP to initialize its PCI Controller.
+          Say N if the IOP is an add in card, the host system owns the PCI
+          bus in this case.
+
 endmenu
 
 endif
index 60e7430..7b21c6e 100644 (file)
@@ -178,9 +178,10 @@ static struct hw_pci iq31244_pci __initdata = {
 
 static int __init iq31244_pci_init(void)
 {
-       if (is_ep80219())
-               pci_common_init(&ep80219_pci);
-       else if (machine_is_iq31244()) {
+       if (is_ep80219()) {
+               if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+                       pci_common_init(&ep80219_pci);
+       } else if (machine_is_iq31244()) {
                if (is_80219()) {
                        printk("note: iq31244 board type has been selected\n");
                        printk("note: to select ep80219 operation:\n");
@@ -189,7 +190,9 @@ static int __init iq31244_pci_init(void)
                        printk("\t2/ update boot loader to pass"
                                " the ep80219 id: %d\n", MACH_TYPE_EP80219);
                }
-               pci_common_init(&iq31244_pci);
+
+               if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+                       pci_common_init(&iq31244_pci);
        }
 
        return 0;
index 361c70c..bc25fb9 100644 (file)
@@ -113,7 +113,8 @@ static struct hw_pci iq80321_pci __initdata = {
 
 static int __init iq80321_pci_init(void)
 {
-       if (machine_is_iq80321())
+       if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
+               machine_is_iq80321())
                pci_common_init(&iq80321_pci);
 
        return 0;
index 9aa016b..45598e0 100644 (file)
@@ -16,6 +16,14 @@ config MACH_IQ80332
          Say Y here if you want to run your kernel on the Intel IQ80332
          evaluation kit for the IOP332 chipset.
 
+config IOP3XX_ATU
+       bool "Enable the PCI Controller"
+       default y
+       help
+         Say Y here if you want the IOP to initialize its PCI Controller.
+         Say N if the IOP is an add in card, the host system owns the PCI
+         bus in this case.
+
 endmenu
 
 endif
index 1a9e361..376c932 100644 (file)
@@ -96,7 +96,8 @@ static struct hw_pci iq80331_pci __initdata = {
 
 static int __init iq80331_pci_init(void)
 {
-       if (machine_is_iq80331())
+       if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
+               machine_is_iq80331())
                pci_common_init(&iq80331_pci);
 
        return 0;
index 96d6f0f..58c8149 100644 (file)
@@ -96,7 +96,8 @@ static struct hw_pci iq80332_pci __initdata = {
 
 static int __init iq80332_pci_init(void)
 {
-       if (machine_is_iq80332())
+       if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
+               machine_is_iq80332())
                pci_common_init(&iq80332_pci);
 
        return 0;
index 27b7480..9cf2498 100644 (file)
@@ -84,59 +84,59 @@ static struct map_desc ixp2000_io_desc[] __initdata = {
                .virtual        = IXP2000_CAP_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_CAP_PHYS_BASE),
                .length         = IXP2000_CAP_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_INTCTL_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE),
                .length         = IXP2000_INTCTL_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_PCI_CREG_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE),
                .length         = IXP2000_PCI_CREG_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_PCI_CSR_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE),
                .length         = IXP2000_PCI_CSR_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_MSF_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_MSF_PHYS_BASE),
                .length         = IXP2000_MSF_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_SCRATCH_RING_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE),
                .length         = IXP2000_SCRATCH_RING_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_SRAM0_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE),
                .length         = IXP2000_SRAM0_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_PCI_IO_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE),
                .length         = IXP2000_PCI_IO_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_PCI_CFG0_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE),
                .length         = IXP2000_PCI_CFG0_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = IXP2000_PCI_CFG1_VIRT_BASE,
                .pfn            = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE),
                .length         = IXP2000_PCI_CFG1_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }
 };
 
 void __init ixp2000_map_io(void)
 {
        /*
-        * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE so that
+        * On IXP2400 CPUs we need to use MT_DEVICE_IXP2000 so that
         * XCB=101 (to avoid triggering erratum #66), and given that
         * this mode speeds up I/O accesses and we have write buffer
         * flushes in the right places anyway, it doesn't hurt to use
index ac29298..500e997 100644 (file)
@@ -70,17 +70,17 @@ static struct map_desc enp2611_io_desc[] __initdata = {
                .virtual        = ENP2611_CALEB_VIRT_BASE,
                .pfn            = __phys_to_pfn(ENP2611_CALEB_PHYS_BASE),
                .length         = ENP2611_CALEB_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = ENP2611_PM3386_0_VIRT_BASE,
                .pfn            = __phys_to_pfn(ENP2611_PM3386_0_PHYS_BASE),
                .length         = ENP2611_PM3386_0_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }, {
                .virtual        = ENP2611_PM3386_1_VIRT_BASE,
                .pfn            = __phys_to_pfn(ENP2611_PM3386_1_PHYS_BASE),
                .length         = ENP2611_PM3386_1_SIZE,
-               .type           = MT_IXP2000_DEVICE,
+               .type           = MT_DEVICE_IXP2000,
        }
 };
 
index 8a339cd..9715ef5 100644 (file)
@@ -62,6 +62,12 @@ config MACH_IXDP465
          IXDP465 Development Platform (Also known as BMP).
          For more information on this platform, see <file:Documentation/arm/IXP4xx>.
 
+config MACH_KIXRP435
+       bool "KIXRP435"
+       help
+         Say 'Y' here if you want your kernel to support Intel's
+         KIXRP435 Reference Platform.
+         For more information on this platform, see <file:Documentation/arm/IXP4xx>.
 
 #
 # IXCDP1100 is the exact same HW as IXDP425, but with a different machine 
@@ -89,12 +95,21 @@ config MACH_NAS100D
          NAS 100d device. For more information on this platform,
          see http://www.nslu2-linux.org/wiki/NAS100d/HomePage
 
+config MACH_DSMG600
+       bool
+       prompt "D-Link DSM-G600 RevA"
+       select PCI
+       help
+         Say 'Y' here if you want your kernel to support D-Link's
+         DSM-G600 RevA device. For more information on this platform,
+         see http://www.nslu2-linux.org/wiki/DSMG600/HomePage
+
 #
 # Avila and IXDP share the same source for now. Will change in future
 #
 config ARCH_IXDP4XX
        bool
-       depends on ARCH_IXDP425 || MACH_IXDP465
+       depends on ARCH_IXDP425 || MACH_IXDP465 || MACH_KIXRP435
        default y
 
 #
@@ -105,6 +120,11 @@ config CPU_IXP46X
        depends on MACH_IXDP465
        default y
 
+config CPU_IXP43X
+       bool
+       depends on MACH_KIXRP435
+       default y
+
 config MACH_GTWX5715
        bool "Gemtek WX5715 (Linksys WRV54G)"
        depends on ARCH_IXP4XX
index 746e297..3b87c47 100644 (file)
@@ -12,6 +12,7 @@ obj-pci-$(CONFIG_ARCH_ADI_COYOTE)     += coyote-pci.o
 obj-pci-$(CONFIG_MACH_GTWX5715)                += gtwx5715-pci.o
 obj-pci-$(CONFIG_MACH_NSLU2)           += nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)         += nas100d-pci.o
+obj-pci-$(CONFIG_MACH_DSMG600)         += dsmg600-pci.o
 
 obj-y  += common.o
 
@@ -22,5 +23,6 @@ obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)    += gtwx5715-setup.o
 obj-$(CONFIG_MACH_NSLU2)       += nslu2-setup.o nslu2-power.o
 obj-$(CONFIG_MACH_NAS100D)     += nas100d-setup.o nas100d-power.o
+obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
 
 obj-$(CONFIG_PCI)              += $(obj-pci-$(CONFIG_PCI)) common-pci.o
index 9562177..bf04121 100644 (file)
@@ -374,7 +374,7 @@ void __init ixp4xx_pci_preinit(void)
         * Determine which PCI read method to use.
         * Rev 0 IXP425 requires workaround.
         */
-       if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
+       if (!(processor_id & 0xf) && cpu_is_ixp42x()) {
                printk("PCI: IXP42x A0 silicon detected - "
                        "PCI Non-Prefetch Workaround Enabled\n");
                ixp4xx_pci_read = ixp4xx_pci_read_errata;
@@ -480,7 +480,7 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
        res[0].flags = IORESOURCE_IO;
 
        res[1].name = "PCI Memory Space";
-       res[1].start = 0x48000000;
+       res[1].start = PCIBIOS_MIN_MEM;
 #ifndef CONFIG_IXP4XX_INDIRECT_PCI
        res[1].end = 0x4bffffff;
 #else
index 45068c3..f5cae1e 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/arch/udc.h>
 #include <asm/hardware.h>
@@ -41,6 +42,8 @@
 #include <asm/mach/time.h>
 
 static int __init ixp4xx_clocksource_init(void);
+static int __init ixp4xx_clockevent_init(void);
+static struct clock_event_device clockevent_ixp4xx;
 
 /*************************************************************************
  * IXP4xx chipset I/O mapping
@@ -102,6 +105,29 @@ static signed char irq2gpio[32] = {
         7,  8,  9, 10, 11, 12, -1, -1,
 };
 
+int gpio_to_irq(int gpio)
+{
+       int irq;
+
+       for (irq = 0; irq < 32; irq++) {
+               if (irq2gpio[irq] == gpio)
+                       return irq;
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(int irq)
+{
+       int gpio = (irq < 32) ? irq2gpio[irq] : -EINVAL;
+
+       if (gpio == -1)
+               return -EINVAL;
+
+       return gpio;
+}
+EXPORT_SYMBOL(irq_to_gpio);
+
 static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
 {
        int line = irq2gpio[irq];
@@ -169,7 +195,7 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
 
 static void ixp4xx_irq_mask(unsigned int irq)
 {
-       if (cpu_is_ixp46x() && irq >= 32)
+       if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && irq >= 32)
                *IXP4XX_ICMR2 &= ~(1 << (irq - 32));
        else
                *IXP4XX_ICMR &= ~(1 << irq);
@@ -192,7 +218,7 @@ static void ixp4xx_irq_unmask(unsigned int irq)
        if (!(ixp4xx_irq_edge & (1 << irq)))
                ixp4xx_irq_ack(irq);
 
-       if (cpu_is_ixp46x() && irq >= 32)
+       if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && irq >= 32)
                *IXP4XX_ICMR2 |= (1 << (irq - 32));
        else
                *IXP4XX_ICMR |= (1 << irq);
@@ -216,7 +242,7 @@ void __init ixp4xx_init_irq(void)
        /* Disable all interrupt */
        *IXP4XX_ICMR = 0x0; 
 
-       if (cpu_is_ixp46x()) {
+       if (cpu_is_ixp46x() || cpu_is_ixp43x()) {
                /* Route upper 32 sources to IRQ instead of FIQ */
                *IXP4XX_ICLR2 = 0x00;
 
@@ -239,52 +265,40 @@ void __init ixp4xx_init_irq(void)
  * counter as a source of real clock ticks to account for missed jiffies.
  *************************************************************************/
 
-static unsigned volatile last_jiffy_time;
-
-#define CLOCK_TICKS_PER_USEC   ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
-
 static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
 {
-       write_seqlock(&xtime_lock);
+       struct clock_event_device *evt = &clockevent_ixp4xx;
 
        /* Clear Pending Interrupt by writing '1' to it */
        *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
 
-       /*
-        * Catch up with the real idea of time
-        */
-       while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
-               timer_tick();
-               last_jiffy_time += LATCH;
-       }
-
-       write_sequnlock(&xtime_lock);
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
 
 static struct irqaction ixp4xx_timer_irq = {
-       .name           = "IXP4xx Timer Tick",
+       .name           = "timer1",
        .flags          = IRQF_DISABLED | IRQF_TIMER,
        .handler        = ixp4xx_timer_interrupt,
 };
 
 static void __init ixp4xx_timer_init(void)
 {
+       /* Reset/disable counter */
+       *IXP4XX_OSRT1 = 0;
+
        /* Clear Pending Interrupt by writing '1' to it */
        *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
 
-       /* Setup the Timer counter value */
-       *IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
-
        /* Reset time-stamp counter */
        *IXP4XX_OSTS = 0;
-       last_jiffy_time = 0;
 
        /* Connect the interrupt handler and enable the interrupt */
        setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
 
        ixp4xx_clocksource_init();
+       ixp4xx_clockevent_init();
 }
 
 struct sys_timer ixp4xx_timer = {
@@ -384,6 +398,9 @@ void __init ixp4xx_sys_init(void)
                        ixp4xx_exp_bus_size >> 20);
 }
 
+/*
+ * clocksource
+ */
 cycle_t ixp4xx_get_cycles(void)
 {
        return *IXP4XX_OSTS;
@@ -408,3 +425,64 @@ static int __init ixp4xx_clocksource_init(void)
 
        return 0;
 }
+
+/*
+ * clockevents
+ */
+static int ixp4xx_set_next_event(unsigned long evt,
+                                struct clock_event_device *unused)
+{
+       unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
+
+       *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
+
+       return 0;
+}
+
+static void ixp4xx_set_mode(enum clock_event_mode mode,
+                           struct clock_event_device *evt)
+{
+       unsigned long opts, osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK;
+               opts = IXP4XX_OST_ENABLE;
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /* period set by 'set next_event' */
+               osrt = 0;
+               opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+       default:
+               osrt = opts = 0;
+               break;
+       }
+
+       *IXP4XX_OSRT1 = osrt | opts;
+}
+
+static struct clock_event_device clockevent_ixp4xx = {
+       .name           = "ixp4xx timer1",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .rating         = 200,
+       .shift          = 24,
+       .set_mode       = ixp4xx_set_mode,
+       .set_next_event = ixp4xx_set_next_event,
+};
+
+static int __init ixp4xx_clockevent_init(void)
+{
+       clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC,
+                                       clockevent_ixp4xx.shift);
+       clockevent_ixp4xx.max_delta_ns =
+               clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
+       clockevent_ixp4xx.min_delta_ns =
+               clockevent_delta2ns(0xf, &clockevent_ixp4xx);
+       clockevent_ixp4xx.cpumask = cpumask_of_cpu(0);
+
+       clockevents_register_device(&clockevent_ixp4xx);
+       return 0;
+}
diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c
new file mode 100644 (file)
index 0000000..9db7e1f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * DSM-G600 board-level PCI initialization
+ *
+ * Copyright (C) 2006 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on ixdp425-pci.c:
+ *     Copyright (C) 2002 Intel Corporation.
+ *     Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: http://www.nslu2-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/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+void __init dsmg600_pci_preinit(void)
+{
+       set_irq_type(IRQ_DSMG600_PCI_INTA, IRQT_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTB, IRQT_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTC, IRQT_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTD, IRQT_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTE, IRQT_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTF, IRQT_LOW);
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init dsmg600_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       static int pci_irq_table[DSMG600_PCI_MAX_DEV][DSMG600_PCI_IRQ_LINES] =
+       {
+               { IRQ_DSMG600_PCI_INTE, -1, -1 },
+               { IRQ_DSMG600_PCI_INTA, -1, -1 },
+               { IRQ_DSMG600_PCI_INTB, IRQ_DSMG600_PCI_INTC, IRQ_DSMG600_PCI_INTD },
+               { IRQ_DSMG600_PCI_INTF, -1, -1 },
+       };
+
+       int irq = -1;
+
+       if (slot >= 1 && slot <= DSMG600_PCI_MAX_DEV &&
+               pin >= 1 && pin <= DSMG600_PCI_IRQ_LINES)
+               irq = pci_irq_table[slot-1][pin-1];
+
+       return irq;
+}
+
+struct hw_pci __initdata dsmg600_pci = {
+       .nr_controllers = 1,
+       .preinit        = dsmg600_pci_preinit,
+       .swizzle        = pci_std_swizzle,
+       .setup          = ixp4xx_setup,
+       .scan           = ixp4xx_scan_bus,
+       .map_irq        = dsmg600_map_irq,
+};
+
+int __init dsmg600_pci_init(void)
+{
+       if (machine_is_dsmg600())
+               pci_common_init(&dsmg600_pci);
+
+       return 0;
+}
+
+subsys_initcall(dsmg600_pci_init);
diff --git a/arch/arm/mach-ixp4xx/dsmg600-power.c b/arch/arm/mach-ixp4xx/dsmg600-power.c
new file mode 100644 (file)
index 0000000..3471787
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * arch/arm/mach-ixp4xx/dsmg600-power.c
+ *
+ * DSM-G600 Power/Reset driver
+ * Author: Michael Westerhof <mwester@dls.net>
+ *
+ * Based on nslu2-power.c
+ *  Copyright (C) 2005 Tower Technologies
+ *  Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * which was based on nslu2-io.c
+ *  Copyright (C) 2004 Karen Spearel
+ *
+ * Maintainers: http://www.nslu2-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/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+
+#include <asm/mach-types.h>
+
+extern void ctrl_alt_del(void);
+
+/* This is used to make sure the power-button pusher is serious.  The button
+ * must be held until the value of this counter reaches zero.
+ */
+static volatile int power_button_countdown;
+
+/* Must hold the button down for at least this many counts to be processed */
+#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
+
+static void dsmg600_power_handler(unsigned long data);
+static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
+
+static void dsmg600_power_handler(unsigned long data)
+{
+       /* This routine is called twice per second to check the
+        * state of the power button.
+        */
+
+       if (*IXP4XX_GPIO_GPINR & DSMG600_PB_BM) {
+
+               /* IO Pin is 1 (button pushed) */
+               if (power_button_countdown == 0) {
+                       /* Signal init to do the ctrlaltdel action, this will bypass
+                        * init if it hasn't started and do a kernel_restart.
+                        */
+                       ctrl_alt_del();
+
+                       /* Change the state of the power LED to "blink" */
+                       gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
+               }
+               power_button_countdown--;
+
+       } else {
+               power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+       }
+
+       mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
+{
+       /* This is the paper-clip reset, it shuts the machine down directly. */
+       machine_power_off();
+
+       return IRQ_HANDLED;
+}
+
+static int __init dsmg600_power_init(void)
+{
+       if (!(machine_is_dsmg600()))
+               return 0;
+
+       if (request_irq(DSMG600_RB_IRQ, &dsmg600_reset_handler,
+               IRQF_DISABLED | IRQF_TRIGGER_LOW, "DSM-G600 reset button",
+               NULL) < 0) {
+
+               printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+                       DSMG600_RB_IRQ);
+
+               return -EIO;
+       }
+
+       /* The power button on the D-Link DSM-G600 is on GPIO 15, but
+        * it cannot handle interrupts on that GPIO line.  So we'll
+        * have to poll it with a kernel timer.
+        */
+
+       /* Make sure that the power button GPIO is set up as an input */
+       gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
+
+       /* Set the initial value for the power button IRQ handler */
+       power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+       mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+
+       return 0;
+}
+
+static void __exit dsmg600_power_exit(void)
+{
+       if (!(machine_is_dsmg600()))
+               return;
+
+       del_timer_sync(&dsmg600_power_timer);
+
+       free_irq(DSMG600_RB_IRQ, NULL);
+}
+
+module_init(dsmg600_power_init);
+module_exit(dsmg600_power_exit);
+
+MODULE_AUTHOR("Michael Westerhof <mwester@dls.net>");
+MODULE_DESCRIPTION("DSM-G600 Power/Reset driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
new file mode 100644 (file)
index 0000000..1caff65
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * DSM-G600 board-setup
+ *
+ * Copyright (C) 2006 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data dsmg600_flash_data = {
+       .map_name               = "cfi_probe",
+       .width                  = 2,
+};
+
+static struct resource dsmg600_flash_resource = {
+       .flags                  = IORESOURCE_MEM,
+};
+
+static struct platform_device dsmg600_flash = {
+       .name                   = "IXP4XX-Flash",
+       .id                     = 0,
+       .dev.platform_data      = &dsmg600_flash_data,
+       .num_resources          = 1,
+       .resource               = &dsmg600_flash_resource,
+};
+
+static struct ixp4xx_i2c_pins dsmg600_i2c_gpio_pins = {
+       .sda_pin                = DSMG600_SDA_PIN,
+       .scl_pin                = DSMG600_SCL_PIN,
+};
+
+static struct platform_device dsmg600_i2c_controller = {
+       .name                   = "IXP4XX-I2C",
+       .id                     = 0,
+       .dev.platform_data      = &dsmg600_i2c_gpio_pins,
+};
+
+#ifdef CONFIG_LEDS_CLASS
+static struct resource dsmg600_led_resources[] = {
+       {
+               .name           = "power",
+               .start          = DSMG600_LED_PWR_GPIO,
+               .end            = DSMG600_LED_PWR_GPIO,
+               .flags          = IXP4XX_GPIO_HIGH,
+       },
+       {
+               .name           = "wlan",
+               .start          = DSMG600_LED_WLAN_GPIO,
+               .end            = DSMG600_LED_WLAN_GPIO,
+               .flags          = IXP4XX_GPIO_LOW,
+       },
+};
+
+static struct platform_device dsmg600_leds = {
+        .name                   = "IXP4XX-GPIO-LED",
+        .id                     = -1,
+        .num_resources          = ARRAY_SIZE(dsmg600_led_resources),
+        .resource               = dsmg600_led_resources,
+};
+#endif
+
+static struct resource dsmg600_uart_resources[] = {
+       {
+               .start          = IXP4XX_UART1_BASE_PHYS,
+               .end            = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = IXP4XX_UART2_BASE_PHYS,
+               .end            = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+               .flags          = IORESOURCE_MEM,
+       }
+};
+
+static struct plat_serial8250_port dsmg600_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART1_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART1,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { }
+};
+
+static struct platform_device dsmg600_uart = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM,
+       .dev.platform_data      = dsmg600_uart_data,
+       .num_resources          = ARRAY_SIZE(dsmg600_uart_resources),
+       .resource               = dsmg600_uart_resources,
+};
+
+static struct platform_device *dsmg600_devices[] __initdata = {
+       &dsmg600_i2c_controller,
+       &dsmg600_flash,
+};
+
+static void dsmg600_power_off(void)
+{
+       /* enable the pwr cntl gpio */
+       gpio_line_config(DSMG600_PO_GPIO, IXP4XX_GPIO_OUT);
+
+       /* poweroff */
+       gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
+}
+
+static void __init dsmg600_init(void)
+{
+       ixp4xx_sys_init();
+
+       /* Make sure that GPIO14 and GPIO15 are not used as clocks */
+       *IXP4XX_GPIO_GPCLKR = 0;
+
+       dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+       dsmg600_flash_resource.end =
+               IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+       pm_power_off = dsmg600_power_off;
+
+       /* The UART is required on the DSM-G600 (Redboot cannot use the
+        * NIC) -- do it here so that it does *not* get removed if
+        * platform_add_devices fails!
+         */
+        (void)platform_device_register(&dsmg600_uart);
+
+       platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
+
+#ifdef CONFIG_LEDS_CLASS
+        /* We don't care whether or not this works. */
+        (void)platform_device_register(&dsmg600_leds);
+#endif
+}
+
+static void __init dsmg600_fixup(struct machine_desc *desc,
+                struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+       /* The xtal on this machine is non-standard. */
+        ixp4xx_timer_freq = DSMG600_FREQ;
+}
+
+MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
+       /* Maintainer: www.nslu2-linux.org */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
+       .boot_params    = 0x00000100,
+       .fixup          = dsmg600_fixup,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .init_machine   = dsmg600_init,
+MACHINE_END
index 99c1dc8..4087960 100644 (file)
@@ -66,7 +66,7 @@ struct hw_pci ixdp425_pci __initdata = {
 int __init ixdp425_pci_init(void)
 {
        if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
-                       machine_is_ixdp465())
+                       machine_is_ixdp465() || machine_is_kixrp435())
                pci_common_init(&ixdp425_pci);
        return 0;
 }
index 04b1d56..ec4f079 100644 (file)
@@ -115,6 +115,11 @@ static void __init ixdp425_init(void)
        ixdp425_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+       if (cpu_is_ixp43x()) {
+               ixdp425_uart.num_resources = 1;
+               ixdp425_uart_data[1].flags = 0;
+       }
+
        platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
 }
 
@@ -156,3 +161,16 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
        .init_machine   = ixdp425_init,
 MACHINE_END
 #endif
+
+#ifdef CONFIG_MACH_KIXRP435
+MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
+       /* Maintainer: MontaVista Software, Inc. */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = ixdp425_init,
+MACHINE_END
+#endif
index 0b938e8..9472bbe 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
index 5760f8c..9b28389 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
index 15b9577..66e1ed3 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
index 8175ba9..8584ed1 100644 (file)
@@ -3,19 +3,30 @@ if ARCH_NS9XXX
 menu "NS9xxx Implementations"
 
 config MACH_CC9P9360DEV
-       bool "Connect Core 9P 9360 on an A9M9750 Devboard"
+       bool "ConnectCore 9P 9360 on an A9M9750 Devboard"
        select PROCESSOR_NS9360
        select BOARD_A9M9750DEV
        help
-         Say Y here if you are using the Digi Connect Core 9P 9360
+         Say Y here if you are using the Digi ConnectCore 9P 9360
          on an A9M9750 Development Board.
 
+config MACH_CC9P9360JS
+       bool "ConnectCore 9P 9360 on a JSCC9P9360 Devboard"
+       select PROCESSOR_NS9360
+       select BOARD_JSCC9P9360
+       help
+         Say Y here if you are using the Digi ConnectCore 9P 9360
+         on an JSCC9P9360 Development Board.
+
 config PROCESSOR_NS9360
        bool
 
 config BOARD_A9M9750DEV
        bool
 
+config BOARD_JSCC9P9360
+       bool
+
 endmenu
 
 endif
index 91e945f..53213a6 100644 (file)
@@ -3,3 +3,4 @@ obj-y := irq.o time.o generic.o
 obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
 
 obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
+obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o
diff --git a/arch/arm/mach-ns9xxx/board-jscc9p9360.c b/arch/arm/mach-ns9xxx/board-jscc9p9360.c
new file mode 100644 (file)
index 0000000..4bd3eec
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-ns9xxx/board-jscc9p9360.c
+ *
+ * Copyright (C) 2006,2007 by Digi International Inc.
+ * 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 "board-jscc9p9360.h"
+
+void __init board_jscc9p9360_init_machine(void)
+{
+       /* TODO: reserve GPIOs for push buttons, etc pp */
+}
+
diff --git a/arch/arm/mach-ns9xxx/board-jscc9p9360.h b/arch/arm/mach-ns9xxx/board-jscc9p9360.h
new file mode 100644 (file)
index 0000000..1a81a07
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * arch/arm/mach-ns9xxx/board-jscc9p9360.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * 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/init.h>
+
+void __init board_jscc9p9360_init_machine(void);
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
new file mode 100644 (file)
index 0000000..d09d5fa
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "board-jscc9p9360.h"
+#include "generic.h"
+
+static void __init mach_cc9p9360js_init_machine(void)
+{
+       ns9xxx_init_machine();
+       board_jscc9p9360_init_machine();
+}
+
+MACHINE_START(CC9P9360DEV, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
+       .map_io = ns9xxx_map_io,
+       .init_irq = ns9xxx_init_irq,
+       .init_machine = mach_cc9p9360js_init_machine,
+       .timer = &ns9xxx_timer,
+       .boot_params = 0x100,
+MACHINE_END
index 410d3e7..0733078 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
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 1b7e4a5..85e048b 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
-struct sys_timer omap_timer;
 
-/*
- * ---------------------------------------------------------------------------
- * MPU timer
- * ---------------------------------------------------------------------------
- */
 #define OMAP_MPU_TIMER_BASE            OMAP_MPU_TIMER1_BASE
 #define OMAP_MPU_TIMER_OFFSET          0x100
 
@@ -88,21 +86,6 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
        return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
 }
 
-/*
- * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
- * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
- * with 0. This divides the 13MHz input by 2, and is undocumented.
- */
-#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
-/* REVISIT: This ifdef construct should be replaced by a query to clock
- * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
- */
-#define MPU_TICKS_PER_SEC              (13000000 / 2)
-#else
-#define MPU_TICKS_PER_SEC              (12000000 / 2)
-#endif
-
-#define MPU_TIMER_TICK_PERIOD          ((MPU_TICKS_PER_SEC / HZ) - 1)
 
 typedef struct {
        u32 cntl;                       /* CNTL_TIMER, R/W */
@@ -120,98 +103,164 @@ static inline unsigned long omap_mpu_timer_read(int nr)
        return timer->read_tim;
 }
 
-static inline void omap_mpu_timer_start(int nr, unsigned long load_val)
+static inline void omap_mpu_set_autoreset(int nr)
 {
        volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
 
-       timer->cntl = MPU_TIMER_CLOCK_ENABLE;
-       udelay(1);
-       timer->load_tim = load_val;
-        udelay(1);
-       timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
+       timer->cntl = timer->cntl | MPU_TIMER_AR;
 }
 
-unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
+static inline void omap_mpu_remove_autoreset(int nr)
 {
-       unsigned long long nsec;
+       volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
 
-       nsec = cycles_2_ns((unsigned long long)nr_ticks);
-       return (unsigned long)nsec / 1000;
+       timer->cntl = timer->cntl & ~MPU_TIMER_AR;
 }
 
-/*
- * Last processed system timer interrupt
- */
-static unsigned long omap_mpu_timer_last = 0;
+static inline void omap_mpu_timer_start(int nr, unsigned long load_val,
+                                       int autoreset)
+{
+       volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+       unsigned int timerflags = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST);
+
+       if (autoreset) timerflags |= MPU_TIMER_AR;
+
+       timer->cntl = MPU_TIMER_CLOCK_ENABLE;
+       udelay(1);
+       timer->load_tim = load_val;
+        udelay(1);
+       timer->cntl = timerflags;
+}
 
 /*
- * Returns elapsed usecs since last system timer interrupt
+ * ---------------------------------------------------------------------------
+ * MPU timer 1 ... count down to zero, interrupt, reload
+ * ---------------------------------------------------------------------------
  */
-static unsigned long omap_mpu_timer_gettimeoffset(void)
+static int omap_mpu_set_next_event(unsigned long cycles,
+                                   struct clock_event_device *evt)
 {
-       unsigned long now = 0 - omap_mpu_timer_read(0);
-       unsigned long elapsed = now - omap_mpu_timer_last;
+       omap_mpu_timer_start(0, cycles, 0);
+       return 0;
+}
 
-       return omap_mpu_timer_ticks_to_usecs(elapsed);
+static void omap_mpu_set_mode(enum clock_event_mode mode,
+                             struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               omap_mpu_set_autoreset(0);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               omap_mpu_remove_autoreset(0);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               break;
+       }
 }
 
-/*
- * Elapsed time between interrupts is calculated using timer0.
- * Latency during the interrupt is calculated using timer1.
- * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
- */
-static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
+static struct clock_event_device clockevent_mpu_timer1 = {
+       .name           = "mpu_timer1",
+       .features       = CLOCK_EVT_FEAT_PERIODIC, CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .set_next_event = omap_mpu_set_next_event,
+       .set_mode       = omap_mpu_set_mode,
+};
+
+static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
 {
-       unsigned long now, latency;
+       struct clock_event_device *evt = &clockevent_mpu_timer1;
 
-       write_seqlock(&xtime_lock);
-       now = 0 - omap_mpu_timer_read(0);
-       latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
-       omap_mpu_timer_last = now - latency;
-       timer_tick();
-       write_sequnlock(&xtime_lock);
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
 
-static struct irqaction omap_mpu_timer_irq = {
-       .name           = "mpu timer",
+static struct irqaction omap_mpu_timer1_irq = {
+       .name           = "mpu_timer1",
        .flags          = IRQF_DISABLED | IRQF_TIMER,
-       .handler        = omap_mpu_timer_interrupt,
+       .handler        = omap_mpu_timer1_interrupt,
 };
 
-static unsigned long omap_mpu_timer1_overflows;
-static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
+static __init void omap_init_mpu_timer(unsigned long rate)
+{
+       set_cyc2ns_scale(rate / 1000);
+
+       setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
+       omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
+
+       clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC,
+                                           clockevent_mpu_timer1.shift);
+       clockevent_mpu_timer1.max_delta_ns =
+               clockevent_delta2ns(-1, &clockevent_mpu_timer1);
+       clockevent_mpu_timer1.min_delta_ns =
+               clockevent_delta2ns(1, &clockevent_mpu_timer1);
+
+       clockevent_mpu_timer1.cpumask = cpumask_of_cpu(0);
+       clockevents_register_device(&clockevent_mpu_timer1);
+}
+
+
+/*
+ * ---------------------------------------------------------------------------
+ * MPU timer 2 ... free running 32-bit clock source and scheduler clock
+ * ---------------------------------------------------------------------------
+ */
+
+static unsigned long omap_mpu_timer2_overflows;
+
+static irqreturn_t omap_mpu_timer2_interrupt(int irq, void *dev_id)
 {
-       omap_mpu_timer1_overflows++;
+       omap_mpu_timer2_overflows++;
        return IRQ_HANDLED;
 }
 
-static struct irqaction omap_mpu_timer1_irq = {
-       .name           = "mpu timer1 overflow",
+static struct irqaction omap_mpu_timer2_irq = {
+       .name           = "mpu_timer2",
        .flags          = IRQF_DISABLED,
-       .handler        = omap_mpu_timer1_interrupt,
+       .handler        = omap_mpu_timer2_interrupt,
 };
 
-static __init void omap_init_mpu_timer(void)
+static cycle_t mpu_read(void)
 {
-       set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
-       omap_timer.offset = omap_mpu_timer_gettimeoffset;
-       setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
-       setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
-       omap_mpu_timer_start(0, 0xffffffff);
-       omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
+       return ~omap_mpu_timer_read(1);
+}
+
+static struct clocksource clocksource_mpu = {
+       .name           = "mpu_timer2",
+       .rating         = 300,
+       .read           = mpu_read,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 24,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init omap_init_clocksource(unsigned long rate)
+{
+       static char err[] __initdata = KERN_ERR
+                       "%s: can't register clocksource!\n";
+
+       clocksource_mpu.mult
+               = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
+
+       setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
+       omap_mpu_timer_start(1, ~0, 1);
+
+       if (clocksource_register(&clocksource_mpu))
+               printk(err, clocksource_mpu.name);
 }
 
+
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
 unsigned long long sched_clock(void)
 {
-       unsigned long ticks = 0 - omap_mpu_timer_read(0);
+       unsigned long ticks = 0 - omap_mpu_timer_read(1);
        unsigned long long ticks64;
 
-       ticks64 = omap_mpu_timer1_overflows;
+       ticks64 = omap_mpu_timer2_overflows;
        ticks64 <<= 32;
        ticks64 |= ticks;
 
@@ -225,10 +274,21 @@ unsigned long long sched_clock(void)
  */
 static void __init omap_timer_init(void)
 {
-       omap_init_mpu_timer();
+       struct clk      *ck_ref = clk_get(NULL, "ck_ref");
+       unsigned long   rate;
+
+       BUG_ON(IS_ERR(ck_ref));
+
+       rate = clk_get_rate(ck_ref);
+       clk_put(ck_ref);
+
+       /* PTV = 0 */
+       rate /= 2;
+
+       omap_init_mpu_timer(rate);
+       omap_init_clocksource(rate);
 }
 
 struct sys_timer omap_timer = {
        .init           = omap_timer_init,
-       .offset         = NULL,         /* Initialized later */
 };
index b8cb79f..64b08b7 100644 (file)
@@ -164,9 +164,9 @@ void pxa_set_cken(int clock, int enable)
        local_irq_save(flags);
 
        if (enable)
-               CKEN |= clock;
+               CKEN |= (1 << clock);
        else
-               CKEN &= ~clock;
+               CKEN &= ~(1 << clock);
 
        local_irq_restore(flags);
 }
index f815678..4619d5f 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -39,11 +38,33 @@ static void pxa_unmask_low_irq(unsigned int irq)
        ICMR |= (1 << (irq + PXA_IRQ_SKIP));
 }
 
+static int pxa_set_wake(unsigned int irq, unsigned int on)
+{
+       u32     mask;
+
+       switch (irq) {
+       case IRQ_RTCAlrm:
+               mask = PWER_RTC;
+               break;
+#ifdef CONFIG_PXA27x
+       /* REVISIT can handle USBH1, USBH2, USB, MSL, USIM, ... */
+#endif
+       default:
+               return -EINVAL;
+       }
+       if (on)
+               PWER |= mask;
+       else
+               PWER &= ~mask;
+       return 0;
+}
+
 static struct irq_chip pxa_internal_chip_low = {
        .name           = "SC",
        .ack            = pxa_mask_low_irq,
        .mask           = pxa_mask_low_irq,
        .unmask         = pxa_unmask_low_irq,
+       .set_wake       = pxa_set_wake,
 };
 
 #if PXA_INTERNAL_IRQS > 32
@@ -71,6 +92,26 @@ static struct irq_chip pxa_internal_chip_high = {
 
 #endif
 
+/* Note that if an input/irq line ever gets changed to an output during
+ * suspend, the relevant PWER, PRER, and PFER bits should be cleared.
+ */
+#ifdef CONFIG_PXA27x
+
+/* PXA27x:  Various gpios can issue wakeup events.  This logic only
+ * handles the simple cases, not the WEMUX2 and WEMUX3 options
+ */
+#define PXA27x_GPIO_NOWAKE_MASK \
+       ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
+#define        WAKEMASK(gpio) \
+       (((gpio) <= 15) \
+               ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
+               : ((gpio == 35) ? (1 << 24) : 0))
+#else
+
+/* pxa 210, 250, 255, 26x:  gpios 0..15 can issue wakeups */
+#define        WAKEMASK(gpio) (((gpio) <= 15) ? (1 << (gpio)) : 0)
+#endif
+
 /*
  * PXA GPIO edge detection for IRQs:
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
@@ -84,9 +125,11 @@ static long GPIO_IRQ_mask[4];
 static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
 {
        int gpio, idx;
+       u32 mask;
 
        gpio = IRQ_TO_GPIO(irq);
        idx = gpio >> 5;
+       mask = WAKEMASK(gpio);
 
        if (type == IRQT_PROBE) {
            /* Don't mess with enabled GPIOs using preconfigured edges or
@@ -106,14 +149,20 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
        if (type & __IRQT_RISEDGE) {
                /* printk("rising "); */
                __set_bit (gpio, GPIO_IRQ_rising_edge);
-       } else
+               PRER |= mask;
+       } else {
                __clear_bit (gpio, GPIO_IRQ_rising_edge);
+               PRER &= ~mask;
+       }
 
        if (type & __IRQT_FALEDGE) {
                /* printk("falling "); */
                __set_bit (gpio, GPIO_IRQ_falling_edge);
-       } else
+               PFER |= mask;
+       } else {
                __clear_bit (gpio, GPIO_IRQ_falling_edge);
+               PFER &= ~mask;
+       }
 
        /* printk("edges\n"); */
 
@@ -131,12 +180,29 @@ static void pxa_ack_low_gpio(unsigned int irq)
        GEDR0 = (1 << (irq - IRQ_GPIO0));
 }
 
+static int pxa_set_gpio_wake(unsigned int irq, unsigned int on)
+{
+       int     gpio = IRQ_TO_GPIO(irq);
+       u32     mask = WAKEMASK(gpio);
+
+       if (!mask)
+               return -EINVAL;
+
+       if (on)
+               PWER |= mask;
+       else
+               PWER &= ~mask;
+       return 0;
+}
+
+
 static struct irq_chip pxa_low_gpio_chip = {
        .name           = "GPIO-l",
        .ack            = pxa_ack_low_gpio,
        .mask           = pxa_mask_low_irq,
        .unmask         = pxa_unmask_low_irq,
        .set_type       = pxa_gpio_irq_type,
+       .set_wake       = pxa_set_gpio_wake,
 };
 
 /*
@@ -245,6 +311,7 @@ static struct irq_chip pxa_muxed_gpio_chip = {
        .mask           = pxa_mask_muxed_gpio,
        .unmask         = pxa_unmask_muxed_gpio,
        .set_type       = pxa_gpio_irq_type,
+       .set_wake       = pxa_set_gpio_wake,
 };
 
 
index 8e27a64..e309766 100644 (file)
@@ -234,7 +234,7 @@ static void lpd270_backlight_power(int on)
 {
        if (on) {
                pxa_gpio_mode(GPIO16_PWM0_MD);
-               pxa_set_cken(CKEN0_PWM0, 1);
+               pxa_set_cken(CKEN_PWM0, 1);
                PWM_CTRL0 = 0;
                PWM_PWDUTY0 = 0x3ff;
                PWM_PERVAL0 = 0x3ff;
@@ -242,7 +242,7 @@ static void lpd270_backlight_power(int on)
                PWM_CTRL0 = 0;
                PWM_PWDUTY0 = 0x0;
                PWM_PERVAL0 = 0x3FF;
-               pxa_set_cken(CKEN0_PWM0, 0);
+               pxa_set_cken(CKEN_PWM0, 0);
        }
 }
 
index 055de7f..6377b2e 100644 (file)
@@ -220,7 +220,7 @@ static struct resource pxa_ssp_resources[] = {
 
 static struct pxa2xx_spi_master pxa_ssp_master_info = {
        .ssp_type       = PXA25x_SSP,
-       .clock_enable   = CKEN3_SSP,
+       .clock_enable   = CKEN_SSP,
        .num_chipselect = 0,
 };
 
index 56d94d8..ed99a81 100644 (file)
@@ -266,7 +266,7 @@ static void mainstone_backlight_power(int on)
 {
        if (on) {
                pxa_gpio_mode(GPIO16_PWM0_MD);
-               pxa_set_cken(CKEN0_PWM0, 1);
+               pxa_set_cken(CKEN_PWM0, 1);
                PWM_CTRL0 = 0;
                PWM_PWDUTY0 = 0x3ff;
                PWM_PERVAL0 = 0x3ff;
@@ -274,7 +274,7 @@ static void mainstone_backlight_power(int on)
                PWM_CTRL0 = 0;
                PWM_PWDUTY0 = 0x0;
                PWM_PERVAL0 = 0x3FF;
-               pxa_set_cken(CKEN0_PWM0, 0);
+               pxa_set_cken(CKEN_PWM0, 0);
        }
 }
 
index 74eeada..c64bab4 100644 (file)
@@ -140,9 +140,9 @@ void pxa_cpu_pm_enter(suspend_state_t state)
        extern void pxa_cpu_resume(void);
 
        if (state == PM_SUSPEND_STANDBY)
-               CKEN = CKEN22_MEMC | CKEN9_OSTIMER | CKEN16_LCD |CKEN0_PWM0;
+               CKEN = CKEN_MEMC | CKEN_OSTIMER | CKEN_LCD | CKEN_PWM0;
        else
-               CKEN = CKEN22_MEMC | CKEN9_OSTIMER;
+               CKEN = CKEN_MEMC | CKEN_OSTIMER;
 
        /* ensure voltage-change sequencer not initiated, which hangs */
        PCFR &= ~PCFR_FVC;
index 6cc2027..71766ac 100644 (file)
@@ -52,13 +52,13 @@ struct ssp_info_ {
  */
 static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = {
 #if defined (CONFIG_PXA27x)
-       {IRQ_SSP,       CKEN23_SSP1},
-       {IRQ_SSP2,      CKEN3_SSP2},
-       {IRQ_SSP3,      CKEN4_SSP3},
+       {IRQ_SSP,       CKEN_SSP1},
+       {IRQ_SSP2,      CKEN_SSP2},
+       {IRQ_SSP3,      CKEN_SSP3},
 #else
-       {IRQ_SSP,       CKEN3_SSP},
-       {IRQ_NSSP,      CKEN9_NSSP},
-       {IRQ_ASSP,      CKEN10_ASSP},
+       {IRQ_SSP,       CKEN_SSP},
+       {IRQ_NSSP,      CKEN_NSSP},
+       {IRQ_ASSP,      CKEN_ASSP},
 #endif
 };
 
index 208a2b5..570cf93 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/serial_8250.h>
+#include <linux/pata_platform.h>
 
 #include <asm/elf.h>
 #include <asm/io.h>
@@ -159,11 +160,45 @@ static struct platform_device serial_device = {
        },
 };
 
+static struct pata_platform_info pata_platform_data = {
+       .ioport_shift           = 2,
+};
+
+static struct resource pata_resources[] = {
+       [0] = {
+               .start          = 0x030107c0,
+               .end            = 0x030107df,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = 0x03010fd8,
+               .end            = 0x03010fdb,
+               .flags          = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start          = IRQ_HARDDISK,
+               .end            = IRQ_HARDDISK,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device pata_device = {
+       .name                   = "pata_platform",
+       .id                     = -1,
+       .num_resources          = ARRAY_SIZE(pata_resources),
+       .resource               = pata_resources,
+       .dev                    = {
+               .platform_data  = &pata_platform_data,
+               .coherent_dma_mask = ~0,        /* grumble */
+       },
+};
+
 static struct platform_device *devs[] __initdata = {
        &iomd_device,
        &kbd_device,
        &serial_device,
        &acornfb_device,
+       &pata_device,
 };
 
 static int __init rpc_init(void)
index daeba42..76a7cb1 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/mach-types.h>
index 53cbdaa..f5c5c53 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/plat-s3c24xx/cpu.h>
index 72f2cc4..bc308ce 100644 (file)
@@ -160,17 +160,11 @@ static struct platform_device *amlm5900_devices[] __initdata = {
 #endif
 };
 
-static struct s3c24xx_board amlm5900_board __initdata = {
-       .devices       = amlm5900_devices,
-       .devices_count = ARRAY_SIZE(amlm5900_devices)
-};
-
 void __init amlm5900_map_io(void)
 {
        s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
-       s3c24xx_set_board(&amlm5900_board);
 }
 
 #ifdef CONFIG_FB_S3C2410
@@ -247,6 +241,7 @@ static void __init amlm5900_init(void)
 #ifdef CONFIG_FB_S3C2410
        s3c24xx_fb_set_platdata(&amlm5900_lcd_info);
 #endif
+       platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices));
 }
 
 MACHINE_START(AML_M5900, "AML_M5900")
index 7b81296..f01de80 100644 (file)
@@ -464,13 +464,6 @@ static struct clk *bast_clocks[] = {
        &s3c24xx_uclk,
 };
 
-static struct s3c24xx_board bast_board __initdata = {
-       .devices       = bast_devices,
-       .devices_count = ARRAY_SIZE(bast_devices),
-       .clocks        = bast_clocks,
-       .clocks_count  = ARRAY_SIZE(bast_clocks),
-};
-
 static void __init bast_map_io(void)
 {
        /* initialise the clocks */
@@ -486,19 +479,22 @@ static void __init bast_map_io(void)
 
        s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
+       s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
+
        s3c_device_nand.dev.platform_data = &bast_nand_info;
        s3c_device_i2c.dev.platform_data = &bast_i2c_info;
 
        s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
-       s3c24xx_set_board(&bast_board);
+
        usb_simtec_init();
 }
 
 static void __init bast_init(void)
 {
        s3c24xx_fb_set_platdata(&bast_lcd_info);
+       platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
 }
 
 MACHINE_START(BAST, "Simtec-BAST")
index d052ab2..5d5f00e 100644 (file)
@@ -129,7 +129,6 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
 };
 
 
-
 /**
  * Set lcd on or off
  **/
@@ -188,17 +187,11 @@ static struct platform_device *h1940_devices[] __initdata = {
        &s3c_device_leds,
 };
 
-static struct s3c24xx_board h1940_board __initdata = {
-       .devices       = h1940_devices,
-       .devices_count = ARRAY_SIZE(h1940_devices)
-};
-
 static void __init h1940_map_io(void)
 {
        s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
-       s3c24xx_set_board(&h1940_board);
 
        /* setup PM */
 
@@ -232,6 +225,8 @@ static void __init h1940_init(void)
              | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
              | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
        writel(tmp, S3C2410_UPLLCON);
+
+       platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 }
 
 MACHINE_START(H1940, "IPAQ-H1940")
index 261aa4c..412e50c 100644 (file)
@@ -90,17 +90,11 @@ static struct s3c2410_platform_i2c n30_i2ccfg = {
        .max_freq       = 10*1000,
 };
 
-static struct s3c24xx_board n30_board __initdata = {
-       .devices       = n30_devices,
-       .devices_count = ARRAY_SIZE(n30_devices)
-};
-
 static void __init n30_map_io(void)
 {
        s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
-       s3c24xx_set_board(&n30_board);
 }
 
 static void __init n30_init_irq(void)
@@ -120,6 +114,8 @@ static void __init n30_init(void)
        s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
                              S3C2410_MISCCR_USBSUSPND0 |
                              S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+       platform_add_devices(n30_devices, ARRAY_SIZE(n30_devices));
 }
 
 MACHINE_START(N30, "Acer-N30")
index c78ab75..1f899fa 100644 (file)
@@ -100,20 +100,17 @@ static struct platform_device *otom11_devices[] __initdata = {
        &otom_device_nor,
 };
 
-static struct s3c24xx_board otom11_board __initdata = {
-       .devices       = otom11_devices,
-       .devices_count = ARRAY_SIZE(otom11_devices)
-};
-
-
 static void __init otom11_map_io(void)
 {
        s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
-       s3c24xx_set_board(&otom11_board);
 }
 
+static void __init otom11_init(void)
+{
+       platform_add_devices(otom11_devices, ARRAY_SIZE(otom11_devices));
+}
 
 MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
@@ -121,6 +118,7 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = otom11_map_io,
+       .init_machine   = otom11_init,
        .init_irq       = s3c24xx_init_irq,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index c6a4159..9cc4253 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
-#include <linux/mmc/protocol.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 
@@ -331,11 +330,6 @@ static struct platform_device *qt2410_devices[] __initdata = {
        &qt2410_led,
 };
 
-static struct s3c24xx_board qt2410_board __initdata = {
-       .devices       = qt2410_devices,
-       .devices_count = ARRAY_SIZE(qt2410_devices)
-};
-
 static struct mtd_partition qt2410_nand_part[] = {
        [0] = {
                .name   = "U-Boot",
@@ -405,7 +399,6 @@ static void __init qt2410_map_io(void)
        s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
        s3c24xx_init_clocks(12*1000*1000);
        s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
-       s3c24xx_set_board(&qt2410_board);
 }
 
 static void __init qt2410_machine_init(void)
@@ -432,6 +425,7 @@ static void __init qt2410_machine_init(void)
 
        s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
 
+       platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
        s3c2410_pm_init();
 }
 
index 57b8a80..5852d30 100644 (file)
@@ -94,17 +94,17 @@ static struct platform_device *smdk2410_devices[] __initdata = {
        &s3c_device_iis,
 };
 
-static struct s3c24xx_board smdk2410_board __initdata = {
-       .devices       = smdk2410_devices,
-       .devices_count = ARRAY_SIZE(smdk2410_devices)
-};
-
 static void __init smdk2410_map_io(void)
 {
        s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
-       s3c24xx_set_board(&smdk2410_board);
+}
+
+static void __init smdk2410_init(void)
+{
+       platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));
+       smdk_machine_init();
 }
 
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
@@ -115,7 +115,7 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = smdk2410_map_io,
        .init_irq       = s3c24xx_init_irq,
-       .init_machine   = smdk_machine_init,
+       .init_machine   = smdk2410_init,
        .timer          = &s3c24xx_timer,
 MACHINE_END
 
index c947c75..7b624bb 100644 (file)
@@ -384,13 +384,6 @@ static struct clk *vr1000_clocks[] = {
        &s3c24xx_uclk,
 };
 
-static struct s3c24xx_board vr1000_board __initdata = {
-       .devices       = vr1000_devices,
-       .devices_count = ARRAY_SIZE(vr1000_devices),
-       .clocks        = vr1000_clocks,
-       .clocks_count  = ARRAY_SIZE(vr1000_clocks),
-};
-
 static void vr1000_power_off(void)
 {
        s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_OUTP);
@@ -412,15 +405,19 @@ static void __init vr1000_map_io(void)
 
        s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
+       s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks));
+
        pm_power_off = vr1000_power_off;
 
        s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
-       s3c24xx_set_board(&vr1000_board);
-       usb_simtec_init();
 }
 
+static void __init vr1000_init(void)
+{
+       platform_add_devices(vr1000_devices, ARRAY_SIZE(vr1000_devices));
+}
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
@@ -428,6 +425,7 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
        .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = vr1000_map_io,
+       .init_machine   = vr1000_init,
        .init_irq       = s3c24xx_init_irq,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index befc5fd..d5be5d0 100644 (file)
@@ -47,6 +47,15 @@ config MACH_S3C2413
          machine_is_s3c2413() will work when MACH_SMDK2413 is
          selected
 
+config MACH_SMDK2412
+       bool "SMDK2412"
+       select MACH_SMDK2413
+       help
+         Say Y here if you are using an SMDK2412
+
+         Note, this shares support with SMDK2413, so will automatically
+         select MACH_SMDK2413.
+
 config MACH_VSTMS
        bool "VMSTMS"
        select CPU_S3C2412
index e89dbdc..f0d6682 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
index b5befce..063af09 100644 (file)
@@ -110,11 +110,6 @@ static struct platform_device *smdk2413_devices[] __initdata = {
        &s3c_device_usbgadget,
 };
 
-static struct s3c24xx_board smdk2413_board __initdata = {
-       .devices       = smdk2413_devices,
-       .devices_count = ARRAY_SIZE(smdk2413_devices)
-};
-
 static void __init smdk2413_fixup(struct machine_desc *desc,
                                  struct tag *tags, char **cmdline,
                                  struct meminfo *mi)
@@ -132,7 +127,6 @@ static void __init smdk2413_map_io(void)
        s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
-       s3c24xx_set_board(&smdk2413_board);
 }
 
 static void __init smdk2413_machine_init(void)
@@ -149,6 +143,7 @@ static void __init smdk2413_machine_init(void)
 
        s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
 
+       platform_add_devices(smdk2413_devices, ARRAY_SIZE(smdk2413_devices));
        smdk_machine_init();
 }
 
index 4231b54..f2fbd65 100644 (file)
@@ -129,11 +129,6 @@ static struct platform_device *vstms_devices[] __initdata = {
        &s3c_device_nand,
 };
 
-static struct s3c24xx_board vstms_board __initdata = {
-       .devices       = vstms_devices,
-       .devices_count = ARRAY_SIZE(vstms_devices)
-};
-
 static void __init vstms_fixup(struct machine_desc *desc,
                                  struct tag *tags, char **cmdline,
                                  struct meminfo *mi)
@@ -153,7 +148,11 @@ static void __init vstms_map_io(void)
        s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
-       s3c24xx_set_board(&vstms_board);
+}
+
+static void __init vstms_init(void)
+{
+       platform_add_devices(vstms_devices, ARRAY_SIZE(vstms_devices));
 }
 
 MACHINE_START(VSTMS, "VSTMS")
@@ -163,6 +162,7 @@ MACHINE_START(VSTMS, "VSTMS")
 
        .fixup          = vstms_fixup,
        .init_irq       = s3c24xx_init_irq,
+       .init_machine   = vstms_init,
        .map_io         = vstms_map_io,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index 1069d13..a87608b 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
index 3f0288e..b5d387e 100644 (file)
@@ -281,13 +281,6 @@ static struct clk *anubis_clocks[] = {
        &s3c24xx_uclk,
 };
 
-static struct s3c24xx_board anubis_board __initdata = {
-       .devices       = anubis_devices,
-       .devices_count = ARRAY_SIZE(anubis_devices),
-       .clocks        = anubis_clocks,
-       .clocks_count  = ARRAY_SIZE(anubis_clocks),
-};
-
 static void __init anubis_map_io(void)
 {
        /* initialise the clocks */
@@ -303,23 +296,31 @@ static void __init anubis_map_io(void)
 
        s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
+       s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
+
        s3c_device_nand.dev.platform_data = &anubis_nand_info;
 
        s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
-       s3c24xx_set_board(&anubis_board);
 
        /* ensure that the GPIO is setup */
        s3c2410_gpio_setpin(S3C2410_GPA0, 1);
 }
 
+static void __init anubis_init(void)
+{
+       platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
+}
+
+
 MACHINE_START(ANUBIS, "Simtec-Anubis")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
        .phys_io        = S3C2410_PA_UART,
        .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = anubis_map_io,
+       .init_machine   = anubis_init,
        .init_irq       = s3c24xx_init_irq,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index 6d551d8..5e61f21 100644 (file)
@@ -116,12 +116,6 @@ static struct platform_device *nexcoder_devices[] __initdata = {
        &nexcoder_device_nor,
 };
 
-static struct s3c24xx_board nexcoder_board __initdata = {
-       .devices       = nexcoder_devices,
-       .devices_count = ARRAY_SIZE(nexcoder_devices),
-};
-
-
 static void __init nexcoder_sensorboard_init(void)
 {
        // Initialize SCCB bus
@@ -142,10 +136,14 @@ static void __init nexcoder_map_io(void)
        s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
-       s3c24xx_set_board(&nexcoder_board);
+
        nexcoder_sensorboard_init();
 }
 
+static void __init nexcoder_init(void)
+{
+       platform_add_devices(nexcoder_devices, ARRAY_SIZE(nexcoder_devices));
+};
 
 MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
        /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
@@ -153,6 +151,7 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
        .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = nexcoder_map_io,
+       .init_machine   = nexcoder_init,
        .init_irq       = s3c24xx_init_irq,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index 2ed8e51..324f5a2 100644 (file)
@@ -251,13 +251,6 @@ static struct clk *osiris_clocks[] = {
        &s3c24xx_uclk,
 };
 
-static struct s3c24xx_board osiris_board __initdata = {
-       .devices       = osiris_devices,
-       .devices_count = ARRAY_SIZE(osiris_devices),
-       .clocks        = osiris_clocks,
-       .clocks_count  = ARRAY_SIZE(osiris_clocks),
-};
-
 static void __init osiris_map_io(void)
 {
        unsigned long flags;
@@ -275,12 +268,13 @@ static void __init osiris_map_io(void)
 
        s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
+       s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks));
+
        s3c_device_nand.dev.platform_data = &osiris_nand_info;
 
        s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
-       s3c24xx_set_board(&osiris_board);
 
        /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
 
@@ -292,12 +286,18 @@ static void __init osiris_map_io(void)
        s3c2410_gpio_setpin(S3C2410_GPA0, 1);
 }
 
+static void __init osiris_init(void)
+{
+       platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
+};
+
 MACHINE_START(OSIRIS, "Simtec-OSIRIS")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
        .phys_io        = S3C2410_PA_UART,
        .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = osiris_map_io,
+       .init_machine   = osiris_init,
        .init_irq       = s3c24xx_init_irq,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index ae1d0a8..c3cc4bf 100644 (file)
@@ -202,11 +202,6 @@ static struct platform_device *rx3715_devices[] __initdata = {
        &s3c_device_nand,
 };
 
-static struct s3c24xx_board rx3715_board __initdata = {
-       .devices       = rx3715_devices,
-       .devices_count = ARRAY_SIZE(rx3715_devices)
-};
-
 static void __init rx3715_map_io(void)
 {
        s3c_device_nand.dev.platform_data = &rx3715_nand_info;
@@ -214,7 +209,6 @@ static void __init rx3715_map_io(void)
        s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
        s3c24xx_init_clocks(16934000);
        s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
-       s3c24xx_set_board(&rx3715_board);
 }
 
 static void __init rx3715_init_irq(void)
@@ -230,9 +224,9 @@ static void __init rx3715_init_machine(void)
        s3c2410_pm_init();
 
        s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
+       platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
 }
 
-
 MACHINE_START(RX3715, "IPAQ-RX3715")
        /* Maintainer: Ben Dooks <ben@fluff.org> */
        .phys_io        = S3C2410_PA_UART,
index c17eb5b..e167254 100644 (file)
@@ -174,23 +174,18 @@ static struct platform_device *smdk2440_devices[] __initdata = {
        &s3c_device_iis,
 };
 
-static struct s3c24xx_board smdk2440_board __initdata = {
-       .devices       = smdk2440_devices,
-       .devices_count = ARRAY_SIZE(smdk2440_devices)
-};
-
 static void __init smdk2440_map_io(void)
 {
        s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
        s3c24xx_init_clocks(16934400);
        s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
-       s3c24xx_set_board(&smdk2440_board);
 }
 
 static void __init smdk2440_machine_init(void)
 {
        s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
 
+       platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
        smdk_machine_init();
 }
 
index 7565735..6cd4818 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
index e82aaff..b71ee53 100644 (file)
@@ -106,21 +106,16 @@ static struct platform_device *smdk2443_devices[] __initdata = {
        &s3c_device_i2c,
 };
 
-static struct s3c24xx_board smdk2443_board __initdata = {
-       .devices       = smdk2443_devices,
-       .devices_count = ARRAY_SIZE(smdk2443_devices)
-};
-
 static void __init smdk2443_map_io(void)
 {
        s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
-       s3c24xx_set_board(&smdk2443_board);
 }
 
 static void __init smdk2443_machine_init(void)
 {
+       platform_add_devices(smdk2443_devices, ARRAY_SIZE(smdk2443_devices));
        smdk_machine_init();
 }
 
index b1e8fd7..fc97fe5 100644 (file)
@@ -9,14 +9,17 @@
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 
 #include <asm/hardware.h>
-#include <asm/semaphore.h>
 
+/*
+ * Very simple clock implementation - we only have one clock to
+ * deal with at the moment, so we only match using the "name".
+ */
 struct clk {
        struct list_head        node;
        unsigned long           rate;
-       struct module           *owner;
        const char              *name;
        unsigned int            enabled;
        void                    (*enable)(void);
@@ -24,21 +27,21 @@ struct clk {
 };
 
 static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_for_each_entry(p, &clocks, node) {
-               if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+               if (strcmp(id, p->name) == 0) {
                        clk = p;
                        break;
                }
        }
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
 
        return clk;
 }
@@ -46,7 +49,6 @@ EXPORT_SYMBOL(clk_get);
 
 void clk_put(struct clk *clk)
 {
-       module_put(clk->owner);
 }
 EXPORT_SYMBOL(clk_put);
 
@@ -109,18 +111,18 @@ static struct clk clk_gpio27 = {
 
 int clk_register(struct clk *clk)
 {
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_add(&clk->node, &clocks);
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
        return 0;
 }
 EXPORT_SYMBOL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_del(&clk->node);
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
 
index 5642aec..edf3347 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
index 075d4d1..d7c038a 100644 (file)
@@ -4,7 +4,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
index 00a6c14..5b0c6af 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/ptrace.h>
 #include <linux/interrupt.h>
 
 #include <asm/irq.h>
index bf71507..1275aa7 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/cnt32_to_63.h>
 #include <asm/system.h>
@@ -828,59 +830,61 @@ void __init versatile_init(void)
 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
 #endif
 
-/*
- * Returns number of ms since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- */
-static unsigned long versatile_gettimeoffset(void)
+static void timer_set_mode(enum clock_event_mode mode,
+                          struct clock_event_device *clk)
 {
-       unsigned long ticks1, ticks2, status;
+       unsigned long ctrl;
 
-       /*
-        * Get the current number of ticks.  Note that there is a race
-        * condition between us reading the timer and checking for
-        * an interrupt.  We get around this by ensuring that the
-        * counter has not reloaded between our two reads.
-        */
-       ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
-       do {
-               ticks1 = ticks2;
-               status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
-               ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
-       } while (ticks2 > ticks1);
+       switch(mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
 
-       /*
-        * Number of ticks since last interrupt.
-        */
-       ticks1 = TIMER_RELOAD - ticks2;
+               ctrl = TIMER_CTRL_PERIODIC;
+               ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /* period set, and timer enabled in 'next_event' hook */
+               ctrl = TIMER_CTRL_ONESHOT;
+               ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       default:
+               ctrl = 0;
+       }
 
-       /*
-        * Interrupt pending?  If so, we've reloaded once already.
-        *
-        * FIXME: Need to check this is effectively timer 0 that expires
-        */
-       if (status & IRQMASK_TIMERINT0_1)
-               ticks1 += TIMER_RELOAD;
+       writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
+}
 
-       /*
-        * Convert the ticks to usecs
-        */
-       return TICKS2USECS(ticks1);
+static int timer_set_next_event(unsigned long evt,
+                               struct clock_event_device *unused)
+{
+       unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
+
+       writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
+       writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
+
+       return 0;
 }
 
+static struct clock_event_device timer0_clockevent =    {
+       .name           = "timer0",
+       .shift          = 32,
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = timer_set_mode,
+       .set_next_event = timer_set_next_event,
+};
+
 /*
  * IRQ handler for the timer
  */
 static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
 {
-       write_seqlock(&xtime_lock);
+       struct clock_event_device *evt = &timer0_clockevent;
 
-       // ...clear the interrupt
        writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
 
-       timer_tick();
-
-       write_sequnlock(&xtime_lock);
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
@@ -891,6 +895,36 @@ static struct irqaction versatile_timer_irq = {
        .handler        = versatile_timer_interrupt,
 };
 
+static cycle_t versatile_get_cycles(void)
+{
+       return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
+}
+
+static struct clocksource clocksource_versatile = {
+       .name           = "timer3",
+       .rating         = 200,
+       .read           = versatile_get_cycles,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 20,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init versatile_clocksource_init(void)
+{
+       /* setup timer3 as free-running clocksource */
+       writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+       writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
+       writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
+       writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
+              TIMER3_VA_BASE + TIMER_CTRL);
+
+       clocksource_versatile.mult =
+               clocksource_khz2mult(1000, clocksource_versatile.shift);
+       clocksource_register(&clocksource_versatile);
+
+       return 0;
+}
+
 /*
  * Set up timer interrupt, and return the current time in seconds.
  */
@@ -918,18 +952,25 @@ static void __init versatile_timer_init(void)
        writel(0, TIMER2_VA_BASE + TIMER_CTRL);
        writel(0, TIMER3_VA_BASE + TIMER_CTRL);
 
-       writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
-       writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
-       writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
-              TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
-
        /* 
         * Make irqs happen for the system timer
         */
        setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
+
+       versatile_clocksource_init();
+
+       timer0_clockevent.mult =
+               div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
+       timer0_clockevent.max_delta_ns =
+               clockevent_delta2ns(0xffffffff, &timer0_clockevent);
+       timer0_clockevent.min_delta_ns =
+               clockevent_delta2ns(0xf, &timer0_clockevent);
+
+       timer0_clockevent.cpumask = cpumask_of_cpu(0);
+       clockevents_register_device(&timer0_clockevent);
 }
 
 struct sys_timer versatile_timer = {
        .init           = versatile_timer_init,
-       .offset         = versatile_gettimeoffset,
 };
+
index 5cd0b5d..ba58223 100644 (file)
@@ -16,7 +16,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
index aa109f0..19ca333 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/ptrace.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 
index 9fd6d2e..5d9ce7d 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/ptrace.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 
@@ -438,7 +437,7 @@ hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *)
 /*
  * Dispatch a data abort to the relevant handler.
  */
-asmlinkage void
+asmlinkage void __exception
 do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
        const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6);
@@ -457,7 +456,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        notify_die("", regs, &info, fsr, 0);
 }
 
-asmlinkage void
+asmlinkage void __exception
 do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
 {
        do_translation_fault(addr, 0, regs);
index 7760193..c0ad7c0 100644 (file)
@@ -9,7 +9,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/ptrace.h>
 #include <linux/swap.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
index 0ac615c..d6167ad 100644 (file)
@@ -32,6 +32,9 @@
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
 
+#include <asm/mach/map.h>
+#include "mm.h"
+
 /*
  * Used by ioremap() and iounmap() code to mark (super)section-mapped
  * I/O regions in vm_struct->flags field.
@@ -39,8 +42,9 @@
 #define VM_ARM_SECTION_MAPPING 0x80000000
 
 static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end,
-                         unsigned long phys_addr, pgprot_t prot)
+                         unsigned long phys_addr, const struct mem_type *type)
 {
+       pgprot_t prot = __pgprot(type->prot_pte);
        pte_t *pte;
 
        pte = pte_alloc_kernel(pmd, addr);
@@ -51,7 +55,8 @@ static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end,
                if (!pte_none(*pte))
                        goto bad;
 
-               set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot), 0);
+               set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot),
+                           type->prot_pte_ext);
                phys_addr += PAGE_SIZE;
        } while (pte++, addr += PAGE_SIZE, addr != end);
        return 0;
@@ -63,7 +68,7 @@ static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end,
 
 static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr,
                                 unsigned long end, unsigned long phys_addr,
-                                pgprot_t prot)
+                                const struct mem_type *type)
 {
        unsigned long next;
        pmd_t *pmd;
@@ -75,7 +80,7 @@ static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr,
 
        do {
                next = pmd_addr_end(addr, end);
-               ret = remap_area_pte(pmd, addr, next, phys_addr, prot);
+               ret = remap_area_pte(pmd, addr, next, phys_addr, type);
                if (ret)
                        return ret;
                phys_addr += next - addr;
@@ -84,13 +89,11 @@ static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr,
 }
 
 static int remap_area_pages(unsigned long start, unsigned long pfn,
-                           unsigned long size, unsigned long flags)
+                           size_t size, const struct mem_type *type)
 {
        unsigned long addr = start;
        unsigned long next, end = start + size;
        unsigned long phys_addr = __pfn_to_phys(pfn);
-       pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
-                                L_PTE_DIRTY | L_PTE_WRITE | flags);
        pgd_t *pgd;
        int err = 0;
 
@@ -98,7 +101,7 @@ static int remap_area_pages(unsigned long start, unsigned long pfn,
        pgd = pgd_offset_k(addr);
        do {
                next = pgd_addr_end(addr, end);
-               err = remap_area_pmd(pgd, addr, next, phys_addr, prot);
+               err = remap_area_pmd(pgd, addr, next, phys_addr, type);
                if (err)
                        break;
                phys_addr += next - addr;
@@ -178,9 +181,9 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
 
 static int
 remap_area_sections(unsigned long virt, unsigned long pfn,
-                   unsigned long size, unsigned long flags)
+                   size_t size, const struct mem_type *type)
 {
-       unsigned long prot, addr = virt, end = virt + size;
+       unsigned long addr = virt, end = virt + size;
        pgd_t *pgd;
 
        /*
@@ -189,23 +192,13 @@ remap_area_sections(unsigned long virt, unsigned long pfn,
         */
        unmap_area_sections(virt, size);
 
-       prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO) |
-              (flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE));
-
-       /*
-        * ARMv6 and above need XN set to prevent speculative prefetches
-        * hitting IO.
-        */
-       if (cpu_architecture() >= CPU_ARCH_ARMv6)
-               prot |= PMD_SECT_XN;
-
        pgd = pgd_offset_k(addr);
        do {
                pmd_t *pmd = pmd_offset(pgd, addr);
 
-               pmd[0] = __pmd(__pfn_to_phys(pfn) | prot);
+               pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect);
                pfn += SZ_1M >> PAGE_SHIFT;
-               pmd[1] = __pmd(__pfn_to_phys(pfn) | prot);
+               pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect);
                pfn += SZ_1M >> PAGE_SHIFT;
                flush_pmd_entry(pmd);
 
@@ -218,9 +211,9 @@ remap_area_sections(unsigned long virt, unsigned long pfn,
 
 static int
 remap_area_supersections(unsigned long virt, unsigned long pfn,
-                        unsigned long size, unsigned long flags)
+                        size_t size, const struct mem_type *type)
 {
-       unsigned long prot, addr = virt, end = virt + size;
+       unsigned long addr = virt, end = virt + size;
        pgd_t *pgd;
 
        /*
@@ -229,22 +222,12 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
         */
        unmap_area_sections(virt, size);
 
-       prot = PMD_TYPE_SECT | PMD_SECT_SUPER | PMD_SECT_AP_WRITE |
-                       PMD_DOMAIN(DOMAIN_IO) |
-                       (flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE));
-
-       /*
-        * ARMv6 and above need XN set to prevent speculative prefetches
-        * hitting IO.
-        */
-       if (cpu_architecture() >= CPU_ARCH_ARMv6)
-               prot |= PMD_SECT_XN;
-
        pgd = pgd_offset_k(virt);
        do {
                unsigned long super_pmd_val, i;
 
-               super_pmd_val = __pfn_to_phys(pfn) | prot;
+               super_pmd_val = __pfn_to_phys(pfn) | type->prot_sect |
+                               PMD_SECT_SUPER;
                super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20;
 
                for (i = 0; i < 8; i++) {
@@ -279,9 +262,10 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
  * mapping.  See include/asm-arm/proc-armv/pgtable.h for more information.
  */
 void __iomem *
-__ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
-             unsigned long flags)
+__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
+                 unsigned int mtype)
 {
+       const struct mem_type *type;
        int err;
        unsigned long addr;
        struct vm_struct * area;
@@ -292,6 +276,10 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
        if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
                return NULL;
 
+       type = get_mem_type(mtype);
+       if (!type)
+               return NULL;
+
        size = PAGE_ALIGN(size);
 
        area = get_vm_area(size, VM_IOREMAP);
@@ -302,16 +290,16 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
 #ifndef CONFIG_SMP
        if (DOMAIN_IO == 0 &&
            (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
-              cpu_is_xsc3()) &&
+              cpu_is_xsc3()) && pfn >= 0x100000 &&
               !((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) {
                area->flags |= VM_ARM_SECTION_MAPPING;
-               err = remap_area_supersections(addr, pfn, size, flags);
+               err = remap_area_supersections(addr, pfn, size, type);
        } else if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
                area->flags |= VM_ARM_SECTION_MAPPING;
-               err = remap_area_sections(addr, pfn, size, flags);
+               err = remap_area_sections(addr, pfn, size, type);
        } else
 #endif
-               err = remap_area_pages(addr, pfn, size, flags);
+               err = remap_area_pages(addr, pfn, size, type);
 
        if (err) {
                vunmap((void *)addr);
@@ -321,10 +309,10 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
        flush_cache_vmap(addr, addr + size);
        return (void __iomem *) (offset + addr);
 }
-EXPORT_SYMBOL(__ioremap_pfn);
+EXPORT_SYMBOL(__arm_ioremap_pfn);
 
 void __iomem *
-__ioremap(unsigned long phys_addr, size_t size, unsigned long flags)
+__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
 {
        unsigned long last_addr;
        unsigned long offset = phys_addr & ~PAGE_MASK;
@@ -342,9 +330,9 @@ __ioremap(unsigned long phys_addr, size_t size, unsigned long flags)
         */
        size = PAGE_ALIGN(last_addr + 1) - phys_addr;
 
-       return __ioremap_pfn(pfn, offset, size, flags);
+       return __arm_ioremap_pfn(pfn, offset, size, mtype);
 }
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(__arm_ioremap);
 
 void __iounmap(volatile void __iomem *addr)
 {
index a44e309..7647c59 100644 (file)
@@ -16,6 +16,16 @@ static inline pmd_t *pmd_off_k(unsigned long virt)
        return pmd_off(pgd_offset_k(virt), virt);
 }
 
+struct mem_type {
+       unsigned int prot_pte;
+       unsigned int prot_pte_ext;
+       unsigned int prot_l1;
+       unsigned int prot_sect;
+       unsigned int domain;
+};
+
+const struct mem_type *get_mem_type(unsigned int type);
+
 #endif
 
 struct map_desc;
index 94fd4bf..2ba1530 100644 (file)
@@ -176,28 +176,42 @@ void adjust_cr(unsigned long mask, unsigned long set)
 }
 #endif
 
-struct mem_types {
-       unsigned int    prot_pte;
-       unsigned int    prot_l1;
-       unsigned int    prot_sect;
-       unsigned int    domain;
-};
-
-static struct mem_types mem_types[] __initdata = {
-       [MT_DEVICE] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE,
-               .prot_l1   = PMD_TYPE_TABLE,
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
-                               PMD_SECT_AP_WRITE,
-               .domain    = DOMAIN_IO,
+#define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE
+#define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_XN|PMD_SECT_AP_WRITE
+
+static struct mem_type mem_types[] = {
+       [MT_DEVICE] = {           /* Strongly ordered / ARMv6 shared device */
+               .prot_pte       = PROT_PTE_DEVICE,
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_UNCACHED,
+               .domain         = DOMAIN_IO,
+       },
+       [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */
+               .prot_pte       = PROT_PTE_DEVICE,
+               .prot_pte_ext   = PTE_EXT_TEX(2),
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_TEX(2),
+               .domain         = DOMAIN_IO,
+       },
+       [MT_DEVICE_CACHED] = {    /* ioremap_cached */
+               .prot_pte       = PROT_PTE_DEVICE | L_PTE_CACHEABLE | L_PTE_BUFFERABLE,
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_WB,
+               .domain         = DOMAIN_IO,
+       },      
+       [MT_DEVICE_IXP2000] = {   /* IXP2400 requires XCB=101 for on-chip I/O */
+               .prot_pte       = PROT_PTE_DEVICE,
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_BUFFERABLE |
+                                 PMD_SECT_TEX(1),
+               .domain         = DOMAIN_IO,
        },
        [MT_CACHECLEAN] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4,
+               .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
                .domain    = DOMAIN_KERNEL,
        },
        [MT_MINICLEAN] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE,
+               .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE,
                .domain    = DOMAIN_KERNEL,
        },
        [MT_LOW_VECTORS] = {
@@ -213,30 +227,20 @@ static struct mem_types mem_types[] __initdata = {
                .domain    = DOMAIN_USER,
        },
        [MT_MEMORY] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE,
+               .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
        [MT_ROM] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4,
+               .prot_sect = PMD_TYPE_SECT,
                .domain    = DOMAIN_KERNEL,
        },
-       [MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE,
-               .prot_l1   = PMD_TYPE_TABLE,
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
-                               PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
-                               PMD_SECT_TEX(1),
-               .domain    = DOMAIN_IO,
-       },
-       [MT_NONSHARED_DEVICE] = {
-               .prot_l1   = PMD_TYPE_TABLE,
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_NONSHARED_DEV |
-                               PMD_SECT_AP_WRITE,
-               .domain    = DOMAIN_IO,
-       }
 };
 
+const struct mem_type *get_mem_type(unsigned int type)
+{
+       return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL;
+}
+
 /*
  * Adjust the PMD section entries according to the CPU in use.
  */
@@ -262,20 +266,23 @@ static void __init build_mem_type_table(void)
        }
 
        /*
-        * Xscale must not have PMD bit 4 set for section mappings.
+        * ARMv5 and lower, bit 4 must be set for page tables.
+        * (was: cache "update-able on write" bit on ARM610)
+        * However, Xscale cores require this bit to be cleared.
         */
-       if (cpu_is_xscale())
-               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+       if (cpu_is_xscale()) {
+               for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
                        mem_types[i].prot_sect &= ~PMD_BIT4;
-
-       /*
-        * ARMv5 and lower, excluding Xscale, bit 4 must be set for
-        * page tables.
-        */
-       if (cpu_arch < CPU_ARCH_ARMv6 && !cpu_is_xscale())
-               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+                       mem_types[i].prot_l1 &= ~PMD_BIT4;
+               }
+       } else if (cpu_arch < CPU_ARCH_ARMv6) {
+               for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
                        if (mem_types[i].prot_l1)
                                mem_types[i].prot_l1 |= PMD_BIT4;
+                       if (mem_types[i].prot_sect)
+                               mem_types[i].prot_sect |= PMD_BIT4;
+               }
+       }
 
        cp = &cache_policies[cachepolicy];
        kern_pgprot = user_pgprot = cp->pte;
@@ -295,13 +302,6 @@ static void __init build_mem_type_table(void)
         * ARMv6 and above have extended page tables.
         */
        if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
-               /*
-                * bit 4 becomes XN which we must clear for the
-                * kernel memory mapping.
-                */
-               mem_types[MT_MEMORY].prot_sect &= ~PMD_SECT_XN;
-               mem_types[MT_ROM].prot_sect &= ~PMD_SECT_XN;
-
                /*
                 * Mark cache clean areas and XIP ROM read only
                 * from SVC mode and no access from userspace.
@@ -368,64 +368,126 @@ static void __init build_mem_type_table(void)
        }
        printk("Memory policy: ECC %sabled, Data cache %s\n",
                ecc_mask ? "en" : "dis", cp->policy);
+
+       for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
+               struct mem_type *t = &mem_types[i];
+               if (t->prot_l1)
+                       t->prot_l1 |= PMD_DOMAIN(t->domain);
+               if (t->prot_sect)
+                       t->prot_sect |= PMD_DOMAIN(t->domain);
+       }
 }
 
 #define vectors_base() (vectors_high() ? 0xffff0000 : 0)
 
-/*
- * Create a SECTION PGD between VIRT and PHYS in domain
- * DOMAIN with protection PROT.  This operates on half-
- * pgdir entry increments.
- */
-static inline void
-alloc_init_section(unsigned long virt, unsigned long phys, int prot)
+static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
+                                 unsigned long end, unsigned long pfn,
+                                 const struct mem_type *type)
 {
-       pmd_t *pmdp = pmd_off_k(virt);
+       pte_t *pte;
 
-       if (virt & (1 << 20))
-               pmdp++;
+       if (pmd_none(*pmd)) {
+               pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t));
+               __pmd_populate(pmd, __pa(pte) | type->prot_l1);
+       }
 
-       *pmdp = __pmd(phys | prot);
-       flush_pmd_entry(pmdp);
+       pte = pte_offset_kernel(pmd, addr);
+       do {
+               set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)),
+                           type->prot_pte_ext);
+               pfn++;
+       } while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-/*
- * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
- */
-static inline void
-alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
+static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
+                                     unsigned long end, unsigned long phys,
+                                     const struct mem_type *type)
 {
-       int i;
+       pmd_t *pmd = pmd_offset(pgd, addr);
+
+       /*
+        * Try a section mapping - end, addr and phys must all be aligned
+        * to a section boundary.  Note that PMDs refer to the individual
+        * L1 entries, whereas PGDs refer to a group of L1 entries making
+        * up one logical pointer to an L2 table.
+        */
+       if (((addr | end | phys) & ~SECTION_MASK) == 0) {
+               pmd_t *p = pmd;
+
+               if (addr & SECTION_SIZE)
+                       pmd++;
 
-       for (i = 0; i < 16; i += 1) {
-               alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
+               do {
+                       *pmd = __pmd(phys | type->prot_sect);
+                       phys += SECTION_SIZE;
+               } while (pmd++, addr += SECTION_SIZE, addr != end);
 
-               virt += (PGDIR_SIZE / 2);
+               flush_pmd_entry(p);
+       } else {
+               /*
+                * No need to loop; pte's aren't interested in the
+                * individual L1 entries.
+                */
+               alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
        }
 }
 
-/*
- * Add a PAGE mapping between VIRT and PHYS in domain
- * DOMAIN with protection PROT.  Note that due to the
- * way we map the PTEs, we must allocate two PTE_SIZE'd
- * blocks - one for the Linux pte table, and one for
- * the hardware pte table.
- */
-static inline void
-alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
+static void __init create_36bit_mapping(struct map_desc *md,
+                                       const struct mem_type *type)
 {
-       pmd_t *pmdp = pmd_off_k(virt);
-       pte_t *ptep;
+       unsigned long phys, addr, length, end;
+       pgd_t *pgd;
+
+       addr = md->virtual;
+       phys = (unsigned long)__pfn_to_phys(md->pfn);
+       length = PAGE_ALIGN(md->length);
+
+       if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
+               printk(KERN_ERR "MM: CPU does not support supersection "
+                      "mapping for 0x%08llx at 0x%08lx\n",
+                      __pfn_to_phys((u64)md->pfn), addr);
+               return;
+       }
 
-       if (pmd_none(*pmdp)) {
-               ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
-                                              sizeof(pte_t));
+       /* N.B. ARMv6 supersections are only defined to work with domain 0.
+        *      Since domain assignments can in fact be arbitrary, the
+        *      'domain == 0' check below is required to insure that ARMv6
+        *      supersections are only allocated for domain 0 regardless
+        *      of the actual domain assignments in use.
+        */
+       if (type->domain) {
+               printk(KERN_ERR "MM: invalid domain in supersection "
+                      "mapping for 0x%08llx at 0x%08lx\n",
+                      __pfn_to_phys((u64)md->pfn), addr);
+               return;
+       }
 
-               __pmd_populate(pmdp, __pa(ptep) | prot_l1);
+       if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) {
+               printk(KERN_ERR "MM: cannot create mapping for "
+                      "0x%08llx at 0x%08lx invalid alignment\n",
+                      __pfn_to_phys((u64)md->pfn), addr);
+               return;
        }
-       ptep = pte_offset_kernel(pmdp, virt);
 
-       set_pte_ext(ptep, pfn_pte(phys >> PAGE_SHIFT, prot), 0);
+       /*
+        * Shift bits [35:32] of address into bits [23:20] of PMD
+        * (See ARMv6 spec).
+        */
+       phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
+
+       pgd = pgd_offset_k(addr);
+       end = addr + length;
+       do {
+               pmd_t *pmd = pmd_offset(pgd, addr);
+               int i;
+
+               for (i = 0; i < 16; i++)
+                       *pmd++ = __pmd(phys | type->prot_sect | PMD_SECT_SUPER);
+
+               addr += SUPERSECTION_SIZE;
+               phys += SUPERSECTION_SIZE;
+               pgd += SUPERSECTION_SIZE >> PGDIR_SHIFT;
+       } while (addr != end);
 }
 
 /*
@@ -437,10 +499,9 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
  */
 void __init create_mapping(struct map_desc *md)
 {
-       unsigned long virt, length;
-       int prot_sect, prot_l1, domain;
-       pgprot_t prot_pte;
-       unsigned long off = (u32)__pfn_to_phys(md->pfn);
+       unsigned long phys, addr, length, end;
+       const struct mem_type *type;
+       pgd_t *pgd;
 
        if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
                printk(KERN_WARNING "BUG: not creating mapping for "
@@ -456,105 +517,37 @@ void __init create_mapping(struct map_desc *md)
                       __pfn_to_phys((u64)md->pfn), md->virtual);
        }
 
-       domain    = mem_types[md->type].domain;
-       prot_pte  = __pgprot(mem_types[md->type].prot_pte);
-       prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
-       prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
+       type = &mem_types[md->type];
 
        /*
         * Catch 36-bit addresses
         */
-       if(md->pfn >= 0x100000) {
-               if(domain) {
-                       printk(KERN_ERR "MM: invalid domain in supersection "
-                               "mapping for 0x%08llx at 0x%08lx\n",
-                               __pfn_to_phys((u64)md->pfn), md->virtual);
-                       return;
-               }
-               if((md->virtual | md->length | __pfn_to_phys(md->pfn))
-                       & ~SUPERSECTION_MASK) {
-                       printk(KERN_ERR "MM: cannot create mapping for "
-                               "0x%08llx at 0x%08lx invalid alignment\n",
-                               __pfn_to_phys((u64)md->pfn), md->virtual);
-                       return;
-               }
-
-               /*
-                * Shift bits [35:32] of address into bits [23:20] of PMD
-                * (See ARMv6 spec).
-                */
-               off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
+       if (md->pfn >= 0x100000) {
+               create_36bit_mapping(md, type);
+               return;
        }
 
-       virt   = md->virtual;
-       off   -= virt;
-       length = md->length;
+       addr = md->virtual;
+       phys = (unsigned long)__pfn_to_phys(md->pfn);
+       length = PAGE_ALIGN(md->length);
 
-       if (mem_types[md->type].prot_l1 == 0 &&
-           (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
+       if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
                printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
                       "be mapped using pages, ignoring.\n",
-                      __pfn_to_phys(md->pfn), md->virtual);
+                      __pfn_to_phys(md->pfn), addr);
                return;
        }
 
-       while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
-               alloc_init_page(virt, virt + off, prot_l1, prot_pte);
+       pgd = pgd_offset_k(addr);
+       end = addr + length;
+       do {
+               unsigned long next = pgd_addr_end(addr, end);
 
-               virt   += PAGE_SIZE;
-               length -= PAGE_SIZE;
-       }
-
-       /* N.B. ARMv6 supersections are only defined to work with domain 0.
-        *      Since domain assignments can in fact be arbitrary, the
-        *      'domain == 0' check below is required to insure that ARMv6
-        *      supersections are only allocated for domain 0 regardless
-        *      of the actual domain assignments in use.
-        */
-       if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
-               && domain == 0) {
-               /*
-                * Align to supersection boundary if !high pages.
-                * High pages have already been checked for proper
-                * alignment above and they will fail the SUPSERSECTION_MASK
-                * check because of the way the address is encoded into
-                * offset.
-                */
-               if (md->pfn <= 0x100000) {
-                       while ((virt & ~SUPERSECTION_MASK ||
-                               (virt + off) & ~SUPERSECTION_MASK) &&
-                               length >= (PGDIR_SIZE / 2)) {
-                               alloc_init_section(virt, virt + off, prot_sect);
-
-                               virt   += (PGDIR_SIZE / 2);
-                               length -= (PGDIR_SIZE / 2);
-                       }
-               }
+               alloc_init_section(pgd, addr, next, phys, type);
 
-               while (length >= SUPERSECTION_SIZE) {
-                       alloc_init_supersection(virt, virt + off, prot_sect);
-
-                       virt   += SUPERSECTION_SIZE;
-                       length -= SUPERSECTION_SIZE;
-               }
-       }
-
-       /*
-        * A section mapping covers half a "pgdir" entry.
-        */
-       while (length >= (PGDIR_SIZE / 2)) {
-               alloc_init_section(virt, virt + off, prot_sect);
-
-               virt   += (PGDIR_SIZE / 2);
-               length -= (PGDIR_SIZE / 2);
-       }
-
-       while (length >= PAGE_SIZE) {
-               alloc_init_page(virt, virt + off, prot_l1, prot_pte);
-
-               virt   += PAGE_SIZE;
-               length -= PAGE_SIZE;
-       }
+               phys += next - addr;
+               addr = next;
+       } while (pgd++, addr != end);
 }
 
 /*
index 05818fc..8cd3a60 100644 (file)
@@ -62,21 +62,21 @@ void flush_dcache_page(struct page *page)
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
-void __iomem *__ioremap_pfn(unsigned long pfn, unsigned long offset,
-                           size_t size, unsigned long flags)
+void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset,
+                               size_t size, unsigned int mtype)
 {
        if (pfn >= (0x100000000ULL >> PAGE_SHIFT))
                return NULL;
        return (void __iomem *) (offset + (pfn << PAGE_SHIFT));
 }
-EXPORT_SYMBOL(__ioremap_pfn);
+EXPORT_SYMBOL(__arm_ioremap_pfn);
 
-void __iomem *__ioremap(unsigned long phys_addr, size_t size,
-                       unsigned long flags)
+void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
+                           unsigned int mtype)
 {
        return (void __iomem *)phys_addr;
 }
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(__arm_ioremap);
 
 void __iounmap(volatile void __iomem *addr)
 {
index d29fe92..c156dda 100644 (file)
@@ -584,6 +584,11 @@ cpu_ixp42x_name:
        .asciz  "XScale-IXP42x Family"
        .size   cpu_ixp42x_name, . - cpu_ixp42x_name
 
+       .type   cpu_ixp43x_name, #object
+cpu_ixp43x_name:
+       .asciz  "XScale-IXP43x Family"
+       .size   cpu_ixp43x_name, . - cpu_ixp43x_name
+
        .type   cpu_ixp46x_name, #object
 cpu_ixp46x_name:
        .asciz  "XScale-IXP46x Family"
@@ -843,6 +848,29 @@ __ixp42x_proc_info:
        .long   xscale_cache_fns
        .size   __ixp42x_proc_info, . - __ixp42x_proc_info                
 
+       .type   __ixp43x_proc_info, #object
+__ixp43x_proc_info:
+       .long   0x69054040
+       .long   0xfffffff0
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_BUFFERABLE | \
+               PMD_SECT_CACHEABLE | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       b       __xscale_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+       .long   cpu_ixp43x_name
+       .long   xscale_processor_functions
+       .long   v4wbi_tlb_fns
+       .long   xscale_mc_user_fns
+       .long   xscale_cache_fns
+       .size   __ixp43x_proc_info, . - __ixp43x_proc_info
+
        .type   __ixp46x_proc_info, #object
 __ixp46x_proc_info:
        .long   0x69054200
index 7c22c12..f5ebf30 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
+#include "../kernel/stacktrace.h"
+
+static int report_trace(struct stackframe *frame, void *d)
+{
+       unsigned int *depth = d;
+
+       if (*depth) {
+               oprofile_add_trace(frame->lr);
+               (*depth)--;
+       }
+
+       return *depth == 0;
+}
 
 /*
  * The registers we're interested in are at the end of the variable
@@ -32,21 +45,6 @@ struct frame_tail {
        unsigned long lr;
 } __attribute__((packed));
 
-
-#ifdef CONFIG_FRAME_POINTER
-static struct frame_tail* kernel_backtrace(struct frame_tail *tail)
-{
-       oprofile_add_trace(tail->lr);
-
-       /* frame pointers should strictly progress back up the stack
-        * (towards higher addresses) */
-       if (tail >= tail->fp)
-               return NULL;
-
-       return tail->fp-1;
-}
-#endif
-
 static struct frame_tail* user_backtrace(struct frame_tail *tail)
 {
        struct frame_tail buftail[2];
@@ -67,47 +65,14 @@ static struct frame_tail* user_backtrace(struct frame_tail *tail)
        return buftail[0].fp-1;
 }
 
-/*
- * |             | /\ Higher addresses
- * |             |
- * --------------- stack base (address of current_thread_info)
- * | thread info |
- * .             .
- * |    stack    |
- * --------------- saved regs->ARM_fp value if valid (frame_tail address)
- * .             .
- * --------------- struct pt_regs stored on stack (struct pt_regs *)
- * |             |
- * .             .
- * |             |
- * --------------- %esp
- * |             |
- * |             | \/ Lower addresses
- *
- * Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
- */
-static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
-{
-       unsigned long tailaddr = (unsigned long)tail;
-       unsigned long stack = (unsigned long)regs;
-       unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
-
-       return (tailaddr > stack) && (tailaddr < stack_base);
-}
-
 void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
-       struct frame_tail *tail;
-
-       tail = ((struct frame_tail *) regs->ARM_fp) - 1;
+       struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1;
 
        if (!user_mode(regs)) {
-
-#ifdef CONFIG_FRAME_POINTER
-               while (depth-- && tail && valid_kernel_stack(tail, regs)) {
-                       tail = kernel_backtrace(tail);
-               }
-#endif
+               unsigned long base = ((unsigned long)regs) & ~(THREAD_SIZE - 1);
+               walk_stackframe(regs->ARM_fp, base, base + THREAD_SIZE,
+                               report_trace, &depth);
                return;
        }
 
index f7eccec..498675d 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/io.h>
 
 void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,
-       unsigned long flags)
+       unsigned int mtype)
 {
        void __iomem * retval;
 
@@ -34,7 +34,7 @@ void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,
                retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);
                break;
        default:
-               retval = __ioremap(cookie, size, flags);
+               retval = __arm_ioremap(cookie, size, mtype);
        }
 
        return retval;
index b5f6ec3..e2744b7 100644 (file)
@@ -55,7 +55,7 @@ static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where)
  * This routine checks the status of the last configuration cycle.  If an error
  * was detected it returns a 1, else it returns a 0.  The errors being checked
  * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
+ * errors occur during a config cycle where there is no device, like during
  * the discovery stage.
  */
 static int iop3xx_pci_status(void)
@@ -223,8 +223,111 @@ struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys)
        return pci_scan_bus(sys->busnr, &iop3xx_ops, sys);
 }
 
+void __init iop3xx_atu_setup(void)
+{
+       /* BAR 0 ( Disabled ) */
+       *IOP3XX_IAUBAR0 = 0x0;
+       *IOP3XX_IABAR0  = 0x0;
+       *IOP3XX_IATVR0  = 0x0;
+       *IOP3XX_IALR0   = 0x0;
+
+       /* BAR 1 ( Disabled ) */
+       *IOP3XX_IAUBAR1 = 0x0;
+       *IOP3XX_IABAR1  = 0x0;
+       *IOP3XX_IALR1   = 0x0;
+
+       /* BAR 2 (1:1 mapping with Physical RAM) */
+       /* Set limit and enable */
+       *IOP3XX_IALR2 = ~((u32)IOP3XX_MAX_RAM_SIZE - 1) & ~0x1;
+       *IOP3XX_IAUBAR2 = 0x0;
+
+       /* Align the inbound bar with the base of memory */
+       *IOP3XX_IABAR2 = PHYS_OFFSET |
+                              PCI_BASE_ADDRESS_MEM_TYPE_64 |
+                              PCI_BASE_ADDRESS_MEM_PREFETCH;
+
+       *IOP3XX_IATVR2 = PHYS_OFFSET;
+
+       /* Outbound window 0 */
+       *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_PA;
+       *IOP3XX_OUMWTVR0 = 0;
+
+       /* Outbound window 1 */
+       *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE;
+       *IOP3XX_OUMWTVR1 = 0;
+
+       /* BAR 3 ( Disabled ) */
+       *IOP3XX_IAUBAR3 = 0x0;
+       *IOP3XX_IABAR3  = 0x0;
+       *IOP3XX_IATVR3  = 0x0;
+       *IOP3XX_IALR3   = 0x0;
+
+       /* Setup the I/O Bar
+        */
+       *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_PA;;
+
+       /* Enable inbound and outbound cycles
+        */
+       *IOP3XX_ATUCMD |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+                              PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+       *IOP3XX_ATUCR |= IOP3XX_ATUCR_OUT_EN;
+}
+
+void __init iop3xx_atu_disable(void)
+{
+       *IOP3XX_ATUCMD = 0;
+       *IOP3XX_ATUCR = 0;
+
+       /* wait for cycles to quiesce */
+       while (*IOP3XX_PCSR & (IOP3XX_PCSR_OUT_Q_BUSY |
+                                    IOP3XX_PCSR_IN_Q_BUSY))
+               cpu_relax();
+
+       /* BAR 0 ( Disabled ) */
+       *IOP3XX_IAUBAR0 = 0x0;
+       *IOP3XX_IABAR0  = 0x0;
+       *IOP3XX_IATVR0  = 0x0;
+       *IOP3XX_IALR0   = 0x0;
+
+       /* BAR 1 ( Disabled ) */
+       *IOP3XX_IAUBAR1 = 0x0;
+       *IOP3XX_IABAR1  = 0x0;
+       *IOP3XX_IALR1   = 0x0;
+
+       /* BAR 2 ( Disabled ) */
+       *IOP3XX_IAUBAR2 = 0x0;
+       *IOP3XX_IABAR2  = 0x0;
+       *IOP3XX_IATVR2  = 0x0;
+       *IOP3XX_IALR2   = 0x0;
+
+       /* BAR 3 ( Disabled ) */
+       *IOP3XX_IAUBAR3 = 0x0;
+       *IOP3XX_IABAR3  = 0x0;
+       *IOP3XX_IATVR3  = 0x0;
+       *IOP3XX_IALR3   = 0x0;
+
+       /* Clear the outbound windows */
+       *IOP3XX_OIOWTVR  = 0;
+
+       /* Outbound window 0 */
+       *IOP3XX_OMWTVR0 = 0;
+       *IOP3XX_OUMWTVR0 = 0;
+
+       /* Outbound window 1 */
+       *IOP3XX_OMWTVR1 = 0;
+       *IOP3XX_OUMWTVR1 = 0;
+}
+
+/* Flag to determine whether the ATU is initialized and the PCI bus scanned */
+int init_atu;
+
 void iop3xx_pci_preinit(void)
 {
+       if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
+               iop3xx_atu_disable();
+               iop3xx_atu_setup();
+       }
+
        DBG("PCI:  Intel 803xx PCI init code.\n");
        DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
        DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
@@ -245,3 +348,38 @@ void iop3xx_pci_preinit(void)
 
        hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
 }
+
+/* allow init_atu to be user overridden */
+static int __init iop3xx_init_atu_setup(char *str)
+{
+       init_atu = IOP3XX_INIT_ATU_DEFAULT;
+       if (str) {
+               while (*str != '\0') {
+                       switch (*str) {
+                       case 'y':
+                       case 'Y':
+                               init_atu = IOP3XX_INIT_ATU_ENABLE;
+                               break;
+                       case 'n':
+                       case 'N':
+                               init_atu = IOP3XX_INIT_ATU_DISABLE;
+                               break;
+                       case ',':
+                       case '=':
+                               break;
+                       default:
+                               printk(KERN_DEBUG "\"%s\" malformed at "
+                                           "character: \'%c\'",
+                                           __FUNCTION__,
+                                           *str);
+                               *(str + 1) = '\0';
+                       }
+                       str++;
+               }
+       }
+
+       return 1;
+}
+
+__setup("iop3xx_init_atu", iop3xx_init_atu_setup);
+
index 16300ad..0cc26da 100644 (file)
@@ -32,22 +32,22 @@ static unsigned long next_jiffy_time;
 
 unsigned long iop_gettimeoffset(void)
 {
-       unsigned long offset, temp1, temp2;
+       unsigned long offset, temp;
 
        /* enable cp6, if necessary, to avoid taking the overhead of an
         * undefined instruction trap
         */
        asm volatile (
        "mrc    p15, 0, %0, c15, c1, 0\n\t"
-       "ands   %1, %0, #(1 << 6)\n\t"
+       "tst    %0, #(1 << 6)\n\t"
        "orreq  %0, %0, #(1 << 6)\n\t"
        "mcreq  p15, 0, %0, c15, c1, 0\n\t"
-#ifdef CONFIG_XSCALE
+#ifdef CONFIG_CPU_XSCALE
        "mrceq  p15, 0, %0, c15, c1, 0\n\t"
        "moveq  %0, %0\n\t"
        "subeq  pc, pc, #4\n\t"
 #endif
-       : "=r"(temp1), "=r"(temp2) : : "cc");
+       : "=r"(temp) : : "cc");
 
        offset = next_jiffy_time - read_tcr1();
 
index f2dc363..9e8d21e 100644 (file)
@@ -11,6 +11,7 @@ choice
 
 config ARCH_OMAP1
        bool "TI OMAP1"
+       select GENERIC_CLOCKEVENTS
 
 config ARCH_OMAP2
        bool "TI OMAP2"
index 57b7b93..fecd3d6 100644 (file)
@@ -156,3 +156,53 @@ static int __init omap_add_serial_console(void)
        return add_preferred_console("ttyS", line, opt);
 }
 console_initcall(omap_add_serial_console);
+
+
+/*
+ * 32KHz clocksource ... always available, on pretty most chips except
+ * OMAP 730 and 1510.  Other timers could be used as clocksources, with
+ * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
+ * but systems won't necessarily want to spend resources that way.
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED         0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED         0x48004010
+#endif
+
+#ifdef TIMER_32K_SYNCHRONIZED
+
+#include <linux/clocksource.h>
+
+static cycle_t omap_32k_read(void)
+{
+       return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static struct clocksource clocksource_32k = {
+       .name           = "32k_counter",
+       .rating         = 250,
+       .read           = omap_32k_read,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 10,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init omap_init_clocksource_32k(void)
+{
+       static char err[] __initdata = KERN_ERR
+                       "%s: can't register clocksource!\n";
+
+       if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+               clocksource_32k.mult = clocksource_hz2mult(32768,
+                                           clocksource_32k.shift);
+
+               if (clocksource_register(&clocksource_32k))
+                       printk(err, clocksource_32k.name);
+       }
+       return 0;
+}
+arch_initcall(omap_init_clocksource_32k);
+
+#endif /* TIMER_32K_SYNCHRONIZED */
index dbc3f44..eeb33fe 100644 (file)
@@ -429,6 +429,10 @@ static inline void omap_init_rng(void) {}
  */
 static int __init omap_init_devices(void)
 {
+/*
+ * Need to enable relevant once for 2430 SDP
+ */
+#ifndef CONFIG_MACH_OMAP_2430SDP
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
@@ -438,7 +442,7 @@ static int __init omap_init_devices(void)
        omap_init_uwire();
        omap_init_wdt();
        omap_init_rng();
-
+#endif
        return 0;
 }
 arch_initcall(omap_init_devices);
index 45f0439..659619f 100644 (file)
@@ -506,6 +506,8 @@ int omap_dm_timer_init(void)
                BUG_ON(dm_source_clocks[i] == NULL);
        }
 #endif
+       if (cpu_is_omap243x())
+               dm_timers[0].phys_base = 0x49018000;
 
        for (i = 0; i < dm_timer_count; i++) {
 #ifdef CONFIG_ARCH_OMAP2
index b8c01de..9dc6d36 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 /*
  * omap24xx specific GPIO registers
  */
-#define OMAP24XX_GPIO1_BASE            (void __iomem *)0x48018000
-#define OMAP24XX_GPIO2_BASE            (void __iomem *)0x4801a000
-#define OMAP24XX_GPIO3_BASE            (void __iomem *)0x4801c000
-#define OMAP24XX_GPIO4_BASE            (void __iomem *)0x4801e000
+#define OMAP242X_GPIO1_BASE            (void __iomem *)0x48018000
+#define OMAP242X_GPIO2_BASE            (void __iomem *)0x4801a000
+#define OMAP242X_GPIO3_BASE            (void __iomem *)0x4801c000
+#define OMAP242X_GPIO4_BASE            (void __iomem *)0x4801e000
+
+#define OMAP243X_GPIO1_BASE            (void __iomem *)0x4900C000
+#define OMAP243X_GPIO2_BASE            (void __iomem *)0x4900E000
+#define OMAP243X_GPIO3_BASE            (void __iomem *)0x49010000
+#define OMAP243X_GPIO4_BASE            (void __iomem *)0x49012000
+#define OMAP243X_GPIO5_BASE            (void __iomem *)0x480B6000
+
 #define OMAP24XX_GPIO_REVISION         0x0000
 #define OMAP24XX_GPIO_SYSCONFIG                0x0010
 #define OMAP24XX_GPIO_SYSSTATUS                0x0014
@@ -118,8 +124,18 @@ struct gpio_bank {
        u16 virtual_irq_start;
        int method;
        u32 reserved_map;
+#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
        u32 suspend_wakeup;
        u32 saved_wakeup;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       u32 non_wakeup_gpios;
+       u32 enabled_non_wakeup_gpios;
+
+       u32 saved_datain;
+       u32 saved_fallingdetect;
+       u32 saved_risingdetect;
+#endif
        spinlock_t lock;
 };
 
@@ -159,12 +175,22 @@ static struct gpio_bank gpio_bank_730[7] = {
 #endif
 
 #ifdef CONFIG_ARCH_OMAP24XX
-static struct gpio_bank gpio_bank_24xx[4] = {
-       { OMAP24XX_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,       METHOD_GPIO_24XX },
-       { OMAP24XX_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,  METHOD_GPIO_24XX },
-       { OMAP24XX_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,  METHOD_GPIO_24XX },
-       { OMAP24XX_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,  METHOD_GPIO_24XX },
+
+static struct gpio_bank gpio_bank_242x[4] = {
+       { OMAP242X_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,       METHOD_GPIO_24XX },
+       { OMAP242X_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,  METHOD_GPIO_24XX },
+       { OMAP242X_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,  METHOD_GPIO_24XX },
+       { OMAP242X_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,  METHOD_GPIO_24XX },
+};
+
+static struct gpio_bank gpio_bank_243x[5] = {
+       { OMAP243X_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,       METHOD_GPIO_24XX },
+       { OMAP243X_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,  METHOD_GPIO_24XX },
+       { OMAP243X_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,  METHOD_GPIO_24XX },
+       { OMAP243X_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,  METHOD_GPIO_24XX },
+       { OMAP243X_GPIO5_BASE, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_24XX },
 };
+
 #endif
 
 static struct gpio_bank *gpio_bank;
@@ -258,21 +284,34 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
        u32 l;
 
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_IO_CNTL;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_DIR_CONTROL;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                reg += OMAP1610_GPIO_DIRECTION;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_DIR_CONTROL;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
                reg += OMAP24XX_GPIO_OE;
                break;
+#endif
+       default:
+               WARN_ON(1);
+               return;
        }
        l = __raw_readl(reg);
        if (is_input)
@@ -300,6 +339,7 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
        u32 l = 0;
 
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_OUTPUT;
                l = __raw_readl(reg);
@@ -308,6 +348,8 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
                else
                        l &= ~(1 << gpio);
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_DATA_OUTPUT;
                l = __raw_readl(reg);
@@ -316,6 +358,8 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
                else
                        l &= ~(1 << gpio);
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                if (enable)
                        reg += OMAP1610_GPIO_SET_DATAOUT;
@@ -323,6 +367,8 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
                        reg += OMAP1610_GPIO_CLEAR_DATAOUT;
                l = 1 << gpio;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_DATA_OUTPUT;
                l = __raw_readl(reg);
@@ -331,6 +377,8 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
                else
                        l &= ~(1 << gpio);
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
                if (enable)
                        reg += OMAP24XX_GPIO_SETDATAOUT;
@@ -338,8 +386,9 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
                        reg += OMAP24XX_GPIO_CLEARDATAOUT;
                l = 1 << gpio;
                break;
+#endif
        default:
-               BUG();
+               WARN_ON(1);
                return;
        }
        __raw_writel(l, reg);
@@ -363,28 +412,37 @@ int omap_get_gpio_datain(int gpio)
        void __iomem *reg;
 
        if (check_gpio(gpio) < 0)
-               return -1;
+               return -EINVAL;
        bank = get_gpio_bank(gpio);
        reg = bank->base;
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_INPUT_LATCH;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_DATA_INPUT;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                reg += OMAP1610_GPIO_DATAIN;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_DATA_INPUT;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
                reg += OMAP24XX_GPIO_DATAIN;
                break;
+#endif
        default:
-               BUG();
-               return -1;
+               return -EINVAL;
        }
        return (__raw_readl(reg)
                        & (1 << get_gpio_index(gpio))) != 0;
@@ -398,8 +456,10 @@ do {       \
        __raw_writel(l, base + reg); \
 } while(0)
 
-static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger)
+#ifdef CONFIG_ARCH_OMAP24XX
+static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
 {
+       void __iomem *base = bank->base;
        u32 gpio_bit = 1 << gpio;
 
        MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
@@ -410,9 +470,21 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
                trigger & __IRQT_RISEDGE);
        MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
                trigger & __IRQT_FALEDGE);
+       if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
+               if (trigger != 0)
+                       __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA);
+               else
+                       __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA);
+       } else {
+               if (trigger != 0)
+                       bank->enabled_non_wakeup_gpios |= gpio_bit;
+               else
+                       bank->enabled_non_wakeup_gpios &= ~gpio_bit;
+       }
        /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level
         * triggering requested. */
 }
+#endif
 
 static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
 {
@@ -420,6 +492,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        u32 l = 0;
 
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_GPIO_INT_EDGE;
                l = __raw_readl(reg);
@@ -430,6 +503,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
                else
                        goto bad;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
@@ -440,22 +515,28 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
                else
                        goto bad;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                if (gpio & 0x08)
                        reg += OMAP1610_GPIO_EDGE_CTRL2;
                else
                        reg += OMAP1610_GPIO_EDGE_CTRL1;
                gpio &= 0x07;
-               /* We allow only edge triggering, i.e. two lowest bits */
-               if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
-                       BUG();
                l = __raw_readl(reg);
                l &= ~(3 << (gpio << 1));
                if (trigger & __IRQT_RISEDGE)
                        l |= 2 << (gpio << 1);
                if (trigger & __IRQT_FALEDGE)
                        l |= 1 << (gpio << 1);
+               if (trigger)
+                       /* Enable wake-up during idle for dynamic tick */
+                       __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA);
+               else
+                       __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
@@ -466,11 +547,13 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
                else
                        goto bad;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
-               set_24xx_gpio_triggering(reg, gpio, trigger);
+               set_24xx_gpio_triggering(bank, gpio, trigger);
                break;
+#endif
        default:
-               BUG();
                goto bad;
        }
        __raw_writel(l, reg);
@@ -485,7 +568,7 @@ static int gpio_irq_type(unsigned irq, unsigned type)
        unsigned gpio;
        int retval;
 
-       if (irq > IH_MPUIO_BASE)
+       if (!cpu_is_omap24xx() && irq > IH_MPUIO_BASE)
                gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
        else
                gpio = irq - IH_GPIO_BASE;
@@ -493,14 +576,21 @@ static int gpio_irq_type(unsigned irq, unsigned type)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       if (type & IRQT_PROBE)
+       if (type & ~IRQ_TYPE_SENSE_MASK)
                return -EINVAL;
-       if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
+
+       /* OMAP1 allows only only edge triggering */
+       if (!cpu_is_omap24xx()
+                       && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
                return -EINVAL;
 
-       bank = get_gpio_bank(gpio);
+       bank = get_irq_chip_data(irq);
        spin_lock(&bank->lock);
        retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
+       if (retval == 0) {
+               irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+               irq_desc[irq].status |= type;
+       }
        spin_unlock(&bank->lock);
        return retval;
 }
@@ -510,24 +600,34 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
        void __iomem *reg = bank->base;
 
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                /* MPUIO irqstatus is reset by reading the status register,
                 * so do nothing here */
                return;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_STATUS;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                reg += OMAP1610_GPIO_IRQSTATUS1;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_STATUS;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
                reg += OMAP24XX_GPIO_IRQSTATUS1;
                break;
+#endif
        default:
-               BUG();
+               WARN_ON(1);
                return;
        }
        __raw_writel(gpio_mask, reg);
@@ -550,31 +650,41 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
        u32 mask;
 
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_GPIO_MASKIT;
                mask = 0xffff;
                inv = 1;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_MASK;
                mask = 0xffff;
                inv = 1;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                reg += OMAP1610_GPIO_IRQENABLE1;
                mask = 0xffff;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_MASK;
                mask = 0xffffffff;
                inv = 1;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
                reg += OMAP24XX_GPIO_IRQENABLE1;
                mask = 0xffffffff;
                break;
+#endif
        default:
-               BUG();
+               WARN_ON(1);
                return 0;
        }
 
@@ -591,6 +701,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
        u32 l;
 
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_GPIO_MASKIT;
                l = __raw_readl(reg);
@@ -599,6 +710,8 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
                else
                        l |= gpio_mask;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_MASK;
                l = __raw_readl(reg);
@@ -607,6 +720,8 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
                else
                        l |= gpio_mask;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
        case METHOD_GPIO_1610:
                if (enable)
                        reg += OMAP1610_GPIO_SET_IRQENABLE1;
@@ -614,6 +729,8 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
                        reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
                l = gpio_mask;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_MASK;
                l = __raw_readl(reg);
@@ -622,6 +739,8 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
                else
                        l |= gpio_mask;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
                if (enable)
                        reg += OMAP24XX_GPIO_SETIRQENABLE1;
@@ -629,8 +748,9 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
                        reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
                l = gpio_mask;
                break;
+#endif
        default:
-               BUG();
+               WARN_ON(1);
                return;
        }
        __raw_writel(l, reg);
@@ -652,15 +772,39 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
 static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 {
        switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_MPUIO:
        case METHOD_GPIO_1610:
+               spin_lock(&bank->lock);
+               if (enable) {
+                       bank->suspend_wakeup |= (1 << gpio);
+                       enable_irq_wake(bank->irq);
+               } else {
+                       disable_irq_wake(bank->irq);
+                       bank->suspend_wakeup &= ~(1 << gpio);
+               }
+               spin_unlock(&bank->lock);
+               return 0;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
+               if (bank->non_wakeup_gpios & (1 << gpio)) {
+                       printk(KERN_ERR "Unable to modify wakeup on "
+                                       "non-wakeup GPIO%d\n",
+                                       (bank - gpio_bank) * 32 + gpio);
+                       return -EINVAL;
+               }
                spin_lock(&bank->lock);
-               if (enable)
+               if (enable) {
                        bank->suspend_wakeup |= (1 << gpio);
-               else
+                       enable_irq_wake(bank->irq);
+               } else {
+                       disable_irq_wake(bank->irq);
                        bank->suspend_wakeup &= ~(1 << gpio);
+               }
                spin_unlock(&bank->lock);
                return 0;
+#endif
        default:
                printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
                       bank->method);
@@ -685,7 +829,7 @@ static int gpio_wake_enable(unsigned int irq, unsigned int enable)
 
        if (check_gpio(gpio) < 0)
                return -ENODEV;
-       bank = get_gpio_bank(gpio);
+       bank = get_irq_chip_data(irq);
        retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
 
        return retval;
@@ -721,20 +865,6 @@ int omap_request_gpio(int gpio)
                reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
                __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
        }
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       if (bank->method == METHOD_GPIO_1610) {
-               /* Enable wake-up during idle for dynamic tick */
-               void __iomem *reg = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-               __raw_writel(1 << get_gpio_index(gpio), reg);
-       }
-#endif
-#ifdef CONFIG_ARCH_OMAP24XX
-       if (bank->method == METHOD_GPIO_24XX) {
-               /* Enable wake-up during idle for dynamic tick */
-               void __iomem *reg = bank->base + OMAP24XX_GPIO_SETWKUENA;
-               __raw_writel(1 << get_gpio_index(gpio), reg);
-       }
 #endif
        spin_unlock(&bank->lock);
 
@@ -795,8 +925,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        desc->chip->ack(irq);
 
        bank = get_irq_data(irq);
+#ifdef CONFIG_ARCH_OMAP1
        if (bank->method == METHOD_MPUIO)
                isr_reg = bank->base + OMAP_MPUIO_GPIO_INT;
+#endif
 #ifdef CONFIG_ARCH_OMAP15XX
        if (bank->method == METHOD_GPIO_1510)
                isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
@@ -912,7 +1044,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 static void gpio_irq_shutdown(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _reset_gpio(bank, gpio);
 }
@@ -920,7 +1052,7 @@ static void gpio_irq_shutdown(unsigned int irq)
 static void gpio_ack_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _clear_gpio_irqstatus(bank, gpio);
 }
@@ -928,7 +1060,7 @@ static void gpio_ack_irq(unsigned int irq)
 static void gpio_mask_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 0);
 }
@@ -937,11 +1069,27 @@ static void gpio_unmask_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
        unsigned int gpio_idx = get_gpio_index(gpio);
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio_idx, 1);
 }
 
+static struct irq_chip gpio_irq_chip = {
+       .name           = "GPIO",
+       .shutdown       = gpio_irq_shutdown,
+       .ack            = gpio_ack_irq,
+       .mask           = gpio_mask_irq,
+       .unmask         = gpio_unmask_irq,
+       .set_type       = gpio_irq_type,
+       .set_wake       = gpio_wake_enable,
+};
+
+/*---------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP1
+
+/* MPUIO uses the always-on 32k clock */
+
 static void mpuio_ack_irq(unsigned int irq)
 {
        /* The ISR is reset automatically, so do nothing here. */
@@ -950,7 +1098,7 @@ static void mpuio_ack_irq(unsigned int irq)
 static void mpuio_mask_irq(unsigned int irq)
 {
        unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 0);
 }
@@ -958,33 +1106,108 @@ static void mpuio_mask_irq(unsigned int irq)
 static void mpuio_unmask_irq(unsigned int irq)
 {
        unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 1);
 }
 
-static struct irq_chip gpio_irq_chip = {
-       .name           = "GPIO",
-       .shutdown       = gpio_irq_shutdown,
-       .ack            = gpio_ack_irq,
-       .mask           = gpio_mask_irq,
-       .unmask         = gpio_unmask_irq,
+static struct irq_chip mpuio_irq_chip = {
+       .name           = "MPUIO",
+       .ack            = mpuio_ack_irq,
+       .mask           = mpuio_mask_irq,
+       .unmask         = mpuio_unmask_irq,
        .set_type       = gpio_irq_type,
+#ifdef CONFIG_ARCH_OMAP16XX
+       /* REVISIT: assuming only 16xx supports MPUIO wake events */
        .set_wake       = gpio_wake_enable,
+#endif
 };
 
-static struct irq_chip mpuio_irq_chip = {
-       .name     = "MPUIO",
-       .ack      = mpuio_ack_irq,
-       .mask     = mpuio_mask_irq,
-       .unmask   = mpuio_unmask_irq,
-       .set_type = gpio_irq_type,
+
+#define bank_is_mpuio(bank)    ((bank)->method == METHOD_MPUIO)
+
+
+#ifdef CONFIG_ARCH_OMAP16XX
+
+#include <linux/platform_device.h>
+
+static int omap_mpuio_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct gpio_bank        *bank = platform_get_drvdata(pdev);
+       void __iomem            *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
+
+       spin_lock(&bank->lock);
+       bank->saved_wakeup = __raw_readl(mask_reg);
+       __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
+       spin_unlock(&bank->lock);
+
+       return 0;
+}
+
+static int omap_mpuio_resume_early(struct platform_device *pdev)
+{
+       struct gpio_bank        *bank = platform_get_drvdata(pdev);
+       void __iomem            *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
+
+       spin_lock(&bank->lock);
+       __raw_writel(bank->saved_wakeup, mask_reg);
+       spin_unlock(&bank->lock);
+
+       return 0;
+}
+
+/* use platform_driver for this, now that there's no longer any
+ * point to sys_device (other than not disturbing old code).
+ */
+static struct platform_driver omap_mpuio_driver = {
+       .suspend_late   = omap_mpuio_suspend_late,
+       .resume_early   = omap_mpuio_resume_early,
+       .driver         = {
+               .name   = "mpuio",
+       },
+};
+
+static struct platform_device omap_mpuio_device = {
+       .name           = "mpuio",
+       .id             = -1,
+       .dev = {
+               .driver = &omap_mpuio_driver.driver,
+       }
+       /* could list the /proc/iomem resources */
 };
 
+static inline void mpuio_init(void)
+{
+       platform_set_drvdata(&omap_mpuio_device, &gpio_bank_1610[0]);
+
+       if (platform_driver_register(&omap_mpuio_driver) == 0)
+               (void) platform_device_register(&omap_mpuio_device);
+}
+
+#else
+static inline void mpuio_init(void) {}
+#endif /* 16xx */
+
+#else
+
+extern struct irq_chip mpuio_irq_chip;
+
+#define bank_is_mpuio(bank)    0
+static inline void mpuio_init(void) {}
+
+#endif
+
+/*---------------------------------------------------------------------*/
+
 static int initialized;
 static struct clk * gpio_ick;
 static struct clk * gpio_fck;
 
+#ifdef CONFIG_ARCH_OMAP2430
+static struct clk * gpio5_ick;
+static struct clk * gpio5_fck;
+#endif
+
 static int __init _omap_gpio_init(void)
 {
        int i;
@@ -1010,7 +1233,25 @@ static int __init _omap_gpio_init(void)
                        printk("Could not get gpios_fck\n");
                else
                        clk_enable(gpio_fck);
-       }
+
+               /*
+                * On 2430 GPIO 5 uses CORE L4 ICLK
+                */
+#ifdef CONFIG_ARCH_OMAP2430
+               if (cpu_is_omap2430()) {
+                       gpio5_ick = clk_get(NULL, "gpio5_ick");
+                       if (IS_ERR(gpio5_ick))
+                               printk("Could not get gpio5_ick\n");
+                       else
+                               clk_enable(gpio5_ick);
+                       gpio5_fck = clk_get(NULL, "gpio5_fck");
+                       if (IS_ERR(gpio5_fck))
+                               printk("Could not get gpio5_fck\n");
+                       else
+                               clk_enable(gpio5_fck);
+               }
+#endif
+}
 
 #ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap15xx()) {
@@ -1037,14 +1278,24 @@ static int __init _omap_gpio_init(void)
                gpio_bank = gpio_bank_730;
        }
 #endif
+
 #ifdef CONFIG_ARCH_OMAP24XX
-       if (cpu_is_omap24xx()) {
+       if (cpu_is_omap242x()) {
                int rev;
 
                gpio_bank_count = 4;
-               gpio_bank = gpio_bank_24xx;
+               gpio_bank = gpio_bank_242x;
+               rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+               printk(KERN_INFO "OMAP242x GPIO hardware version %d.%d\n",
+                       (rev >> 4) & 0x0f, rev & 0x0f);
+       }
+       if (cpu_is_omap243x()) {
+               int rev;
+
+               gpio_bank_count = 5;
+               gpio_bank = gpio_bank_243x;
                rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
-               printk(KERN_INFO "OMAP24xx GPIO hardware version %d.%d\n",
+               printk(KERN_INFO "OMAP243x GPIO hardware version %d.%d\n",
                        (rev >> 4) & 0x0f, rev & 0x0f);
        }
 #endif
@@ -1055,9 +1306,8 @@ static int __init _omap_gpio_init(void)
                bank->reserved_map = 0;
                bank->base = IO_ADDRESS(bank->base);
                spin_lock_init(&bank->lock);
-               if (bank->method == METHOD_MPUIO) {
+               if (bank_is_mpuio(bank))
                        omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT);
-               }
 #ifdef CONFIG_ARCH_OMAP15XX
                if (bank->method == METHOD_GPIO_1510) {
                        __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK);
@@ -1081,15 +1331,25 @@ static int __init _omap_gpio_init(void)
 #endif
 #ifdef CONFIG_ARCH_OMAP24XX
                if (bank->method == METHOD_GPIO_24XX) {
+                       static const u32 non_wakeup_gpios[] = {
+                               0xe203ffc0, 0x08700040
+                       };
+
                        __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
                        __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
+                       __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG);
 
+                       /* Initialize interface clock ungated, module enabled */
+                       __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
+                       if (i < ARRAY_SIZE(non_wakeup_gpios))
+                               bank->non_wakeup_gpios = non_wakeup_gpios[i];
                        gpio_count = 32;
                }
 #endif
                for (j = bank->virtual_irq_start;
                     j < bank->virtual_irq_start + gpio_count; j++) {
-                       if (bank->method == METHOD_MPUIO)
+                       set_irq_chip_data(j, bank);
+                       if (bank_is_mpuio(bank))
                                set_irq_chip(j, &mpuio_irq_chip);
                        else
                                set_irq_chip(j, &gpio_irq_chip);
@@ -1105,6 +1365,12 @@ static int __init _omap_gpio_init(void)
        if (cpu_is_omap16xx())
                omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
 
+#ifdef CONFIG_ARCH_OMAP24XX
+       /* Enable autoidle for the OCP interface */
+       if (cpu_is_omap24xx())
+               omap_writel(1 << 0, 0x48019010);
+#endif
+
        return 0;
 }
 
@@ -1123,16 +1389,20 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
                void __iomem *wake_set;
 
                switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
                case METHOD_GPIO_1610:
                        wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
                        wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
                        wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
                        break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
                case METHOD_GPIO_24XX:
                        wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
                        wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
                        wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
                        break;
+#endif
                default:
                        continue;
                }
@@ -1160,14 +1430,18 @@ static int omap_gpio_resume(struct sys_device *dev)
                void __iomem *wake_set;
 
                switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
                case METHOD_GPIO_1610:
                        wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
                        wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
                        break;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
                case METHOD_GPIO_24XX:
                        wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
                        wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
                        break;
+#endif
                default:
                        continue;
                }
@@ -1191,6 +1465,80 @@ static struct sys_device omap_gpio_device = {
        .id             = 0,
        .cls            = &omap_gpio_sysclass,
 };
+
+#endif
+
+#ifdef CONFIG_ARCH_OMAP24XX
+
+static int workaround_enabled;
+
+void omap2_gpio_prepare_for_retention(void)
+{
+       int i, c = 0;
+
+       /* Remove triggering for all non-wakeup GPIOs.  Otherwise spurious
+        * IRQs will be generated.  See OMAP2420 Errata item 1.101. */
+       for (i = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               u32 l1, l2;
+
+               if (!(bank->enabled_non_wakeup_gpios))
+                       continue;
+               bank->saved_datain = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
+               l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+               l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
+               bank->saved_fallingdetect = l1;
+               bank->saved_risingdetect = l2;
+               l1 &= ~bank->enabled_non_wakeup_gpios;
+               l2 &= ~bank->enabled_non_wakeup_gpios;
+               __raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+               __raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT);
+               c++;
+       }
+       if (!c) {
+               workaround_enabled = 0;
+               return;
+       }
+       workaround_enabled = 1;
+}
+
+void omap2_gpio_resume_after_retention(void)
+{
+       int i;
+
+       if (!workaround_enabled)
+               return;
+       for (i = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               u32 l;
+
+               if (!(bank->enabled_non_wakeup_gpios))
+                       continue;
+               __raw_writel(bank->saved_fallingdetect,
+                                bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+               __raw_writel(bank->saved_risingdetect,
+                                bank->base + OMAP24XX_GPIO_RISINGDETECT);
+               /* Check if any of the non-wakeup interrupt GPIOs have changed
+                * state.  If so, generate an IRQ by software.  This is
+                * horribly racy, but it's the best we can do to work around
+                * this silicon bug. */
+               l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
+               l ^= bank->saved_datain;
+               l &= bank->non_wakeup_gpios;
+               if (l) {
+                       u32 old0, old1;
+
+                       old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
+                       old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+                       __raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
+                       __raw_writel(old1 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+                       __raw_writel(old0, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
+                       __raw_writel(old1, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+               }
+       }
+
+}
+
 #endif
 
 /*
@@ -1212,6 +1560,8 @@ static int __init omap_gpio_sysinit(void)
        if (!initialized)
                ret = _omap_gpio_init();
 
+       mpuio_init();
+
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
        if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
                if (ret == 0) {
@@ -1232,3 +1582,128 @@ EXPORT_SYMBOL(omap_set_gpio_dataout);
 EXPORT_SYMBOL(omap_get_gpio_datain);
 
 arch_initcall(omap_gpio_sysinit);
+
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static int gpio_is_input(struct gpio_bank *bank, int mask)
+{
+       void __iomem *reg = bank->base;
+
+       switch (bank->method) {
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_IO_CNTL;
+               break;
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DIRECTION;
+               break;
+       case METHOD_GPIO_730:
+               reg += OMAP730_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_OE;
+               break;
+       }
+       return __raw_readl(reg) & mask;
+}
+
+
+static int dbg_gpio_show(struct seq_file *s, void *unused)
+{
+       unsigned        i, j, gpio;
+
+       for (i = 0, gpio = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank        *bank = gpio_bank + i;
+               unsigned                bankwidth = 16;
+               u32                     mask = 1;
+
+               if (bank_is_mpuio(bank))
+                       gpio = OMAP_MPUIO(0);
+               else if (cpu_is_omap24xx() || cpu_is_omap730())
+                       bankwidth = 32;
+
+               for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
+                       unsigned        irq, value, is_in, irqstat;
+
+                       if (!(bank->reserved_map & mask))
+                               continue;
+
+                       irq = bank->virtual_irq_start + j;
+                       value = omap_get_gpio_datain(gpio);
+                       is_in = gpio_is_input(bank, mask);
+
+                       if (bank_is_mpuio(bank))
+                               seq_printf(s, "MPUIO %2d: ", j);
+                       else
+                               seq_printf(s, "GPIO %3d: ", gpio);
+                       seq_printf(s, "%s %s",
+                                       is_in ? "in " : "out",
+                                       value ? "hi"  : "lo");
+
+                       irqstat = irq_desc[irq].status;
+                       if (is_in && ((bank->suspend_wakeup & mask)
+                                       || irqstat & IRQ_TYPE_SENSE_MASK)) {
+                               char    *trigger = NULL;
+
+                               switch (irqstat & IRQ_TYPE_SENSE_MASK) {
+                               case IRQ_TYPE_EDGE_FALLING:
+                                       trigger = "falling";
+                                       break;
+                               case IRQ_TYPE_EDGE_RISING:
+                                       trigger = "rising";
+                                       break;
+                               case IRQ_TYPE_EDGE_BOTH:
+                                       trigger = "bothedge";
+                                       break;
+                               case IRQ_TYPE_LEVEL_LOW:
+                                       trigger = "low";
+                                       break;
+                               case IRQ_TYPE_LEVEL_HIGH:
+                                       trigger = "high";
+                                       break;
+                               case IRQ_TYPE_NONE:
+                                       trigger = "(unspecified)";
+                                       break;
+                               }
+                               seq_printf(s, ", irq-%d %s%s",
+                                               irq, trigger,
+                                               (bank->suspend_wakeup & mask)
+                                                       ? " wakeup" : "");
+                       }
+                       seq_printf(s, "\n");
+               }
+
+               if (bank_is_mpuio(bank)) {
+                       seq_printf(s, "\n");
+                       gpio = 0;
+               }
+       }
+       return 0;
+}
+
+static int dbg_gpio_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_gpio_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+       .open           = dbg_gpio_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int __init omap_gpio_debuginit(void)
+{
+       (void) debugfs_create_file("omap_gpio", S_IRUGO,
+                                       NULL, NULL, &debug_fops);
+       return 0;
+}
+late_initcall(omap_gpio_debuginit);
+#endif
index b8d6f17..f7b9ccd 100644 (file)
@@ -225,11 +225,16 @@ static void omap_mcbsp_dsp_free(void)
 #ifdef CONFIG_ARCH_OMAP2
 static void omap2_mcbsp2_mux_setup(void)
 {
-       omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
-       omap_cfg_reg(R14_24XX_MCBSP2_FSX);
-       omap_cfg_reg(W15_24XX_MCBSP2_DR);
-       omap_cfg_reg(V15_24XX_MCBSP2_DX);
-       omap_cfg_reg(V14_24XX_GPIO117);
+       if (cpu_is_omap2420()) {
+               omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
+               omap_cfg_reg(R14_24XX_MCBSP2_FSX);
+               omap_cfg_reg(W15_24XX_MCBSP2_DR);
+               omap_cfg_reg(V15_24XX_MCBSP2_DX);
+               omap_cfg_reg(V14_24XX_GPIO117);
+       }
+       /*
+        * Need to add MUX settings for OMAP 2430 SDP
+        */
 }
 #endif
 
index 2653106..114f871 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/spinlock.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/system.h>
 #include <asm/hardware.h>
@@ -80,13 +82,13 @@ struct sys_timer omap_timer;
 #define OMAP1_32K_TIMER_TVR            0x00
 #define OMAP1_32K_TIMER_TCR            0x04
 
-#define OMAP_32K_TICKS_PER_HZ          (32768 / HZ)
+#define OMAP_32K_TICKS_PER_SEC         (32768)
 
 /*
  * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
  * so with HZ = 128, TVR = 255.
  */
-#define OMAP_32K_TIMER_TICK_PERIOD     ((32768 / HZ) - 1)
+#define OMAP_32K_TIMER_TICK_PERIOD     ((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
 
 #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)                    \
                                (((nr_jiffies) * (clock_rate)) / HZ)
@@ -142,6 +144,28 @@ static inline void omap_32k_timer_ack_irq(void)
 
 #endif
 
+static void omap_32k_timer_set_mode(enum clock_event_mode mode,
+                                   struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_ONESHOT:
+       case CLOCK_EVT_MODE_PERIODIC:
+               omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               omap_32k_timer_stop();
+               break;
+       }
+}
+
+static struct clock_event_device clockevent_32k_timer = {
+       .name           = "32k-timer",
+       .features       = CLOCK_EVT_FEAT_PERIODIC,
+       .shift          = 32,
+       .set_mode       = omap_32k_timer_set_mode,
+};
+
 /*
  * The 32KHz synchronized timer is an additional timer on 16xx.
  * It is always running.
@@ -170,15 +194,6 @@ omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
 
 static unsigned long omap_32k_last_tick = 0;
 
-/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
-       unsigned long now = omap_32k_sync_timer_read();
-       return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
 /*
  * Returns current time from boot in nsecs. It's OK for this to wrap
  * around for now, as it's just a relative time stamp.
@@ -188,95 +203,16 @@ unsigned long long sched_clock(void)
        return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
 }
 
-/*
- * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
- * function is also called from other interrupts to remove latency
- * issues with dynamic tick. In the dynamic tick case, we need to lock
- * with irqsave.
- */
-static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id)
-{
-       unsigned long now;
-
-       omap_32k_timer_ack_irq();
-       now = omap_32k_sync_timer_read();
-
-       while ((signed long)(now - omap_32k_last_tick)
-                                               >= OMAP_32K_TICKS_PER_HZ) {
-               omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
-               timer_tick();
-       }
-
-       /* Restart timer so we don't drift off due to modulo or dynamic tick.
-        * By default we program the next timer to be continuous to avoid
-        * latencies during high system load. During dynamic tick operation the
-        * continuous timer can be overridden from pm_idle to be longer.
-        */
-       omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
-{
-       return _omap_32k_timer_interrupt(irq, dev_id);
-}
-
 static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
 {
-       unsigned long flags;
+       struct clock_event_device *evt = &clockevent_32k_timer;
+       omap_32k_timer_ack_irq();
 
-       write_seqlock_irqsave(&xtime_lock, flags);
-       _omap_32k_timer_interrupt(irq, dev_id);
-       write_sequnlock_irqrestore(&xtime_lock, flags);
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_NO_IDLE_HZ
-/*
- * Programs the next timer interrupt needed. Called when dynamic tick is
- * enabled, and to reprogram the ticks to skip from pm_idle. Note that
- * we can keep the timer continuous, and don't need to set it to run in
- * one-shot mode. This is because the timer will get reprogrammed again
- * after next interrupt.
- */
-void omap_32k_timer_reprogram(unsigned long next_tick)
-{
-       unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1;
-       unsigned long now = omap_32k_sync_timer_read();
-       unsigned long idled = now - omap_32k_last_tick;
-
-       if (idled + 1 < ticks)
-               ticks -= idled;
-       else
-               ticks = 1;
-       omap_32k_timer_start(ticks);
-}
-
-static struct irqaction omap_32k_timer_irq;
-extern struct timer_update_handler timer_update;
-
-static int omap_32k_timer_enable_dyn_tick(void)
-{
-       /* No need to reprogram timer, just use the next interrupt */
-       return 0;
-}
-
-static int omap_32k_timer_disable_dyn_tick(void)
-{
-       omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-       return 0;
-}
-
-static struct dyn_tick_timer omap_dyn_tick_timer = {
-       .enable         = omap_32k_timer_enable_dyn_tick,
-       .disable        = omap_32k_timer_disable_dyn_tick,
-       .reprogram      = omap_32k_timer_reprogram,
-       .handler        = omap_32k_timer_handler,
-};
-#endif /* CONFIG_NO_IDLE_HZ */
-
 static struct irqaction omap_32k_timer_irq = {
        .name           = "32KHz timer",
        .flags          = IRQF_DISABLED | IRQF_TIMER,
@@ -285,13 +221,8 @@ static struct irqaction omap_32k_timer_irq = {
 
 static __init void omap_init_32k_timer(void)
 {
-#ifdef CONFIG_NO_IDLE_HZ
-       omap_timer.dyn_tick = &omap_dyn_tick_timer;
-#endif
-
        if (cpu_class_is_omap1())
                setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
-       omap_timer.offset  = omap_32k_timer_gettimeoffset;
        omap_32k_last_tick = omap_32k_sync_timer_read();
 
 #ifdef CONFIG_ARCH_OMAP2
@@ -308,7 +239,16 @@ static __init void omap_init_32k_timer(void)
        }
 #endif
 
-       omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+       clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
+                                          NSEC_PER_SEC,
+                                          clockevent_32k_timer.shift);
+       clockevent_32k_timer.max_delta_ns =
+               clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
+       clockevent_32k_timer.min_delta_ns =
+               clockevent_delta2ns(1, &clockevent_32k_timer);
+
+       clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
+       clockevents_register_device(&clockevent_32k_timer);
 }
 
 /*
@@ -326,5 +266,4 @@ static void __init omap_timer_init(void)
 
 struct sys_timer omap_timer = {
        .init           = omap_timer_init,
-       .offset         = NULL,         /* Initialized later */
 };
index d3dc03a..79cda0f 100644 (file)
@@ -404,6 +404,18 @@ int s3c24xx_register_clock(struct clk *clk)
        return 0;
 }
 
+int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
+{
+       int fails = 0;
+
+       for (; nr_clks > 0; nr_clks--, clks++) {
+               if (s3c24xx_register_clock(*clks) < 0)
+                       fails++;
+       }
+
+       return fails;
+}
+
 /* initalise all the clocks */
 
 int __init s3c24xx_setup_clocks(unsigned long xtal,
index 6a2d107..8ce4904 100644 (file)
@@ -181,24 +181,6 @@ s3c_lookup_cpu(unsigned long idcode)
        return NULL;
 }
 
-/* board information */
-
-static struct s3c24xx_board *board;
-
-void s3c24xx_set_board(struct s3c24xx_board *b)
-{
-       int i;
-
-       board = b;
-
-       if (b->clocks_count != 0) {
-               struct clk **ptr = b->clocks;
-
-               for (i = b->clocks_count; i > 0; i--, ptr++)
-                       s3c24xx_register_clock(*ptr);
-       }
-}
-
 /* cpu information */
 
 static struct cpu_table *cpu;
@@ -342,26 +324,6 @@ static int __init s3c_arch_init(void)
                return ret;
 
        ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
-       if (ret != 0)
-               return ret;
-
-       if (board != NULL) {
-               struct platform_device **ptr = board->devices;
-               int i;
-
-               for (i = 0; i < board->devices_count; i++, ptr++) {
-                       ret = platform_device_register(*ptr);
-
-                       if (ret) {
-                               printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr);
-                       }
-               }
-
-               /* mask any error, we may not need all these board
-                * devices */
-               ret = 0;
-       }
-
        return ret;
 }
 
index 4540a80..6f03c93 100644 (file)
@@ -44,7 +44,7 @@ static struct kmem_cache *dma_kmem;
 
 static int dma_channels;
 
-struct s3c24xx_dma_selection dma_sel;
+static struct s3c24xx_dma_selection dma_sel;
 
 /* dma channel state information */
 struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
@@ -880,7 +880,7 @@ static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
        return 0;
 }
 
-void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+static void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
 {
        unsigned long tmp;
        unsigned int timeout = 0x10000;
@@ -957,8 +957,7 @@ static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
        return 0;
 }
 
-int
-s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)
 {
        unsigned long flags;
 
@@ -1280,7 +1279,7 @@ static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long
 
 /* initialisation code */
 
-int __init s3c24xx_dma_sysclass_init(void)
+static int __init s3c24xx_dma_sysclass_init(void)
 {
        int ret = sysdev_class_register(&dma_sysclass);
 
@@ -1292,7 +1291,7 @@ int __init s3c24xx_dma_sysclass_init(void)
 
 core_initcall(s3c24xx_dma_sysclass_init);
 
-int __init s3c24xx_dma_sysdev_register(void)
+static int __init s3c24xx_dma_sysdev_register(void)
 {
        struct s3c2410_dma_chan *cp = s3c2410_chans;
        int channel, ret;
@@ -1396,7 +1395,7 @@ static struct s3c24xx_dma_order *dma_order;
  * channel
 */
 
-struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
 {
        struct s3c24xx_dma_order_ch *ord = NULL;
        struct s3c24xx_dma_map *ch_map;
index ce18639..8fbc884 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
index a0e39d8..2dbb260 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
index e44b9ed..74e89f8 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/bitops.h>
 
 #include <asm/div64.h>
-#include <asm/ptrace.h>
 #include <asm/vfp.h>
 
 #include "vfpinstr.h"
index 0221ba3..b252631 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/bitops.h>
 
 #include <asm/div64.h>
-#include <asm/ptrace.h>
 #include <asm/vfp.h>
 
 #include "vfpinstr.h"
index f17f50e..0714d19 100644 (file)
@@ -182,7 +182,7 @@ extern int end;
 static ulg free_mem_ptr;
 static ulg free_mem_ptr_end;
 
-#define HEAP_SIZE 0x2000
+#define HEAP_SIZE 0x3000
 
 #include "../../../../lib/inflate.c"
 
index e124fcd..dfa25e1 100644 (file)
@@ -91,6 +91,7 @@ SECTIONS
        }
        SECURITY_INIT
 
+       . =  ALIGN (8192);
        __per_cpu_start = .;
        .data.percpu  : { *(.data.percpu) }
        __per_cpu_end = .;
index 97910e0..28eae97 100644 (file)
@@ -57,6 +57,7 @@ SECTIONS
   __alt_instructions_end = .;
  .altinstr_replacement : { *(.altinstr_replacement) }
 
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
index 53d6237..a9af760 100644 (file)
@@ -220,7 +220,7 @@ config PARAVIRT
 
 config VMI
        bool "VMI Paravirt-ops support"
-       depends on PARAVIRT && !COMPAT_VDSO
+       depends on PARAVIRT
        help
          VMI provides a paravirtualized interface to the VMware ESX server
          (it could be used by other hypervisors in theory too, but is not
@@ -571,6 +571,9 @@ choice
                bool "3G/1G user/kernel split (for full 1G low memory)"
        config VMSPLIT_2G
                bool "2G/2G user/kernel split"
+       config VMSPLIT_2G_OPT
+               depends on !HIGHMEM
+               bool "2G/2G user/kernel split (for full 2G low memory)"
        config VMSPLIT_1G
                bool "1G/3G user/kernel split"
 endchoice
@@ -578,7 +581,8 @@ endchoice
 config PAGE_OFFSET
        hex
        default 0xB0000000 if VMSPLIT_3G_OPT
-       default 0x78000000 if VMSPLIT_2G
+       default 0x80000000 if VMSPLIT_2G
+       default 0x78000000 if VMSPLIT_2G_OPT
        default 0x40000000 if VMSPLIT_1G
        default 0xC0000000
 
@@ -915,12 +919,9 @@ source kernel/power/Kconfig
 
 source "drivers/acpi/Kconfig"
 
-menu "APM (Advanced Power Management) BIOS Support"
-depends on PM && !X86_VISWS
-
-config APM
+menuconfig APM
        tristate "APM (Advanced Power Management) BIOS support"
-       depends on PM
+       depends on PM && !X86_VISWS
        ---help---
          APM is a BIOS specification for saving power using several different
          techniques. This is mostly useful for battery powered laptops with
@@ -977,9 +978,10 @@ config APM
          To compile this driver as a module, choose M here: the
          module will be called apm.
 
+if APM
+
 config APM_IGNORE_USER_SUSPEND
        bool "Ignore USER SUSPEND"
-       depends on APM
        help
          This option will ignore USER SUSPEND requests. On machines with a
          compliant APM BIOS, you want to say N. However, on the NEC Versa M
@@ -987,7 +989,6 @@ config APM_IGNORE_USER_SUSPEND
 
 config APM_DO_ENABLE
        bool "Enable PM at boot time"
-       depends on APM
        ---help---
          Enable APM features at boot time. From page 36 of the APM BIOS
          specification: "When disabled, the APM BIOS does not automatically
@@ -1005,7 +1006,6 @@ config APM_DO_ENABLE
 
 config APM_CPU_IDLE
        bool "Make CPU Idle calls when idle"
-       depends on APM
        help
          Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop.
          On some machines, this can activate improved power savings, such as
@@ -1017,7 +1017,6 @@ config APM_CPU_IDLE
 
 config APM_DISPLAY_BLANK
        bool "Enable console blanking using APM"
-       depends on APM
        help
          Enable console blanking using the APM. Some laptops can use this to
          turn off the LCD backlight when the screen blanker of the Linux
@@ -1029,22 +1028,8 @@ config APM_DISPLAY_BLANK
          backlight at all, or it might print a lot of errors to the console,
          especially if you are using gpm.
 
-config APM_RTC_IS_GMT
-       bool "RTC stores time in GMT"
-       depends on APM
-       help
-         Say Y here if your RTC (Real Time Clock a.k.a. hardware clock)
-         stores the time in GMT (Greenwich Mean Time). Say N if your RTC
-         stores localtime.
-
-         It is in fact recommended to store GMT in your RTC, because then you
-         don't have to worry about daylight savings time changes. The only
-         reason not to use GMT in your RTC is if you also run a broken OS
-         that doesn't understand GMT.
-
 config APM_ALLOW_INTS
        bool "Allow interrupts during APM BIOS calls"
-       depends on APM
        help
          Normally we disable external interrupts while we are making calls to
          the APM BIOS as a measure to lessen the effects of a badly behaving
@@ -1055,13 +1040,12 @@ config APM_ALLOW_INTS
 
 config APM_REAL_MODE_POWER_OFF
        bool "Use real mode APM BIOS call to power off"
-       depends on APM
        help
          Use real mode APM BIOS calls to switch off the computer. This is
          a work-around for a number of buggy BIOSes. Switch this option on if
          your computer crashes instead of powering off properly.
 
-endmenu
+endif # APM
 
 source "arch/i386/kernel/cpu/cpufreq/Kconfig"
 
@@ -1073,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 b99c0e2..dce6124 100644 (file)
@@ -43,6 +43,7 @@ config M386
          - "Geode GX/LX" For AMD Geode GX and LX processors.
          - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
          - "VIA C3-2" for VIA C3-2 "Nehemiah" (model 9 and above).
+         - "VIA C7" for VIA C7.
 
          If you don't know what to do, choose "386".
 
@@ -203,6 +204,12 @@ config MVIAC3_2
          of SSE and tells gcc to treat the CPU as a 686.
          Note, this kernel will not boot on older (pre model 9) C3s.
 
+config MVIAC7
+       bool "VIA C7"
+       help
+         Select this for a VIA C7.  Selecting this uses the correct cache
+         shift and tells gcc to treat the CPU as a 686.
+
 endchoice
 
 config X86_GENERIC
@@ -231,16 +238,21 @@ config X86_L1_CACHE_SHIFT
        default "7" if MPENTIUM4 || X86_GENERIC
        default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
        default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
-       default "6" if MK7 || MK8 || MPENTIUMM || MCORE2
+       default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7
+
+config X86_XADD
+       bool
+       depends on !M386
+       default y
 
 config RWSEM_GENERIC_SPINLOCK
        bool
-       depends on M386
+       depends on !X86_XADD
        default y
 
 config RWSEM_XCHGADD_ALGORITHM
        bool
-       depends on !M386
+       depends on X86_XADD
        default y
 
 config ARCH_HAS_ILOG2_U32
@@ -297,7 +309,7 @@ config X86_ALIGNMENT_16
 
 config X86_GOOD_APIC
        bool
-       depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2
+       depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7
        default y
 
 config X86_INTEL_USERCOPY
@@ -322,5 +334,18 @@ config X86_OOSTORE
 
 config X86_TSC
        bool
-       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
+       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
        default y
+
+# this should be set for all -march=.. options where the compiler
+# generates cmov.
+config X86_CMOV
+       bool
+       depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
+       default y
+
+config X86_MINIMUM_CPU_MODEL
+       int
+       default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP
+       default "0"
+
index 458bc16..b31c080 100644 (file)
@@ -85,14 +85,4 @@ config DOUBLEFAULT
           option saves about 4k and might cause you much additional grey
           hair.
 
-config DEBUG_PARAVIRT
-       bool "Enable some paravirtualization debugging"
-       default n
-       depends on PARAVIRT && DEBUG_KERNEL
-       help
-         Currently deliberately clobbers regs which are allowed to be
-         clobbered in inlined paravirt hooks, even in native mode.
-         If turning this off solves a problem, then DISABLE_INTERRUPTS() or
-         ENABLE_INTERRUPTS() is lying about what registers can be clobbered.
-
 endmenu
index bd28f9f..6dc5e5d 100644 (file)
@@ -34,7 +34,7 @@ CHECKFLAGS    += -D__i386__
 CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return
 
 # prevent gcc from keeping the stack 16 byte aligned
-CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
+CFLAGS += -mpreferred-stack-boundary=4
 
 # CPU-specific tuning. Anything which can be shared with UML should go here.
 include $(srctree)/arch/i386/Makefile.cpu
index a32c031..e372b58 100644 (file)
@@ -4,9 +4,9 @@
 #-mtune exists since gcc 3.4
 HAS_MTUNE      := $(call cc-option-yn, -mtune=i386)
 ifeq ($(HAS_MTUNE),y)
-tune           = $(call cc-option,-mtune=$(1),)
+tune           = $(call cc-option,-mtune=$(1),$(2))
 else
-tune           = $(call cc-option,-mcpu=$(1),)
+tune           = $(call cc-option,-mcpu=$(1),$(2))
 endif
 
 align := $(cc-option-align)
@@ -32,7 +32,8 @@ cflags-$(CONFIG_MWINCHIP2)    += $(call cc-option,-march=winchip2,-march=i586)
 cflags-$(CONFIG_MWINCHIP3D)    += $(call cc-option,-march=winchip2,-march=i586)
 cflags-$(CONFIG_MCYRIXIII)     += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
 cflags-$(CONFIG_MVIAC3_2)      += $(call cc-option,-march=c3-2,-march=i686)
-cflags-$(CONFIG_MCORE2)                += -march=i686 $(call cc-option,-mtune=core2,$(call cc-option,-mtune=generic,-mtune=i686))
+cflags-$(CONFIG_MVIAC7)                += -march=i686
+cflags-$(CONFIG_MCORE2)                += -march=i686 $(call tune,core2)
 
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)      += -march=i486
@@ -42,5 +43,5 @@ cflags-$(CONFIG_MGEODEGX1)    += -march=pentium-mmx
 
 # add at the end to overwrite eventual tuning options from earlier
 # cpu entries
-cflags-$(CONFIG_X86_GENERIC)   += $(call tune,generic)
+cflags-$(CONFIG_X86_GENERIC)   += $(call tune,generic,$(call tune,i686))
 
index e979466..bfbc320 100644 (file)
@@ -36,9 +36,9 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE)
 # ---------------------------------------------------------------------------
 
 $(obj)/zImage:  IMAGE_OFFSET := 0x1000
-$(obj)/zImage:  EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK)
+$(obj)/zImage:  EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK)
 $(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
+$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
 $(obj)/bzImage: BUILDFLAGS   := -b
 
 quiet_cmd_image = BUILD   $@
index 1ce7017..b28505c 100644 (file)
@@ -189,7 +189,7 @@ static void putstr(const char *);
 static unsigned long free_mem_ptr;
 static unsigned long free_mem_end_ptr;
 
-#define HEAP_SIZE             0x3000
+#define HEAP_SIZE             0x4000
 
 static char *vidmem = (char *)0xb8000;
 static int vidport;
index 06edf1c..f8b3b9c 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page.h>
+#include <asm/setup.h>
        
 /* Signature words to ensure LILO loaded us right */
 #define SIG1   0xAA55
@@ -81,7 +82,7 @@ start:
 # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
 
                .ascii  "HdrS"          # header signature
-               .word   0x0205          # header version number (>= 0x0105)
+               .word   0x0206          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
 start_sys_seg: .word   SYSSEG
@@ -171,6 +172,10 @@ relocatable_kernel:    .byte 0
 pad2:                  .byte 0
 pad3:                  .word 0
 
+cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
+                                                #added with boot protocol
+                                                #version 2.06
+
 trampoline:    call    start_of_setup
                .align 16
                                        # The offset at this point is 0x240
@@ -297,7 +302,24 @@ good_sig:
 
 loader_panic_mess: .string "Wrong loader, giving up..."
 
+# check minimum cpuid
+# we do this here because it is the last place we can actually
+# show a user visible error message. Later the video modus
+# might be already messed up.
 loader_ok:
+       call verify_cpu
+       testl  %eax,%eax
+       jz      cpu_ok
+       lea     cpu_panic_mess,%si
+       call    prtstr
+1:     jmp     1b
+
+cpu_panic_mess:
+       .asciz  "PANIC: CPU too old for this kernel."
+
+#include "../kernel/verify_cpu.S"
+
+cpu_ok:
 # Get memory size (extended mem, kB)
 
        xorl    %eax, %eax
index c96911c..9da8441 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Wed Mar  7 15:29:47 2007
+# Linux kernel version: 2.6.21-git3
+# Tue May  1 07:30:51 2007
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -108,9 +108,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 # Processor type and features
 #
-# CONFIG_TICK_ONESHOT is not set
-# CONFIG_NO_HZ is not set
-# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 # CONFIG_X86_PC is not set
 # CONFIG_X86_ELAN is not set
@@ -146,9 +146,11 @@ CONFIG_MPENTIUMIII=y
 # CONFIG_MGEODE_LX is not set
 # CONFIG_MCYRIXIII is not set
 # CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
 CONFIG_X86_GENERIC=y
 CONFIG_X86_CMPXCHG=y
 CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_XADD=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -162,6 +164,8 @@ CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_INTEL_USERCOPY=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
 CONFIG_X86_TSC=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_MODEL=4
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
 CONFIG_NR_CPUS=32
@@ -248,7 +252,6 @@ CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
 # CONFIG_ACPI_ASUS is not set
-# CONFIG_ACPI_IBM is not set
 # CONFIG_ACPI_TOSHIBA is not set
 CONFIG_ACPI_BLACKLIST_YEAR=2001
 CONFIG_ACPI_DEBUG=y
@@ -257,10 +260,7 @@ CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
 CONFIG_X86_PM_TIMER=y
 # CONFIG_ACPI_CONTAINER is not set
-
-#
-# APM (Advanced Power Management) BIOS Support
-#
+# CONFIG_ACPI_SBS is not set
 # CONFIG_APM is not set
 
 #
@@ -277,7 +277,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 
 #
 # CPUFreq processor drivers
@@ -349,7 +349,6 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -388,6 +387,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
@@ -443,6 +443,13 @@ CONFIG_IPV6_SIT=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
 # CONFIG_IEEE80211 is not set
 
 #
@@ -463,10 +470,6 @@ CONFIG_FW_LOADER=y
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -513,6 +516,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_SONY_LAPTOP is not set
+# CONFIG_THINKPAD_ACPI is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -548,7 +552,6 @@ CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -580,7 +583,6 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -669,6 +671,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
 
 #
@@ -697,6 +700,7 @@ CONFIG_SATA_ACPI=y
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -762,10 +766,9 @@ CONFIG_IEEE1394=y
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
 
 #
-# Device Drivers
+# Controllers
 #
 
 #
@@ -774,10 +777,11 @@ CONFIG_IEEE1394=y
 CONFIG_IEEE1394_OHCI1394=y
 
 #
-# Protocol Drivers
+# Protocols
 #
 # CONFIG_IEEE1394_VIDEO1394 is not set
 # CONFIG_IEEE1394_SBP2 is not set
+# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
 # CONFIG_IEEE1394_ETH1394 is not set
 # CONFIG_IEEE1394_DV1394 is not set
 CONFIG_IEEE1394_RAWIO=y
@@ -820,7 +824,9 @@ CONFIG_MII=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=y
+# CONFIG_TYPHOON is not set
 
 #
 # Tulip family network device support
@@ -901,9 +907,10 @@ CONFIG_BNX2=y
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
 # Wan interfaces
@@ -917,7 +924,6 @@ CONFIG_BNX2=y
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
 # CONFIG_NETPOLL_TRAP is not set
 CONFIG_NET_POLL_CONTROLLER=y
 
@@ -1050,7 +1056,7 @@ CONFIG_MAX_RAW_DEVS=256
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
-CONFIG_HANGCHECK_TIMER=y
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # TPM devices
@@ -1141,6 +1147,14 @@ CONFIG_SOUND_ICH=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
 
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
 #
 # USB support
 #
@@ -1154,6 +1168,7 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
@@ -1204,10 +1219,6 @@ CONFIG_USB_STORAGE=y
 #
 # USB Input Devices
 #
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_ACECAD is not set
@@ -1528,7 +1539,7 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
+CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
index 4ae3dcf..4f98516 100644 (file)
@@ -39,12 +39,10 @@ obj-$(CONFIG_EARLY_PRINTK)  += early_printk.o
 obj-$(CONFIG_HPET_TIMER)       += hpet.o
 obj-$(CONFIG_K8_NB)            += k8.o
 
-obj-$(CONFIG_VMI)              += vmi.o vmitime.o
+obj-$(CONFIG_VMI)              += vmi.o vmiclock.o
 obj-$(CONFIG_PARAVIRT)         += paravirt.o
 obj-y                          += pcspeaker.o
 
-EXTRA_AFLAGS   := -traditional
-
 obj-$(CONFIG_SCx200)           += scx200.o
 
 # vsyscall.o contains the vsyscall DSO images as __initdata.
index 9ea5b8e..280898b 100644 (file)
@@ -874,7 +874,7 @@ static void __init acpi_process_madt(void)
                                acpi_ioapic = 1;
 
                                smp_found_config = 1;
-                               clustered_apic_check();
+                               setup_apic_routing();
                        }
                }
                if (error == -EINVAL) {
index 8f7efd3..23f78ef 100644 (file)
@@ -10,7 +10,6 @@
 #include <asm/pci-direct.h>
 #include <asm/acpi.h>
 #include <asm/apic.h>
-#include <asm/irq.h>
 
 #ifdef CONFIG_ACPI
 
@@ -48,24 +47,6 @@ static int __init check_bridge(int vendor, int device)
        return 0;
 }
 
-static void check_intel(void)
-{
-       u16 vendor, device;
-
-       vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID);
-
-       if (vendor != PCI_VENDOR_ID_INTEL)
-               return;
-
-       device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
-#ifdef CONFIG_SMP
-       if (device == PCI_DEVICE_ID_INTEL_E7320_MCH ||
-           device == PCI_DEVICE_ID_INTEL_E7520_MCH ||
-           device == PCI_DEVICE_ID_INTEL_E7525_MCH)
-               quirk_intel_irqbalance();
-#endif
-}
-
 void __init check_acpi_pci(void)
 {
        int num, slot, func;
@@ -77,8 +58,6 @@ void __init check_acpi_pci(void)
        if (!early_pci_allowed())
                return;
 
-       check_intel();
-
        /* Poor man's PCI discovery */
        for (num = 0; num < 32; num++) {
                for (slot = 0; slot < 32; slot++) {
index 426f59b..e5cec66 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/alternative.h>
 #include <asm/sections.h>
 
+static int noreplace_smp     = 0;
 static int smp_alt_once      = 0;
 static int debug_alternative = 0;
 
@@ -13,15 +14,33 @@ static int __init bootonly(char *str)
        smp_alt_once = 1;
        return 1;
 }
+__setup("smp-alt-boot", bootonly);
+
 static int __init debug_alt(char *str)
 {
        debug_alternative = 1;
        return 1;
 }
-
-__setup("smp-alt-boot", bootonly);
 __setup("debug-alternative", debug_alt);
 
+static int __init setup_noreplace_smp(char *str)
+{
+       noreplace_smp = 1;
+       return 1;
+}
+__setup("noreplace-smp", setup_noreplace_smp);
+
+#ifdef CONFIG_PARAVIRT
+static int noreplace_paravirt = 0;
+
+static int __init setup_noreplace_paravirt(char *str)
+{
+       noreplace_paravirt = 1;
+       return 1;
+}
+__setup("noreplace-paravirt", setup_noreplace_paravirt);
+#endif
+
 #define DPRINTK(fmt, args...) if (debug_alternative) \
        printk(KERN_DEBUG fmt, args)
 
@@ -132,11 +151,8 @@ static void nop_out(void *insns, unsigned int len)
 }
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
-extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
 extern u8 *__smp_locks[], *__smp_locks_end[];
 
-extern u8 __smp_alt_begin[], __smp_alt_end[];
-
 /* Replace instructions with better alternatives for this CPU type.
    This runs before SMP is initialized to avoid SMP problems with
    self modifying code. This implies that assymetric systems where
@@ -171,29 +187,6 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
 
 #ifdef CONFIG_SMP
 
-static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end)
-{
-       struct alt_instr *a;
-
-       DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end);
-       for (a = start; a < end; a++) {
-               memcpy(a->replacement + a->replacementlen,
-                      a->instr,
-                      a->instrlen);
-       }
-}
-
-static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end)
-{
-       struct alt_instr *a;
-
-       for (a = start; a < end; a++) {
-               memcpy(a->instr,
-                      a->replacement + a->replacementlen,
-                      a->instrlen);
-       }
-}
-
 static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
 {
        u8 **ptr;
@@ -211,6 +204,9 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end
 {
        u8 **ptr;
 
+       if (noreplace_smp)
+               return;
+
        for (ptr = start; ptr < end; ptr++) {
                if (*ptr < text)
                        continue;
@@ -245,6 +241,9 @@ void alternatives_smp_module_add(struct module *mod, char *name,
        struct smp_alt_module *smp;
        unsigned long flags;
 
+       if (noreplace_smp)
+               return;
+
        if (smp_alt_once) {
                if (boot_cpu_has(X86_FEATURE_UP))
                        alternatives_smp_unlock(locks, locks_end,
@@ -279,7 +278,7 @@ void alternatives_smp_module_del(struct module *mod)
        struct smp_alt_module *item;
        unsigned long flags;
 
-       if (smp_alt_once)
+       if (smp_alt_once || noreplace_smp)
                return;
 
        spin_lock_irqsave(&smp_alt, flags);
@@ -310,7 +309,7 @@ void alternatives_smp_switch(int smp)
        return;
 #endif
 
-       if (smp_alt_once)
+       if (noreplace_smp || smp_alt_once)
                return;
        BUG_ON(!smp && (num_online_cpus() > 1));
 
@@ -319,8 +318,6 @@ void alternatives_smp_switch(int smp)
                printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
                clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
                clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
-               alternatives_smp_apply(__smp_alt_instructions,
-                                      __smp_alt_instructions_end);
                list_for_each_entry(mod, &smp_alt_modules, next)
                        alternatives_smp_lock(mod->locks, mod->locks_end,
                                              mod->text, mod->text_end);
@@ -328,8 +325,6 @@ void alternatives_smp_switch(int smp)
                printk(KERN_INFO "SMP alternatives: switching to UP code\n");
                set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
                set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
-               apply_alternatives(__smp_alt_instructions,
-                                  __smp_alt_instructions_end);
                list_for_each_entry(mod, &smp_alt_modules, next)
                        alternatives_smp_unlock(mod->locks, mod->locks_end,
                                                mod->text, mod->text_end);
@@ -340,36 +335,31 @@ void alternatives_smp_switch(int smp)
 #endif
 
 #ifdef CONFIG_PARAVIRT
-void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
+void apply_paravirt(struct paravirt_patch_site *start,
+                   struct paravirt_patch_site *end)
 {
-       struct paravirt_patch *p;
+       struct paravirt_patch_site *p;
+
+       if (noreplace_paravirt)
+               return;
 
        for (p = start; p < end; p++) {
                unsigned int used;
 
                used = paravirt_ops.patch(p->instrtype, p->clobbers, p->instr,
                                          p->len);
-#ifdef CONFIG_DEBUG_PARAVIRT
-               {
-               int i;
-               /* Deliberately clobber regs using "not %reg" to find bugs. */
-               for (i = 0; i < 3; i++) {
-                       if (p->len - used >= 2 && (p->clobbers & (1 << i))) {
-                               memcpy(p->instr + used, "\xf7\xd0", 2);
-                               p->instr[used+1] |= i;
-                               used += 2;
-                       }
-               }
-               }
-#endif
+
+               BUG_ON(used > p->len);
+
                /* Pad the rest with nops */
                nop_out(p->instr + used, p->len - used);
        }
 
-       /* Sync to be conservative, in case we patched following instructions */
+       /* Sync to be conservative, in case we patched following
+        * instructions */
        sync_core();
 }
-extern struct paravirt_patch __start_parainstructions[],
+extern struct paravirt_patch_site __start_parainstructions[],
        __stop_parainstructions[];
 #endif /* CONFIG_PARAVIRT */
 
@@ -396,23 +386,19 @@ void __init alternative_instructions(void)
                        printk(KERN_INFO "SMP alternatives: switching to UP code\n");
                        set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
                        set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
-                       apply_alternatives(__smp_alt_instructions,
-                                          __smp_alt_instructions_end);
                        alternatives_smp_unlock(__smp_locks, __smp_locks_end,
                                                _text, _etext);
                }
                free_init_pages("SMP alternatives",
-                               (unsigned long)__smp_alt_begin,
-                               (unsigned long)__smp_alt_end);
+                               __pa_symbol(&__smp_locks),
+                               __pa_symbol(&__smp_locks_end));
        } else {
-               alternatives_smp_save(__smp_alt_instructions,
-                                     __smp_alt_instructions_end);
                alternatives_smp_module_add(NULL, "core kernel",
                                            __smp_locks, __smp_locks_end,
                                            _text, _etext);
                alternatives_smp_switch(0);
        }
 #endif
-       apply_paravirt(__start_parainstructions, __stop_parainstructions);
+       apply_paravirt(__parainstructions, __parainstructions_end);
        local_irq_restore(flags);
 }
index 93aa911..aca054c 100644 (file)
@@ -129,6 +129,28 @@ static int modern_apic(void)
        return lapic_get_version() >= 0x14;
 }
 
+void apic_wait_icr_idle(void)
+{
+       while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
+               cpu_relax();
+}
+
+unsigned long safe_apic_wait_icr_idle(void)
+{
+       unsigned long send_status;
+       int timeout;
+
+       timeout = 0;
+       do {
+               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
+               if (!send_status)
+                       break;
+               udelay(100);
+       } while (timeout++ < 1000);
+
+       return send_status;
+}
+
 /**
  * enable_NMI_through_LVT0 - enable NMI through local vector table 0
  */
index 064bbf2..367ff1d 100644 (file)
 #include <asm/desc.h>
 #include <asm/i8253.h>
 #include <asm/paravirt.h>
+#include <asm/reboot.h>
 
 #include "io_ports.h"
 
-extern void machine_real_restart(unsigned char *, int);
-
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 extern int (*console_blank_hook)(int);
 #endif
@@ -384,13 +383,6 @@ static int                 ignore_sys_suspend;
 static int                     ignore_normal_resume;
 static int                     bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
 
-#ifdef CONFIG_APM_RTC_IS_GMT
-#      define  clock_cmos_diff 0
-#      define  got_clock_diff  1
-#else
-static long                    clock_cmos_diff;
-static int                     got_clock_diff;
-#endif
 static int                     debug __read_mostly;
 static int                     smp __read_mostly;
 static int                     apm_disabled = -1;
index c375351..27a776c 100644 (file)
 #include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include "sigframe.h"
+#include <asm/pgtable.h>
 #include <asm/fixmap.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include <asm/elf.h>
-#include <asm/pda.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -25,6 +25,9 @@
 #define OFFSET(sym, str, mem) \
        DEFINE(sym, offsetof(struct str, mem));
 
+/* workaround for a warning with -Wmissing-prototypes */
+void foo(void);
+
 void foo(void)
 {
        OFFSET(SIGCONTEXT_eax, sigcontext, eax);
@@ -90,17 +93,18 @@ void foo(void)
        OFFSET(pbe_next, pbe, next);
 
        /* Offset from the sysenter stack to tss.esp0 */
-       DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, esp0) -
+       DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, x86_tss.esp0) -
                 sizeof(struct tss_struct));
 
        DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
-       DEFINE(VDSO_PRELINK, VDSO_PRELINK);
+       DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
+       DEFINE(PTRS_PER_PTE, PTRS_PER_PTE);
+       DEFINE(PTRS_PER_PMD, PTRS_PER_PMD);
+       DEFINE(PTRS_PER_PGD, PTRS_PER_PGD);
 
-       OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+       DEFINE(VDSO_PRELINK_asm, VDSO_PRELINK);
 
-       BLANK();
-       OFFSET(PDA_cpu, i386_pda, cpu_number);
-       OFFSET(PDA_pcurrent, i386_pda, pcurrent);
+       OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
 
 #ifdef CONFIG_PARAVIRT
        BLANK();
index 010aecf..74f27a4 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for x86-compatible CPU details and quirks
 #
 
-obj-y  :=      common.o proc.o
+obj-y  :=      common.o proc.o bugs.o
 
 obj-y  +=      amd.o
 obj-y  +=      cyrix.o
@@ -17,3 +17,5 @@ obj-$(CONFIG_X86_MCE) +=      mcheck/
 
 obj-$(CONFIG_MTRR)     +=      mtrr/
 obj-$(CONFIG_CPU_FREQ) +=      cpufreq/
+
+obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o
index 2d47db4..4fec702 100644 (file)
@@ -53,6 +53,8 @@ static __cpuinit int amd_apic_timer_broken(void)
        return 0;
 }
 
+int force_mwait __cpuinitdata;
+
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
@@ -275,6 +277,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 
        if (amd_apic_timer_broken())
                set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability);
+
+       if (c->x86 == 0x10 && !force_mwait)
+               clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
 }
 
 static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
@@ -314,13 +319,3 @@ int __init amd_init_cpu(void)
        cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
        return 0;
 }
-
-//early_arch_initcall(amd_init_cpu);
-
-static int __init amd_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_AMD] = NULL;
-       return 0;
-}
-
-late_initcall(amd_exit_cpu);
diff --git a/arch/i386/kernel/cpu/bugs.c b/arch/i386/kernel/cpu/bugs.c
new file mode 100644 (file)
index 0000000..54428a2
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *  arch/i386/cpu/bugs.c
+ *
+ *  Copyright (C) 1994  Linus Torvalds
+ *
+ *  Cyrix stuff, June 1998 by:
+ *     - Rafael R. Reilova (moved everything from head.S),
+ *        <rreilova@ececs.uc.edu>
+ *     - Channing Corn (tests & fixes),
+ *     - Andrew D. Balsa (code cleanup).
+ */
+#include <linux/init.h>
+#include <linux/utsname.h>
+#include <asm/processor.h>
+#include <asm/i387.h>
+#include <asm/msr.h>
+#include <asm/paravirt.h>
+#include <asm/alternative.h>
+
+static int __init no_halt(char *s)
+{
+       boot_cpu_data.hlt_works_ok = 0;
+       return 1;
+}
+
+__setup("no-hlt", no_halt);
+
+static int __init mca_pentium(char *s)
+{
+       mca_pentium_flag = 1;
+       return 1;
+}
+
+__setup("mca-pentium", mca_pentium);
+
+static int __init no_387(char *s)
+{
+       boot_cpu_data.hard_math = 0;
+       write_cr0(0xE | read_cr0());
+       return 1;
+}
+
+__setup("no387", no_387);
+
+static double __initdata x = 4195835.0;
+static double __initdata y = 3145727.0;
+
+/*
+ * This used to check for exceptions..
+ * However, it turns out that to support that,
+ * the XMM trap handlers basically had to
+ * be buggy. So let's have a correct XMM trap
+ * handler, and forget about printing out
+ * some status at boot.
+ *
+ * We should really only care about bugs here
+ * anyway. Not features.
+ */
+static void __init check_fpu(void)
+{
+       if (!boot_cpu_data.hard_math) {
+#ifndef CONFIG_MATH_EMULATION
+               printk(KERN_EMERG "No coprocessor found and no math emulation present.\n");
+               printk(KERN_EMERG "Giving up.\n");
+               for (;;) ;
+#endif
+               return;
+       }
+
+/* trap_init() enabled FXSR and company _before_ testing for FP problems here. */
+       /* Test for the divl bug.. */
+       __asm__("fninit\n\t"
+               "fldl %1\n\t"
+               "fdivl %2\n\t"
+               "fmull %2\n\t"
+               "fldl %1\n\t"
+               "fsubp %%st,%%st(1)\n\t"
+               "fistpl %0\n\t"
+               "fwait\n\t"
+               "fninit"
+               : "=m" (*&boot_cpu_data.fdiv_bug)
+               : "m" (*&x), "m" (*&y));
+       if (boot_cpu_data.fdiv_bug)
+               printk("Hmm, FPU with FDIV bug.\n");
+}
+
+static void __init check_hlt(void)
+{
+       if (paravirt_enabled())
+               return;
+
+       printk(KERN_INFO "Checking 'hlt' instruction... ");
+       if (!boot_cpu_data.hlt_works_ok) {
+               printk("disabled\n");
+               return;
+       }
+       halt();
+       halt();
+       halt();
+       halt();
+       printk("OK.\n");
+}
+
+/*
+ *     Most 386 processors have a bug where a POPAD can lock the
+ *     machine even from user space.
+ */
+
+static void __init check_popad(void)
+{
+#ifndef CONFIG_X86_POPAD_OK
+       int res, inp = (int) &res;
+
+       printk(KERN_INFO "Checking for popad bug... ");
+       __asm__ __volatile__(
+         "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
+         : "=&a" (res)
+         : "d" (inp)
+         : "ecx", "edi" );
+       /* If this fails, it means that any user program may lock the CPU hard. Too bad. */
+       if (res != 12345678) printk( "Buggy.\n" );
+                       else printk( "OK.\n" );
+#endif
+}
+
+/*
+ * Check whether we are able to run this kernel safely on SMP.
+ *
+ * - In order to run on a i386, we need to be compiled for i386
+ *   (for due to lack of "invlpg" and working WP on a i386)
+ * - In order to run on anything without a TSC, we need to be
+ *   compiled for a i486.
+ * - In order to support the local APIC on a buggy Pentium machine,
+ *   we need to be compiled with CONFIG_X86_GOOD_APIC disabled,
+ *   which happens implicitly if compiled for a Pentium or lower
+ *   (unless an advanced selection of CPU features is used) as an
+ *   otherwise config implies a properly working local APIC without
+ *   the need to do extra reads from the APIC.
+*/
+
+static void __init check_config(void)
+{
+/*
+ * We'd better not be a i386 if we're configured to use some
+ * i486+ only features! (WP works in supervisor mode and the
+ * new "invlpg" and "bswap" instructions)
+ */
+#if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP)
+       if (boot_cpu_data.x86 == 3)
+               panic("Kernel requires i486+ for 'invlpg' and other features");
+#endif
+
+/*
+ * If we configured ourselves for a TSC, we'd better have one!
+ */
+#ifdef CONFIG_X86_TSC
+       if (!cpu_has_tsc && !tsc_disable)
+               panic("Kernel compiled for Pentium+, requires TSC feature!");
+#endif
+
+/*
+ * If we were told we had a good local APIC, check for buggy Pentia,
+ * i.e. all B steppings and the C2 stepping of P54C when using their
+ * integrated APIC (see 11AP erratum in "Pentium Processor
+ * Specification Update").
+ */
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
+           && cpu_has_apic
+           && boot_cpu_data.x86 == 5
+           && boot_cpu_data.x86_model == 2
+           && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
+               panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
+#endif
+}
+
+
+void __init check_bugs(void)
+{
+       identify_boot_cpu();
+#ifndef CONFIG_SMP
+       printk("CPU: ");
+       print_cpu_info(&boot_cpu_data);
+#endif
+       check_config();
+       check_fpu();
+       check_hlt();
+       check_popad();
+       init_utsname()->machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
+       alternative_instructions();
+}
index 8c25047..473eac8 100644 (file)
@@ -469,13 +469,3 @@ int __init centaur_init_cpu(void)
        cpu_devs[X86_VENDOR_CENTAUR] = &centaur_cpu_dev;
        return 0;
 }
-
-//early_arch_initcall(centaur_init_cpu);
-
-static int __init centaur_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_CENTAUR] = NULL;
-       return 0;
-}
-
-late_initcall(centaur_exit_cpu);
index dcbbd0a..794d593 100644 (file)
 #include <asm/apic.h>
 #include <mach_apic.h>
 #endif
-#include <asm/pda.h>
 
 #include "cpu.h"
 
-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
+DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
+       [GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 },
+       [GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 },
+       [GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 },
+       [GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 },
+       /*
+        * Segments used for calling PnP BIOS have byte granularity.
+        * They code segments and data segments have fixed 64k limits,
+        * the transfer segment sizes are set at run time.
+        */
+       [GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
+       [GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */
+       [GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */
+       [GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */
+       [GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */
+       /*
+        * The APM segments have byte granularity and their bases
+        * are set at run time.  All have 64k limits.
+        */
+       [GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
+       /* 16-bit code */
+       [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
+       [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
 
-struct i386_pda *_cpu_pda[NR_CPUS] __read_mostly;
-EXPORT_SYMBOL(_cpu_pda);
+       [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
+       [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+} };
+EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
 
 static int cachesize_override __cpuinitdata = -1;
 static int disable_x86_fxsr __cpuinitdata;
@@ -368,7 +390,7 @@ __setup("serialnumber", x86_serial_nr_setup);
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 {
        int i;
 
@@ -479,15 +501,22 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 
        /* Init Machine Check Exception if available. */
        mcheck_init(c);
+}
 
-       if (c == &boot_cpu_data)
-               sysenter_setup();
+void __init identify_boot_cpu(void)
+{
+       identify_cpu(&boot_cpu_data);
+       sysenter_setup();
        enable_sep_cpu();
+       mtrr_bp_init();
+}
 
-       if (c == &boot_cpu_data)
-               mtrr_bp_init();
-       else
-               mtrr_ap_init();
+void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+{
+       BUG_ON(c == &boot_cpu_data);
+       identify_cpu(c);
+       enable_sep_cpu();
+       mtrr_ap_init();
 }
 
 #ifdef CONFIG_X86_HT
@@ -601,129 +630,36 @@ void __init early_cpu_init(void)
 #endif
 }
 
-/* Make sure %gs is initialized properly in idle threads */
+/* Make sure %fs is initialized properly in idle threads */
 struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 {
        memset(regs, 0, sizeof(struct pt_regs));
-       regs->xfs = __KERNEL_PDA;
+       regs->xfs = __KERNEL_PERCPU;
        return regs;
 }
 
-static __cpuinit int alloc_gdt(int cpu)
+/* Current gdt points %fs at the "master" per-cpu area: after this,
+ * it's on the real one. */
+void switch_to_new_gdt(void)
 {
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-       struct desc_struct *gdt;
-       struct i386_pda *pda;
-
-       gdt = (struct desc_struct *)cpu_gdt_descr->address;
-       pda = cpu_pda(cpu);
-
-       /*
-        * This is a horrible hack to allocate the GDT.  The problem
-        * is that cpu_init() is called really early for the boot CPU
-        * (and hence needs bootmem) but much later for the secondary
-        * CPUs, when bootmem will have gone away
-        */
-       if (NODE_DATA(0)->bdata->node_bootmem_map) {
-               BUG_ON(gdt != NULL || pda != NULL);
-
-               gdt = alloc_bootmem_pages(PAGE_SIZE);
-               pda = alloc_bootmem(sizeof(*pda));
-               /* alloc_bootmem(_pages) panics on failure, so no check */
-
-               memset(gdt, 0, PAGE_SIZE);
-               memset(pda, 0, sizeof(*pda));
-       } else {
-               /* GDT and PDA might already have been allocated if
-                  this is a CPU hotplug re-insertion. */
-               if (gdt == NULL)
-                       gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
-
-               if (pda == NULL)
-                       pda = kmalloc_node(sizeof(*pda), GFP_KERNEL, cpu_to_node(cpu));
-
-               if (unlikely(!gdt || !pda)) {
-                       free_pages((unsigned long)gdt, 0);
-                       kfree(pda);
-                       return 0;
-               }
-       }
-
-       cpu_gdt_descr->address = (unsigned long)gdt;
-       cpu_pda(cpu) = pda;
-
-       return 1;
-}
+       struct Xgt_desc_struct gdt_descr;
 
-/* Initial PDA used by boot CPU */
-struct i386_pda boot_pda = {
-       ._pda = &boot_pda,
-       .cpu_number = 0,
-       .pcurrent = &init_task,
-};
-
-static inline void set_kernel_fs(void)
-{
-       /* Set %fs for this CPU's PDA.  Memory clobber is to create a
-          barrier with respect to any PDA operations, so the compiler
-          doesn't move any before here. */
-       asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
+       gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
+       gdt_descr.size = GDT_SIZE - 1;
+       load_gdt(&gdt_descr);
+       asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
 }
 
-/* Initialize the CPU's GDT and PDA.  The boot CPU does this for
-   itself, but secondaries find this done for them. */
-__cpuinit int init_gdt(int cpu, struct task_struct *idle)
-{
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-       struct desc_struct *gdt;
-       struct i386_pda *pda;
-
-       /* For non-boot CPUs, the GDT and PDA should already have been
-          allocated. */
-       if (!alloc_gdt(cpu)) {
-               printk(KERN_CRIT "CPU%d failed to allocate GDT or PDA\n", cpu);
-               return 0;
-       }
-
-       gdt = (struct desc_struct *)cpu_gdt_descr->address;
-       pda = cpu_pda(cpu);
-
-       BUG_ON(gdt == NULL || pda == NULL);
-
-       /*
-        * Initialize the per-CPU GDT with the boot GDT,
-        * and set up the GDT descriptor:
-        */
-       memcpy(gdt, cpu_gdt_table, GDT_SIZE);
-       cpu_gdt_descr->size = GDT_SIZE - 1;
-
-       pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
-                       (u32 *)&gdt[GDT_ENTRY_PDA].b,
-                       (unsigned long)pda, sizeof(*pda) - 1,
-                       0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */
-
-       memset(pda, 0, sizeof(*pda));
-       pda->_pda = pda;
-       pda->cpu_number = cpu;
-       pda->pcurrent = idle;
-
-       return 1;
-}
-
-void __cpuinit cpu_set_gdt(int cpu)
-{
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-
-       /* Reinit these anyway, even if they've already been done (on
-          the boot CPU, this will transition from the boot gdt+pda to
-          the real ones). */
-       load_gdt(cpu_gdt_descr);
-       set_kernel_fs();
-}
-
-/* Common CPU init for both boot and secondary CPUs */
-static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+/*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process, such as the GDT
+ * and IDT. We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+void __cpuinit cpu_init(void)
 {
+       int cpu = smp_processor_id();
+       struct task_struct *curr = current;
        struct tss_struct * t = &per_cpu(init_tss, cpu);
        struct thread_struct *thread = &curr->thread;
 
@@ -744,6 +680,7 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
        }
 
        load_idt(&idt_descr);
+       switch_to_new_gdt();
 
        /*
         * Set up and load the per-CPU TSS and LDT
@@ -783,38 +720,6 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
        mxcsr_feature_mask_init();
 }
 
-/* Entrypoint to initialize secondary CPU */
-void __cpuinit secondary_cpu_init(void)
-{
-       int cpu = smp_processor_id();
-       struct task_struct *curr = current;
-
-       _cpu_init(cpu, curr);
-}
-
-/*
- * cpu_init() initializes state that is per-CPU. Some data is already
- * initialized (naturally) in the bootstrap process, such as the GDT
- * and IDT. We reload them nevertheless, this function acts as a
- * 'CPU state barrier', nothing should get across.
- */
-void __cpuinit cpu_init(void)
-{
-       int cpu = smp_processor_id();
-       struct task_struct *curr = current;
-
-       /* Set up the real GDT and PDA, so we can transition from the
-          boot versions. */
-       if (!init_gdt(cpu, curr)) {
-               /* failed to allocate something; not much we can do... */
-               for (;;)
-                       local_irq_enable();
-       }
-
-       cpu_set_gdt(cpu);
-       _cpu_init(cpu, curr);
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 void __cpuinit cpu_uninit(void)
 {
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 de27bd0..0b8411a 100644 (file)
@@ -279,7 +279,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
                 */  
                if (vendor == PCI_VENDOR_ID_CYRIX &&
         (device == PCI_DEVICE_ID_CYRIX_5510 || device == PCI_DEVICE_ID_CYRIX_5520))
-                       pit_latch_buggy = 1;
+                       mark_tsc_unstable("cyrix 5510/5520 detected");
        }
 #endif
                c->x86_cache_size=16;   /* Yep 16K integrated cache thats it */
@@ -448,16 +448,6 @@ int __init cyrix_init_cpu(void)
        return 0;
 }
 
-//early_arch_initcall(cyrix_init_cpu);
-
-static int __init cyrix_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_CYRIX] = NULL;
-       return 0;
-}
-
-late_initcall(cyrix_exit_cpu);
-
 static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
        .c_vendor       = "NSC",
        .c_ident        = { "Geode by NSC" },
@@ -470,12 +460,3 @@ int __init nsc_init_cpu(void)
        return 0;
 }
 
-//early_arch_initcall(nsc_init_cpu);
-
-static int __init nsc_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_NSC] = NULL;
-       return 0;
-}
-
-late_initcall(nsc_exit_cpu);
index 56fe265..dc4e081 100644 (file)
@@ -188,8 +188,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
        }
 #endif
 
-       if (c->x86 == 15)
+       if (c->x86 == 15) {
                set_bit(X86_FEATURE_P4, c->x86_capability);
+               set_bit(X86_FEATURE_SYNC_RDTSC, c->x86_capability);
+       }
        if (c->x86 == 6) 
                set_bit(X86_FEATURE_P3, c->x86_capability);
        if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
index b0862af..f9fa414 100644 (file)
@@ -75,6 +75,9 @@ void amd_mcheck_init(struct cpuinfo_x86 *c)
        machine_check_vector = k7_machine_check;
        wmb();
 
+       if (!cpu_has(c, X86_FEATURE_MCE))
+               return;
+
        printk (KERN_INFO "Intel machine check architecture supported.\n");
        rdmsr (MSR_IA32_MCG_CAP, l, h);
        if (l & (1<<8)) /* Control register present ? */
@@ -82,9 +85,13 @@ void amd_mcheck_init(struct cpuinfo_x86 *c)
        nr_mce_banks = l & 0xff;
 
        /* Clear status for MC index 0 separately, we don't touch CTL,
-        * as some Athlons cause spurious MCEs when its enabled. */
-       wrmsr (MSR_IA32_MC0_STATUS, 0x0, 0x0);
-       for (i=1; i<nr_mce_banks; i++) {
+        * as some K7 Athlons cause spurious MCEs when its enabled. */
+       if (boot_cpu_data.x86 == 6) {
+               wrmsr (MSR_IA32_MC0_STATUS, 0x0, 0x0);
+               i = 1;
+       } else
+               i = 0;
+       for (; i<nr_mce_banks; i++) {
                wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
                wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
        }
index 4f10c62..56cd485 100644 (file)
@@ -38,8 +38,7 @@ void mcheck_init(struct cpuinfo_x86 *c)
 
        switch (c->x86_vendor) {
                case X86_VENDOR_AMD:
-                       if (c->x86==6 || c->x86==15)
-                               amd_mcheck_init(c);
+                       amd_mcheck_init(c);
                        break;
 
                case X86_VENDOR_INTEL:
index 504434a..1509edf 100644 (file)
@@ -124,13 +124,10 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
 
 
 /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */
-static inline int intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
+static inline void intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
 {
        u32 h;
 
-       if (mce_num_extended_msrs == 0)
-               goto done;
-
        rdmsr (MSR_IA32_MCG_EAX, r->eax, h);
        rdmsr (MSR_IA32_MCG_EBX, r->ebx, h);
        rdmsr (MSR_IA32_MCG_ECX, r->ecx, h);
@@ -141,12 +138,6 @@ static inline int intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
        rdmsr (MSR_IA32_MCG_ESP, r->esp, h);
        rdmsr (MSR_IA32_MCG_EFLAGS, r->eflags, h);
        rdmsr (MSR_IA32_MCG_EIP, r->eip, h);
-
-       /* can we rely on kmalloc to do a dynamic
-        * allocation for the reserved registers?
-        */
-done:
-       return mce_num_extended_msrs;
 }
 
 static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
@@ -155,7 +146,6 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
        u32 alow, ahigh, high, low;
        u32 mcgstl, mcgsth;
        int i;
-       struct intel_mce_extended_msrs dbg;
 
        rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
        if (mcgstl & (1<<0))    /* Recoverable ? */
@@ -164,7 +154,9 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
        printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
                smp_processor_id(), mcgsth, mcgstl);
 
-       if (intel_get_extended_msrs(&dbg)) {
+       if (mce_num_extended_msrs > 0) {
+               struct intel_mce_extended_msrs dbg;
+               intel_get_extended_msrs(&dbg);
                printk (KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n",
                        smp_processor_id(), dbg.eip, dbg.eflags);
                printk (KERN_DEBUG "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n",
index f77fc53..5367e32 100644 (file)
@@ -20,13 +20,25 @@ struct mtrr_state {
        mtrr_type def_type;
 };
 
+struct fixed_range_block {
+       int base_msr; /* start address of an MTRR block */
+       int ranges;   /* number of MTRRs in this block  */
+};
+
+static struct fixed_range_block fixed_range_blocks[] = {
+       { MTRRfix64K_00000_MSR, 1 }, /* one  64k MTRR  */
+       { MTRRfix16K_80000_MSR, 2 }, /* two  16k MTRRs */
+       { MTRRfix4K_C0000_MSR,  8 }, /* eight 4k MTRRs */
+       {}
+};
+
 static unsigned long smp_changes_mask;
 static struct mtrr_state mtrr_state = {};
 
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "mtrr."
 
-static __initdata int mtrr_show;
+static int mtrr_show;
 module_param_named(show, mtrr_show, bool, 0);
 
 /*  Get the MSR pair relating to a var range  */
@@ -37,7 +49,7 @@ get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
        rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
 }
 
-static void __init
+static void
 get_fixed_ranges(mtrr_type * frs)
 {
        unsigned int *p = (unsigned int *) frs;
@@ -51,12 +63,18 @@ get_fixed_ranges(mtrr_type * frs)
                rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]);
 }
 
-static void __init print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+void mtrr_save_fixed_ranges(void *info)
+{
+       get_fixed_ranges(mtrr_state.fixed_ranges);
+}
+
+static void __cpuinit print_fixed(unsigned base, unsigned step, const mtrr_type*types)
 {
        unsigned i;
 
        for (i = 0; i < 8; ++i, ++types, base += step)
-               printk(KERN_INFO "MTRR %05X-%05X %s\n", base, base + step - 1, mtrr_attrib_to_str(*types));
+               printk(KERN_INFO "MTRR %05X-%05X %s\n",
+                       base, base + step - 1, mtrr_attrib_to_str(*types));
 }
 
 /*  Grab all of the MTRR state for this CPU into *state  */
@@ -147,6 +165,44 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
                        smp_processor_id(), msr, a, b);
 }
 
+/**
+ * Enable and allow read/write of extended fixed-range MTRR bits on K8 CPUs
+ * see AMD publication no. 24593, chapter 3.2.1 for more information
+ */
+static inline void k8_enable_fixed_iorrs(void)
+{
+       unsigned lo, hi;
+
+       rdmsr(MSR_K8_SYSCFG, lo, hi);
+       mtrr_wrmsr(MSR_K8_SYSCFG, lo
+                               | K8_MTRRFIXRANGE_DRAM_ENABLE
+                               | K8_MTRRFIXRANGE_DRAM_MODIFY, hi);
+}
+
+/**
+ * Checks and updates an fixed-range MTRR if it differs from the value it
+ * should have. If K8 extenstions are wanted, update the K8 SYSCFG MSR also.
+ * see AMD publication no. 24593, chapter 7.8.1, page 233 for more information
+ * \param msr MSR address of the MTTR which should be checked and updated
+ * \param changed pointer which indicates whether the MTRR needed to be changed
+ * \param msrwords pointer to the MSR values which the MSR should have
+ */
+static void set_fixed_range(int msr, int * changed, unsigned int * msrwords)
+{
+       unsigned lo, hi;
+
+       rdmsr(msr, lo, hi);
+
+       if (lo != msrwords[0] || hi != msrwords[1]) {
+               if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+                   boot_cpu_data.x86 == 15 &&
+                   ((msrwords[0] | msrwords[1]) & K8_MTRR_RDMEM_WRMEM_MASK))
+                       k8_enable_fixed_iorrs();
+               mtrr_wrmsr(msr, msrwords[0], msrwords[1]);
+               *changed = TRUE;
+       }
+}
+
 int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg)
 /*  [SUMMARY] Get a free MTRR.
     <base> The starting (base) address of the region.
@@ -196,36 +252,21 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
        *type = base_lo & 0xff;
 }
 
+/**
+ * Checks and updates the fixed-range MTRRs if they differ from the saved set
+ * \param frs pointer to fixed-range MTRR values, saved by get_fixed_ranges()
+ */
 static int set_fixed_ranges(mtrr_type * frs)
 {
-       unsigned int *p = (unsigned int *) frs;
+       unsigned long long *saved = (unsigned long long *) frs;
        int changed = FALSE;
-       int i;
-       unsigned int lo, hi;
+       int block=-1, range;
 
-       rdmsr(MTRRfix64K_00000_MSR, lo, hi);
-       if (p[0] != lo || p[1] != hi) {
-               mtrr_wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
-               changed = TRUE;
-       }
+       while (fixed_range_blocks[++block].ranges)
+           for (range=0; range < fixed_range_blocks[block].ranges; range++)
+               set_fixed_range(fixed_range_blocks[block].base_msr + range,
+                   &changed, (unsigned int *) saved++);
 
-       for (i = 0; i < 2; i++) {
-               rdmsr(MTRRfix16K_80000_MSR + i, lo, hi);
-               if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) {
-                       mtrr_wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2],
-                             p[3 + i * 2]);
-                       changed = TRUE;
-               }
-       }
-
-       for (i = 0; i < 8; i++) {
-               rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi);
-               if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) {
-                       mtrr_wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2],
-                             p[7 + i * 2]);
-                       changed = TRUE;
-               }
-       }
        return changed;
 }
 
@@ -428,7 +469,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
                }
        }
 
-       if (base + size < 0x100) {
+       if (base < 0x100) {
                printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
                       base, size);
                return -EINVAL;
index 0acfb6a..02a2f39 100644 (file)
@@ -729,6 +729,17 @@ void mtrr_ap_init(void)
        local_irq_restore(flags);
 }
 
+/**
+ * Save current fixed-range MTRR state of the BSP
+ */
+void mtrr_save_state(void)
+{
+       if (smp_processor_id() == 0)
+               mtrr_save_fixed_ranges(NULL);
+       else
+               smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1, 1);
+}
+
 static int __init mtrr_init_finialize(void)
 {
        if (!mtrr_if)
index 8bf23cc..961fbe1 100644 (file)
@@ -58,13 +58,3 @@ int __init nexgen_init_cpu(void)
        cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
        return 0;
 }
-
-//early_arch_initcall(nexgen_init_cpu);
-
-static int __init nexgen_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_NEXGEN] = NULL;
-       return 0;
-}
-
-late_initcall(nexgen_exit_cpu);
diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c
new file mode 100644 (file)
index 0000000..2b04c8f
--- /dev/null
@@ -0,0 +1,658 @@
+/* local apic based NMI watchdog for various CPUs.
+   This file also handles reservation of performance counters for coordination
+   with other users (like oprofile).
+
+   Note that these events normally don't tick when the CPU idles. This means
+   the frequency varies with CPU load.
+
+   Original code for K7/P6 written by Keith Owens */
+
+#include <linux/percpu.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/smp.h>
+#include <linux/nmi.h>
+#include <asm/apic.h>
+#include <asm/intel_arch_perfmon.h>
+
+struct nmi_watchdog_ctlblk {
+       unsigned int cccr_msr;
+       unsigned int perfctr_msr;  /* the MSR to reset in NMI handler */
+       unsigned int evntsel_msr;  /* the MSR to select the events to handle */
+};
+
+/* Interface defining a CPU specific perfctr watchdog */
+struct wd_ops {
+       int (*reserve)(void);
+       void (*unreserve)(void);
+       int (*setup)(unsigned nmi_hz);
+       void (*rearm)(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz);
+       void (*stop)(void *);
+       unsigned perfctr;
+       unsigned evntsel;
+       u64 checkbit;
+};
+
+static struct wd_ops *wd_ops;
+
+/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
+ * offset from MSR_P4_BSU_ESCR0.  It will be the max for all platforms (for now)
+ */
+#define NMI_MAX_COUNTER_BITS 66
+
+/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
+ * evtsel_nmi_owner tracks the ownership of the event selection
+ * - different performance counters/ event selection may be reserved for
+ *   different subsystems this reservation system just tries to coordinate
+ *   things a little
+ */
+static DECLARE_BITMAP(perfctr_nmi_owner, NMI_MAX_COUNTER_BITS);
+static DECLARE_BITMAP(evntsel_nmi_owner, NMI_MAX_COUNTER_BITS);
+
+static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
+
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
+{
+       return wd_ops ? msr - wd_ops->perfctr : 0;
+}
+
+/* converts an msr to an appropriate reservation bit */
+/* returns the bit offset of the event selection register */
+static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
+{
+       return wd_ops ? msr - wd_ops->evntsel : 0;
+}
+
+/* checks for a bit availability (hack for oprofile) */
+int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
+{
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       return (!test_bit(counter, perfctr_nmi_owner));
+}
+
+/* checks the an msr for availability */
+int avail_to_resrv_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       return (!test_bit(counter, perfctr_nmi_owner));
+}
+
+int reserve_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       if (!test_and_set_bit(counter, perfctr_nmi_owner))
+               return 1;
+       return 0;
+}
+
+void release_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       clear_bit(counter, perfctr_nmi_owner);
+}
+
+int reserve_evntsel_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_evntsel_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       if (!test_and_set_bit(counter, evntsel_nmi_owner))
+               return 1;
+       return 0;
+}
+
+void release_evntsel_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_evntsel_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       clear_bit(counter, evntsel_nmi_owner);
+}
+
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
+EXPORT_SYMBOL(reserve_perfctr_nmi);
+EXPORT_SYMBOL(release_perfctr_nmi);
+EXPORT_SYMBOL(reserve_evntsel_nmi);
+EXPORT_SYMBOL(release_evntsel_nmi);
+
+void disable_lapic_nmi_watchdog(void)
+{
+       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
+
+       if (atomic_read(&nmi_active) <= 0)
+               return;
+
+       on_each_cpu(wd_ops->stop, NULL, 0, 1);
+       wd_ops->unreserve();
+
+       BUG_ON(atomic_read(&nmi_active) != 0);
+}
+
+void enable_lapic_nmi_watchdog(void)
+{
+       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
+
+       /* are we already enabled */
+       if (atomic_read(&nmi_active) != 0)
+               return;
+
+       /* are we lapic aware */
+       if (!wd_ops)
+               return;
+       if (!wd_ops->reserve()) {
+               printk(KERN_ERR "NMI watchdog: cannot reserve perfctrs\n");
+               return;
+       }
+
+       on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+       touch_nmi_watchdog();
+}
+
+/*
+ * Activate the NMI watchdog via the local APIC.
+ */
+
+static unsigned int adjust_for_32bit_ctr(unsigned int hz)
+{
+       u64 counter_val;
+       unsigned int retval = hz;
+
+       /*
+        * On Intel CPUs with P6/ARCH_PERFMON only 32 bits in the counter
+        * are writable, with higher bits sign extending from bit 31.
+        * So, we can only program the counter with 31 bit values and
+        * 32nd bit should be 1, for 33.. to be 1.
+        * Find the appropriate nmi_hz
+        */
+       counter_val = (u64)cpu_khz * 1000;
+       do_div(counter_val, retval);
+       if (counter_val > 0x7fffffffULL) {
+               u64 count = (u64)cpu_khz * 1000;
+               do_div(count, 0x7fffffffUL);
+               retval = count + 1;
+       }
+       return retval;
+}
+
+static void
+write_watchdog_counter(unsigned int perfctr_msr, const char *descr, unsigned nmi_hz)
+{
+       u64 count = (u64)cpu_khz * 1000;
+
+       do_div(count, nmi_hz);
+       if(descr)
+               Dprintk("setting %s to -0x%08Lx\n", descr, count);
+       wrmsrl(perfctr_msr, 0 - count);
+}
+
+static void write_watchdog_counter32(unsigned int perfctr_msr,
+               const char *descr, unsigned nmi_hz)
+{
+       u64 count = (u64)cpu_khz * 1000;
+
+       do_div(count, nmi_hz);
+       if(descr)
+               Dprintk("setting %s to -0x%08Lx\n", descr, count);
+       wrmsr(perfctr_msr, (u32)(-count), 0);
+}
+
+/* AMD K7/K8/Family10h/Family11h support. AMD keeps this interface
+   nicely stable so there is not much variety */
+
+#define K7_EVNTSEL_ENABLE      (1 << 22)
+#define K7_EVNTSEL_INT         (1 << 20)
+#define K7_EVNTSEL_OS          (1 << 17)
+#define K7_EVNTSEL_USR         (1 << 16)
+#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
+#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+
+static int setup_k7_watchdog(unsigned nmi_hz)
+{
+       unsigned int perfctr_msr, evntsel_msr;
+       unsigned int evntsel;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       perfctr_msr = MSR_K7_PERFCTR0;
+       evntsel_msr = MSR_K7_EVNTSEL0;
+
+       wrmsrl(perfctr_msr, 0UL);
+
+       evntsel = K7_EVNTSEL_INT
+               | K7_EVNTSEL_OS
+               | K7_EVNTSEL_USR
+               | K7_NMI_EVENT;
+
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       write_watchdog_counter(perfctr_msr, "K7_PERFCTR0",nmi_hz);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       evntsel |= K7_EVNTSEL_ENABLE;
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       return 1;
+}
+
+static void single_msr_stop_watchdog(void *arg)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       wrmsr(wd->evntsel_msr, 0, 0);
+}
+
+static int single_msr_reserve(void)
+{
+       if (!reserve_perfctr_nmi(wd_ops->perfctr))
+               return 0;
+
+       if (!reserve_evntsel_nmi(wd_ops->evntsel)) {
+               release_perfctr_nmi(wd_ops->perfctr);
+               return 0;
+       }
+       return 1;
+}
+
+static void single_msr_unreserve(void)
+{
+       release_evntsel_nmi(wd_ops->perfctr);
+       release_perfctr_nmi(wd_ops->evntsel);
+}
+
+static void single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
+{
+       /* start the cycle over again */
+       write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
+}
+
+static struct wd_ops k7_wd_ops = {
+       .reserve = single_msr_reserve,
+       .unreserve = single_msr_unreserve,
+       .setup = setup_k7_watchdog,
+       .rearm = single_msr_rearm,
+       .stop = single_msr_stop_watchdog,
+       .perfctr = MSR_K7_PERFCTR0,
+       .evntsel = MSR_K7_EVNTSEL0,
+       .checkbit = 1ULL<<63,
+};
+
+/* Intel Model 6 (PPro+,P2,P3,P-M,Core1) */
+
+#define P6_EVNTSEL0_ENABLE     (1 << 22)
+#define P6_EVNTSEL_INT         (1 << 20)
+#define P6_EVNTSEL_OS          (1 << 17)
+#define P6_EVNTSEL_USR         (1 << 16)
+#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
+#define P6_NMI_EVENT           P6_EVENT_CPU_CLOCKS_NOT_HALTED
+
+static int setup_p6_watchdog(unsigned nmi_hz)
+{
+       unsigned int perfctr_msr, evntsel_msr;
+       unsigned int evntsel;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       perfctr_msr = MSR_P6_PERFCTR0;
+       evntsel_msr = MSR_P6_EVNTSEL0;
+
+       wrmsrl(perfctr_msr, 0UL);
+
+       evntsel = P6_EVNTSEL_INT
+               | P6_EVNTSEL_OS
+               | P6_EVNTSEL_USR
+               | P6_NMI_EVENT;
+
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+       write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0",nmi_hz);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       evntsel |= P6_EVNTSEL0_ENABLE;
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       return 1;
+}
+
+static void p6_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
+{
+       /* P6 based Pentium M need to re-unmask
+        * the apic vector but it doesn't hurt
+        * other P6 variant.
+        * ArchPerfom/Core Duo also needs this */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       /* P6/ARCH_PERFMON has 32 bit counter write */
+       write_watchdog_counter32(wd->perfctr_msr, NULL,nmi_hz);
+}
+
+static struct wd_ops p6_wd_ops = {
+       .reserve = single_msr_reserve,
+       .unreserve = single_msr_unreserve,
+       .setup = setup_p6_watchdog,
+       .rearm = p6_rearm,
+       .stop = single_msr_stop_watchdog,
+       .perfctr = MSR_P6_PERFCTR0,
+       .evntsel = MSR_P6_EVNTSEL0,
+       .checkbit = 1ULL<<39,
+};
+
+/* Intel P4 performance counters. By far the most complicated of all. */
+
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
+#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
+#define P4_ESCR_OS             (1<<3)
+#define P4_ESCR_USR            (1<<2)
+#define P4_CCCR_OVF_PMI0       (1<<26)
+#define P4_CCCR_OVF_PMI1       (1<<27)
+#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
+#define P4_CCCR_COMPLEMENT     (1<<19)
+#define P4_CCCR_COMPARE                (1<<18)
+#define P4_CCCR_REQUIRED       (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE         (1<<12)
+#define P4_CCCR_OVF            (1<<31)
+
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+
+static int setup_p4_watchdog(unsigned nmi_hz)
+{
+       unsigned int perfctr_msr, evntsel_msr, cccr_msr;
+       unsigned int evntsel, cccr_val;
+       unsigned int misc_enable, dummy;
+       unsigned int ht_num;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
+       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+               return 0;
+
+#ifdef CONFIG_SMP
+       /* detect which hyperthread we are on */
+       if (smp_num_siblings == 2) {
+               unsigned int ebx, apicid;
+
+               ebx = cpuid_ebx(1);
+               apicid = (ebx >> 24) & 0xff;
+               ht_num = apicid & 1;
+       } else
+#endif
+               ht_num = 0;
+
+       /* performance counters are shared resources
+        * assign each hyperthread its own set
+        * (re-use the ESCR0 register, seems safe
+        * and keeps the cccr_val the same)
+        */
+       if (!ht_num) {
+               /* logical cpu 0 */
+               perfctr_msr = MSR_P4_IQ_PERFCTR0;
+               evntsel_msr = MSR_P4_CRU_ESCR0;
+               cccr_msr = MSR_P4_IQ_CCCR0;
+               cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
+       } else {
+               /* logical cpu 1 */
+               perfctr_msr = MSR_P4_IQ_PERFCTR1;
+               evntsel_msr = MSR_P4_CRU_ESCR0;
+               cccr_msr = MSR_P4_IQ_CCCR1;
+               cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
+       }
+
+       evntsel = P4_ESCR_EVENT_SELECT(0x3F)
+               | P4_ESCR_OS
+               | P4_ESCR_USR;
+
+       cccr_val |= P4_CCCR_THRESHOLD(15)
+                | P4_CCCR_COMPLEMENT
+                | P4_CCCR_COMPARE
+                | P4_CCCR_REQUIRED;
+
+       wrmsr(evntsel_msr, evntsel, 0);
+       wrmsr(cccr_msr, cccr_val, 0);
+       write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0", nmi_hz);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       cccr_val |= P4_CCCR_ENABLE;
+       wrmsr(cccr_msr, cccr_val, 0);
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = cccr_msr;
+       return 1;
+}
+
+static void stop_p4_watchdog(void *arg)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+       wrmsr(wd->cccr_msr, 0, 0);
+       wrmsr(wd->evntsel_msr, 0, 0);
+}
+
+static int p4_reserve(void)
+{
+       if (!reserve_perfctr_nmi(MSR_P4_IQ_PERFCTR0))
+               return 0;
+#ifdef CONFIG_SMP
+       if (smp_num_siblings > 1 && !reserve_perfctr_nmi(MSR_P4_IQ_PERFCTR1))
+               goto fail1;
+#endif
+       if (!reserve_evntsel_nmi(MSR_P4_CRU_ESCR0))
+               goto fail2;
+       /* RED-PEN why is ESCR1 not reserved here? */
+       return 1;
+ fail2:
+#ifdef CONFIG_SMP
+       if (smp_num_siblings > 1)
+               release_perfctr_nmi(MSR_P4_IQ_PERFCTR1);
+ fail1:
+#endif
+       release_perfctr_nmi(MSR_P4_IQ_PERFCTR0);
+       return 0;
+}
+
+static void p4_unreserve(void)
+{
+#ifdef CONFIG_SMP
+       if (smp_num_siblings > 1)
+               release_evntsel_nmi(MSR_P4_IQ_PERFCTR1);
+#endif
+       release_evntsel_nmi(MSR_P4_IQ_PERFCTR0);
+       release_perfctr_nmi(MSR_P4_CRU_ESCR0);
+}
+
+static void p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
+{
+       unsigned dummy;
+       /*
+        * P4 quirks:
+        * - An overflown perfctr will assert its interrupt
+        *   until the OVF flag in its CCCR is cleared.
+        * - LVTPC is masked on interrupt and must be
+        *   unmasked by the LVTPC handler.
+        */
+       rdmsrl(wd->cccr_msr, dummy);
+       dummy &= ~P4_CCCR_OVF;
+       wrmsrl(wd->cccr_msr, dummy);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       /* start the cycle over again */
+       write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
+}
+
+static struct wd_ops p4_wd_ops = {
+       .reserve = p4_reserve,
+       .unreserve = p4_unreserve,
+       .setup = setup_p4_watchdog,
+       .rearm = p4_rearm,
+       .stop = stop_p4_watchdog,
+       /* RED-PEN this is wrong for the other sibling */
+       .perfctr = MSR_P4_BPU_PERFCTR0,
+       .evntsel = MSR_P4_BSU_ESCR0,
+       .checkbit = 1ULL<<39,
+};
+
+/* Watchdog using the Intel architected PerfMon. Used for Core2 and hopefully
+   all future Intel CPUs. */
+
+#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
+static int setup_intel_arch_watchdog(unsigned nmi_hz)
+{
+       unsigned int ebx;
+       union cpuid10_eax eax;
+       unsigned int unused;
+       unsigned int perfctr_msr, evntsel_msr;
+       unsigned int evntsel;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       /*
+        * Check whether the Architectural PerfMon supports
+        * Unhalted Core Cycles Event or not.
+        * NOTE: Corresponding bit = 0 in ebx indicates event present.
+        */
+       cpuid(10, &(eax.full), &ebx, &unused, &unused);
+       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+               return 0;
+
+       perfctr_msr = MSR_ARCH_PERFMON_PERFCTR1;
+       evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL1;
+
+       wrmsrl(perfctr_msr, 0UL);
+
+       evntsel = ARCH_PERFMON_EVENTSEL_INT
+               | ARCH_PERFMON_EVENTSEL_OS
+               | ARCH_PERFMON_EVENTSEL_USR
+               | ARCH_PERFMON_NMI_EVENT_SEL
+               | ARCH_PERFMON_NMI_EVENT_UMASK;
+
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+       write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0", nmi_hz);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       wd_ops->checkbit = 1ULL << (eax.split.bit_width - 1);
+       return 1;
+}
+
+static struct wd_ops intel_arch_wd_ops = {
+       .reserve = single_msr_reserve,
+       .unreserve = single_msr_unreserve,
+       .setup = setup_intel_arch_watchdog,
+       .rearm = p6_rearm,
+       .stop = single_msr_stop_watchdog,
+       .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
+       .evntsel = MSR_ARCH_PERFMON_EVENTSEL0,
+};
+
+static void probe_nmi_watchdog(void)
+{
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
+                   boot_cpu_data.x86 != 16)
+                       return;
+               wd_ops = &k7_wd_ops;
+               break;
+       case X86_VENDOR_INTEL:
+               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+                       wd_ops = &intel_arch_wd_ops;
+                       break;
+               }
+               switch (boot_cpu_data.x86) {
+               case 6:
+                       if (boot_cpu_data.x86_model > 0xd)
+                               return;
+
+                       wd_ops = &p6_wd_ops;
+                       break;
+               case 15:
+                       if (boot_cpu_data.x86_model > 0x4)
+                               return;
+
+                       wd_ops = &p4_wd_ops;
+                       break;
+               default:
+                       return;
+               }
+               break;
+       }
+}
+
+/* Interface to nmi.c */
+
+int lapic_watchdog_init(unsigned nmi_hz)
+{
+       if (!wd_ops) {
+               probe_nmi_watchdog();
+               if (!wd_ops)
+                       return -1;
+       }
+
+       if (!(wd_ops->setup(nmi_hz))) {
+               printk(KERN_ERR "Cannot setup NMI watchdog on CPU %d\n",
+                      raw_smp_processor_id());
+               return -1;
+       }
+
+       return 0;
+}
+
+void lapic_watchdog_stop(void)
+{
+       if (wd_ops)
+               wd_ops->stop(NULL);
+}
+
+unsigned lapic_adjust_nmi_hz(unsigned hz)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+       if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
+           wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR1)
+               hz = adjust_for_32bit_ctr(hz);
+       return hz;
+}
+
+int lapic_wd_event(unsigned nmi_hz)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+       u64 ctr;
+       rdmsrl(wd->perfctr_msr, ctr);
+       if (ctr & wd_ops->checkbit) { /* perfctr still running? */
+               return 0;
+       }
+       wd_ops->rearm(wd, nmi_hz);
+       return 1;
+}
+
+int lapic_watchdog_ok(void)
+{
+       return wd_ops != NULL;
+}
index 47e3ebb..89d91e6 100644 (file)
@@ -72,8 +72,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "stc",
                "100mhzsteps",
                "hwpstate",
-               NULL,
-               NULL,   /* constant_tsc - moved to flags */
+               "",     /* constant_tsc - moved to flags */
                /* nothing */
        };
        struct cpuinfo_x86 *c = v;
index 9317f74..50076f2 100644 (file)
@@ -50,12 +50,3 @@ int __init rise_init_cpu(void)
        return 0;
 }
 
-//early_arch_initcall(rise_init_cpu);
-
-static int __init rise_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_RISE] = NULL;
-       return 0;
-}
-
-late_initcall(rise_exit_cpu);
index 5678d46..6471a5a 100644 (file)
@@ -112,13 +112,3 @@ int __init transmeta_init_cpu(void)
        cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev;
        return 0;
 }
-
-//early_arch_initcall(transmeta_init_cpu);
-
-static int __init transmeta_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_TRANSMETA] = NULL;
-       return 0;
-}
-
-late_initcall(transmeta_exit_cpu);
index 1bf3f87..a7a4e75 100644 (file)
@@ -24,13 +24,3 @@ int __init umc_init_cpu(void)
        cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev;
        return 0;
 }
-
-//early_arch_initcall(umc_init_cpu);
-
-static int __init umc_exit_cpu(void)
-{
-       cpu_devs[X86_VENDOR_UMC] = NULL;
-       return 0;
-}
-
-late_initcall(umc_exit_cpu);
index b4d14c2..265c559 100644 (file)
@@ -33,7 +33,7 @@ static void doublefault_fn(void)
                printk("double fault, tss at %08lx\n", tss);
 
                if (ptr_ok(tss)) {
-                       struct tss_struct *t = (struct tss_struct *)tss;
+                       struct i386_hw_tss *t = (struct i386_hw_tss *)tss;
 
                        printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp);
 
@@ -49,18 +49,21 @@ static void doublefault_fn(void)
 }
 
 struct tss_struct doublefault_tss __cacheline_aligned = {
-       .esp0           = STACK_START,
-       .ss0            = __KERNEL_DS,
-       .ldt            = 0,
-       .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
+       .x86_tss = {
+               .esp0           = STACK_START,
+               .ss0            = __KERNEL_DS,
+               .ldt            = 0,
+               .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
 
-       .eip            = (unsigned long) doublefault_fn,
-       .eflags         = X86_EFLAGS_SF | 0x2,  /* 0x2 bit is always set */
-       .esp            = STACK_START,
-       .es             = __USER_DS,
-       .cs             = __KERNEL_CS,
-       .ss             = __KERNEL_DS,
-       .ds             = __USER_DS,
+               .eip            = (unsigned long) doublefault_fn,
+               /* 0x2 bit is always set */
+               .eflags         = X86_EFLAGS_SF | 0x2,
+               .esp            = STACK_START,
+               .es             = __USER_DS,
+               .cs             = __KERNEL_CS,
+               .ss             = __KERNEL_DS,
+               .ds             = __USER_DS,
 
-       .__cr3          = __pa(swapper_pg_dir)
+               .__cr3          = __pa(swapper_pg_dir)
+       }
 };
index 70f3956..9645bb5 100644 (file)
@@ -161,26 +161,27 @@ static struct resource standard_io_resources[] = { {
 
 static int __init romsignature(const unsigned char *rom)
 {
+       const unsigned short * const ptr = (const unsigned short *)rom;
        unsigned short sig;
 
-       return probe_kernel_address((const unsigned short *)rom, sig) == 0 &&
-              sig == ROMSIGNATURE;
+       return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
 }
 
-static int __init romchecksum(unsigned char *rom, unsigned long length)
+static int __init romchecksum(const unsigned char *rom, unsigned long length)
 {
-       unsigned char sum;
+       unsigned char sum, c;
 
-       for (sum = 0; length; length--)
-               sum += *rom++;
-       return sum == 0;
+       for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
+               sum += c;
+       return !length && !sum;
 }
 
 static void __init probe_roms(void)
 {
+       const unsigned char *rom;
        unsigned long start, length, upper;
-       unsigned char *rom;
-       int           i;
+       unsigned char c;
+       int i;
 
        /* video rom */
        upper = adapter_rom_resources[0].start;
@@ -191,8 +192,11 @@ static void __init probe_roms(void)
 
                video_rom_resource.start = start;
 
+               if (probe_kernel_address(rom + 2, c) != 0)
+                       continue;
+
                /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
+               length = c * 512;
 
                /* if checksum okay, trust length byte */
                if (length && romchecksum(rom, length))
@@ -226,8 +230,11 @@ static void __init probe_roms(void)
                if (!romsignature(rom))
                        continue;
 
+               if (probe_kernel_address(rom + 2, c) != 0)
+                       continue;
+
                /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
+               length = c * 512;
 
                /* but accept any length that fits if checksum okay */
                if (!length || start + length > upper || !romchecksum(rom, length))
@@ -386,10 +393,8 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
                   ____________________33__
                   ______________________4_
        */
-       printk("sanitize start\n");
        /* if there's only one memory region, don't bother */
        if (*pnr_map < 2) {
-               printk("sanitize bail 0\n");
                return -1;
        }
 
@@ -398,7 +403,6 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
        /* bail out if we find any unreasonable addresses in bios map */
        for (i=0; i<old_nr; i++)
                if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {
-                       printk("sanitize bail 1\n");
                        return -1;
                }
 
@@ -494,7 +498,6 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
        memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
        *pnr_map = new_nr;
 
-       printk("sanitize end\n");
        return 0;
 }
 
@@ -525,7 +528,6 @@ int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
                unsigned long long size = biosmap->size;
                unsigned long long end = start + size;
                unsigned long type = biosmap->type;
-               printk("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n", start, size, end, type);
 
                /* Overflow in 64 bits? Ignore the memory map. */
                if (start > end)
@@ -536,17 +538,11 @@ int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
                 * Not right. Fix it up.
                 */
                if (type == E820_RAM) {
-                       printk("copy_e820_map() type is E820_RAM\n");
                        if (start < 0x100000ULL && end > 0xA0000ULL) {
-                               printk("copy_e820_map() lies in range...\n");
-                               if (start < 0xA0000ULL) {
-                                       printk("copy_e820_map() start < 0xA0000ULL\n");
+                               if (start < 0xA0000ULL)
                                        add_memory_region(start, 0xA0000ULL-start, type);
-                               }
-                               if (end <= 0x100000ULL) {
-                                       printk("copy_e820_map() end <= 0x100000ULL\n");
+                               if (end <= 0x100000ULL)
                                        continue;
-                               }
                                start = 0x100000ULL;
                                size = end - start;
                        }
@@ -818,6 +814,26 @@ void __init limit_regions(unsigned long long size)
        print_memory_map("limit_regions endfunc");
 }
 
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int
+e820_any_mapped(u64 start, u64 end, unsigned type)
+{
+       int i;
+       for (i = 0; i < e820.nr_map; i++) {
+               const struct e820entry *ei = &e820.map[i];
+               if (type && ei->type != type)
+                       continue;
+               if (ei->addr >= end || ei->addr + ei->size <= start)
+                       continue;
+               return 1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(e820_any_mapped);
+
  /*
   * This function checks if the entire range <start,end> is mapped with type.
   *
index 8f9c624..dd9e7fa 100644 (file)
@@ -69,13 +69,11 @@ static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
 {
        unsigned long cr4;
        unsigned long temp;
-       struct Xgt_desc_struct *cpu_gdt_descr;
+       struct Xgt_desc_struct gdt_descr;
 
        spin_lock(&efi_rt_lock);
        local_irq_save(efi_rt_eflags);
 
-       cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
-
        /*
         * If I don't have PSE, I should just duplicate two entries in page
         * directory. If I have PSE, I just need to duplicate one entry in
@@ -105,17 +103,19 @@ static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
         */
        local_flush_tlb();
 
-       cpu_gdt_descr->address = __pa(cpu_gdt_descr->address);
-       load_gdt(cpu_gdt_descr);
+       gdt_descr.address = __pa(get_cpu_gdt_table(0));
+       gdt_descr.size = GDT_SIZE - 1;
+       load_gdt(&gdt_descr);
 }
 
 static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
 {
        unsigned long cr4;
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
+       struct Xgt_desc_struct gdt_descr;
 
-       cpu_gdt_descr->address = (unsigned long)__va(cpu_gdt_descr->address);
-       load_gdt(cpu_gdt_descr);
+       gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
+       gdt_descr.size = GDT_SIZE - 1;
+       load_gdt(&gdt_descr);
 
        cr4 = read_cr4();
 
index 18bddcb..b1f16ee 100644 (file)
@@ -15,7 +15,7 @@
  * I changed all the .align's to 4 (16 byte alignment), as that's faster
  * on a 486.
  *
- * Stack layout in 'ret_from_system_call':
+ * Stack layout in 'syscall_exit':
  *     ptrace needs to have all regs on the stack.
  *     if the order here is changed, it needs to be
  *     updated in fork.c:copy_process, signal.c:do_signal,
@@ -132,7 +132,7 @@ VM_MASK             = 0x00020000
        movl $(__USER_DS), %edx; \
        movl %edx, %ds; \
        movl %edx, %es; \
-       movl $(__KERNEL_PDA), %edx; \
+       movl $(__KERNEL_PERCPU), %edx; \
        movl %edx, %fs
 
 #define RESTORE_INT_REGS \
@@ -305,16 +305,12 @@ sysenter_past_esp:
        pushl $(__USER_CS)
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET cs, 0*/
-#ifndef CONFIG_COMPAT_VDSO
        /*
         * Push current_thread_info()->sysenter_return to the stack.
         * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
         * pushed above; +8 corresponds to copy_thread's esp0 setting.
         */
        pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
-#else
-       pushl $SYSENTER_RETURN
-#endif
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET eip, 0
 
@@ -342,7 +338,7 @@ sysenter_past_esp:
        jae syscall_badsys
        call *sys_call_table(,%eax,4)
        movl %eax,PT_EAX(%esp)
-       DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX)
+       DISABLE_INTERRUPTS(CLBR_ANY)
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx
@@ -560,9 +556,7 @@ END(syscall_badsys)
 
 #define FIXUP_ESPFIX_STACK \
        /* since we are on a wrong stack, we cant make it a C code :( */ \
-       movl %fs:PDA_cpu, %ebx; \
-       PER_CPU(cpu_gdt_descr, %ebx); \
-       movl GDS_address(%ebx), %ebx; \
+       PER_CPU(gdt_page, %ebx); \
        GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
        addl %esp, %eax; \
        pushl $__KERNEL_DS; \
@@ -635,7 +629,7 @@ ENTRY(name)                         \
        SAVE_ALL;                       \
        TRACE_IRQS_OFF                  \
        movl %esp,%eax;                 \
-       call smp_/**/name;              \
+       call smp_##name;                \
        jmp ret_from_intr;              \
        CFI_ENDPROC;                    \
 ENDPROC(name)
@@ -643,11 +637,6 @@ ENDPROC(name)
 /* The include is where all of the SMP etc. interrupts come from */
 #include "entry_arch.h"
 
-/* This alternate entry is needed because we hijack the apic LVTT */
-#if defined(CONFIG_VMI) && defined(CONFIG_X86_LOCAL_APIC)
-BUILD_INTERRUPT(apic_vmi_timer_interrupt,LOCAL_TIMER_VECTOR)
-#endif
-
 KPROBE_ENTRY(page_fault)
        RING0_EC_FRAME
        pushl $do_page_fault
@@ -686,7 +675,7 @@ error_code:
        pushl %fs
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET fs, 0*/
-       movl $(__KERNEL_PDA), %ecx
+       movl $(__KERNEL_PERCPU), %ecx
        movl %ecx, %fs
        UNWIND_ESPFIX_STACK
        popl %ecx
index 3fa7f93..9b10af6 100644 (file)
 
 /*
  * This is how much memory *in addition to the memory covered up to
- * and including _end* we need mapped initially.  We need one bit for
- * each possible page, but only in low memory, which means
- * 2^32/4096/8 = 128K worst case (4G/4G split.)
+ * and including _end* we need mapped initially.
+ * We need:
+ *  - one bit for each possible page, but only in low memory, which means
+ *     2^32/4096/8 = 128K worst case (4G/4G split.)
+ *  - enough space to map all low memory, which means
+ *     (2^32/4096) / 1024 pages (worst case, non PAE)
+ *     (2^32/4096) / 512 + 4 pages (worst case for PAE)
+ *  - a few pages for allocator use before the kernel pagetable has
+ *     been set up
  *
  * Modulo rounding, each megabyte assigned here requires a kilobyte of
  * memory, which is currently unreclaimed.
  *
  * This should be a multiple of a page.
  */
-#define INIT_MAP_BEYOND_END    (128*1024)
+LOW_PAGES = 1<<(32-PAGE_SHIFT_asm)
 
+#if PTRS_PER_PMD > 1
+PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD
+#else
+PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD)
+#endif
+BOOTBITMAP_SIZE = LOW_PAGES / 8
+ALLOCATOR_SLOP = 4
+
+INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm
 
 /*
  * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
@@ -147,8 +162,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
 /*
  * Non-boot CPU entry point; entered from trampoline.S
  * We can't lgdt here, because lgdt itself uses a data segment, but
- * we know the trampoline has already loaded the boot_gdt_table GDT
- * for us.
+ * we know the trampoline has already loaded the boot_gdt for us.
  *
  * If cpu hotplug is not supported then this code can go in init section
  * which will be freed later
@@ -318,12 +332,12 @@ is386:    movl $2,%ecx            # set MP
        movl %eax,%cr0
 
        call check_x87
-       call setup_pda
        lgdt early_gdt_descr
        lidt idt_descr
        ljmp $(__KERNEL_CS),$1f
 1:     movl $(__KERNEL_DS),%eax        # reload all the segment registers
        movl %eax,%ss                   # after changing gdt.
+       movl %eax,%fs                   # gets reset once there's real percpu
 
        movl $(__USER_DS),%eax          # DS/ES contains default USER segment
        movl %eax,%ds
@@ -333,16 +347,17 @@ is386:    movl $2,%ecx            # set MP
        movl %eax,%gs
        lldt %ax
 
-       movl $(__KERNEL_PDA),%eax
-       mov  %eax,%fs
-
        cld                     # gcc2 wants the direction flag cleared at all times
        pushl $0                # fake return address for unwinder
 #ifdef CONFIG_SMP
        movb ready, %cl
        movb $1, ready
        cmpb $0,%cl             # the first CPU calls start_kernel
-       jne initialize_secondary # all other CPUs call initialize_secondary
+       je   1f
+       movl $(__KERNEL_PERCPU), %eax
+       movl %eax,%fs           # set this cpu's percpu
+       jmp initialize_secondary # all other CPUs call initialize_secondary
+1:
 #endif /* CONFIG_SMP */
        jmp start_kernel
 
@@ -365,23 +380,6 @@ check_x87:
        .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
        ret
 
-/*
- * Point the GDT at this CPU's PDA.  On boot this will be
- * cpu_gdt_table and boot_pda; for secondary CPUs, these will be
- * that CPU's GDT and PDA.
- */
-ENTRY(setup_pda)
-       /* get the PDA pointer */
-       movl start_pda, %eax
-
-       /* slot the PDA address into the GDT */
-       mov early_gdt_descr+2, %ecx
-       mov %ax, (__KERNEL_PDA+0+2)(%ecx)               /* base & 0x0000ffff */
-       shr $16, %eax
-       mov %al, (__KERNEL_PDA+4+0)(%ecx)               /* base & 0x00ff0000 */
-       mov %ah, (__KERNEL_PDA+4+3)(%ecx)               /* base & 0xff000000 */
-       ret
-
 /*
  *  setup_idt
  *
@@ -554,9 +552,6 @@ ENTRY(empty_zero_page)
  * This starts the data section.
  */
 .data
-ENTRY(start_pda)
-       .long boot_pda
-
 ENTRY(stack_start)
        .long init_thread_union+THREAD_SIZE
        .long __BOOT_DS
@@ -588,7 +583,7 @@ fault_msg:
        .word 0                         # 32 bit align gdt_desc.address
 boot_gdt_descr:
        .word __BOOT_DS+7
-       .long boot_gdt_table - __PAGE_OFFSET
+       .long boot_gdt - __PAGE_OFFSET
 
        .word 0                         # 32-bit align idt_desc.address
 idt_descr:
@@ -599,67 +594,14 @@ idt_descr:
        .word 0                         # 32 bit align gdt_desc.address
 ENTRY(early_gdt_descr)
        .word GDT_ENTRIES*8-1
-       .long cpu_gdt_table
+       .long per_cpu__gdt_page         /* Overwritten for secondary CPUs */
 
 /*
- * The boot_gdt_table must mirror the equivalent in setup.S and is
+ * The boot_gdt must mirror the equivalent in setup.S and is
  * used only for booting.
  */
        .align L1_CACHE_BYTES
-ENTRY(boot_gdt_table)
+ENTRY(boot_gdt)
        .fill GDT_ENTRY_BOOT_CS,8,0
        .quad 0x00cf9a000000ffff        /* kernel 4GB code at 0x00000000 */
        .quad 0x00cf92000000ffff        /* kernel 4GB data at 0x00000000 */
-
-/*
- * The Global Descriptor Table contains 28 quadwords, per-CPU.
- */
-       .align L1_CACHE_BYTES
-ENTRY(cpu_gdt_table)
-       .quad 0x0000000000000000        /* NULL descriptor */
-       .quad 0x0000000000000000        /* 0x0b reserved */
-       .quad 0x0000000000000000        /* 0x13 reserved */
-       .quad 0x0000000000000000        /* 0x1b reserved */
-       .quad 0x0000000000000000        /* 0x20 unused */
-       .quad 0x0000000000000000        /* 0x28 unused */
-       .quad 0x0000000000000000        /* 0x33 TLS entry 1 */
-       .quad 0x0000000000000000        /* 0x3b TLS entry 2 */
-       .quad 0x0000000000000000        /* 0x43 TLS entry 3 */
-       .quad 0x0000000000000000        /* 0x4b reserved */
-       .quad 0x0000000000000000        /* 0x53 reserved */
-       .quad 0x0000000000000000        /* 0x5b reserved */
-
-       .quad 0x00cf9a000000ffff        /* 0x60 kernel 4GB code at 0x00000000 */
-       .quad 0x00cf92000000ffff        /* 0x68 kernel 4GB data at 0x00000000 */
-       .quad 0x00cffa000000ffff        /* 0x73 user 4GB code at 0x00000000 */
-       .quad 0x00cff2000000ffff        /* 0x7b user 4GB data at 0x00000000 */
-
-       .quad 0x0000000000000000        /* 0x80 TSS descriptor */
-       .quad 0x0000000000000000        /* 0x88 LDT descriptor */
-
-       /*
-        * Segments used for calling PnP BIOS have byte granularity.
-        * They code segments and data segments have fixed 64k limits,
-        * the transfer segment sizes are set at run time.
-        */
-       .quad 0x00409a000000ffff        /* 0x90 32-bit code */
-       .quad 0x00009a000000ffff        /* 0x98 16-bit code */
-       .quad 0x000092000000ffff        /* 0xa0 16-bit data */
-       .quad 0x0000920000000000        /* 0xa8 16-bit data */
-       .quad 0x0000920000000000        /* 0xb0 16-bit data */
-
-       /*
-        * The APM segments have byte granularity and their bases
-        * are set at run time.  All have 64k limits.
-        */
-       .quad 0x00409a000000ffff        /* 0xb8 APM CS    code */
-       .quad 0x00009a000000ffff        /* 0xc0 APM CS 16 code (16 bit) */
-       .quad 0x004092000000ffff        /* 0xc8 APM DS    data */
-
-       .quad 0x00c0920000000000        /* 0xd0 - ESPFIX SS */
-       .quad 0x00cf92000000ffff        /* 0xd8 - PDA */
-       .quad 0x0000000000000000        /* 0xe0 - unused */
-       .quad 0x0000000000000000        /* 0xe8 - unused */
-       .quad 0x0000000000000000        /* 0xf0 - unused */
-       .quad 0x0000000000000000        /* 0xf8 - GDT entry 31: double-fault TSS */
-
index 4afe26e..e3d4b73 100644 (file)
@@ -28,5 +28,3 @@ EXPORT_SYMBOL(__read_lock_failed);
 #endif
 
 EXPORT_SYMBOL(csum_partial);
-
-EXPORT_SYMBOL(_proxy_pda);
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 b3ab8ff..1b623cd 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/msi.h>
 #include <linux/htirq.h>
 #include <linux/freezer.h>
+#include <linux/kthread.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -661,8 +662,6 @@ static int balanced_irq(void *unused)
        unsigned long prev_balance_time = jiffies;
        long time_remaining = balanced_irq_interval;
 
-       daemonize("kirqd");
-       
        /* push everything to CPU 0 to give us a starting point.  */
        for (i = 0 ; i < NR_IRQS ; i++) {
                irq_desc[i].pending_mask = cpumask_of_cpu(0);
@@ -722,10 +721,9 @@ static int __init balanced_irq_init(void)
        }
        
        printk(KERN_INFO "Starting balanced_irq\n");
-       if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0) 
+       if (!IS_ERR(kthread_run(balanced_irq, NULL, "kirqd")))
                return 0;
-       else 
-               printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
+       printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
 failed:
        for_each_possible_cpu(i) {
                kfree(irq_cpu_data[i].irq_delta);
@@ -1403,10 +1401,6 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
        enable_8259A_irq(0);
 }
 
-static inline void UNEXPECTED_IO_APIC(void)
-{
-}
-
 void __init print_IO_APIC(void)
 {
        int apic, i;
@@ -1446,34 +1440,12 @@ void __init print_IO_APIC(void)
        printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
        printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
        printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
-       if (reg_00.bits.ID >= get_physical_broadcast())
-               UNEXPECTED_IO_APIC();
-       if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
-               UNEXPECTED_IO_APIC();
 
        printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
        printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
-       if (    (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
-               (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
-               (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
-               (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
-               (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
-               (reg_01.bits.entries != 0x2E) &&
-               (reg_01.bits.entries != 0x3F)
-       )
-               UNEXPECTED_IO_APIC();
 
        printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
        printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
-       if (    (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
-               (reg_01.bits.version != 0x10) && /* oldest IO-APICs */
-               (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
-               (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
-               (reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
-       )
-               UNEXPECTED_IO_APIC();
-       if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
-               UNEXPECTED_IO_APIC();
 
        /*
         * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
@@ -1483,8 +1455,6 @@ void __init print_IO_APIC(void)
        if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
                printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
                printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
-               if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
-                       UNEXPECTED_IO_APIC();
        }
 
        /*
@@ -1496,8 +1466,6 @@ void __init print_IO_APIC(void)
            reg_03.raw != reg_01.raw) {
                printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
                printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
-               if (reg_03.bits.__reserved_1)
-                       UNEXPECTED_IO_APIC();
        }
 
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
@@ -2611,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 498e8bc..d1e42e0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/thread_info.h>
+#include <linux/syscalls.h>
 
 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
 static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
@@ -113,7 +114,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
         * Reset the owner so that a process switch will not set
         * tss->io_bitmap_base to IO_BITMAP_OFFSET.
         */
-       tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+       tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
        tss->io_bitmap_owner = NULL;
 
        put_cpu();
index 8db8d51..d2daf67 100644 (file)
@@ -24,6 +24,9 @@
 DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
 EXPORT_PER_CPU_SYMBOL(irq_stat);
 
+DEFINE_PER_CPU(struct pt_regs *, irq_regs);
+EXPORT_PER_CPU_SYMBOL(irq_regs);
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
index 4f5983c..0952ecc 100644 (file)
@@ -477,7 +477,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                }
                ++mpc_record;
        }
-       clustered_apic_check();
+       setup_apic_routing();
        if (!num_processors)
                printk(KERN_ERR "SMP mptable: no processors registered!\n");
        return num_processors;
index 84c3497..33cf2f3 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/sysdev.h>
 #include <linux/sysctl.h>
 #include <linux/percpu.h>
-#include <linux/dmi.h>
 #include <linux/kprobes.h>
 #include <linux/cpumask.h>
 #include <linux/kernel_stat.h>
 #include <asm/smp.h>
 #include <asm/nmi.h>
 #include <asm/kdebug.h>
-#include <asm/intel_arch_perfmon.h>
 
 #include "mach_traps.h"
 
 int unknown_nmi_panic;
 int nmi_watchdog_enabled;
 
-/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
- * evtsel_nmi_owner tracks the ownership of the event selection
- * - different performance counters/ event selection may be reserved for
- *   different subsystems this reservation system just tries to coordinate
- *   things a little
- */
-
-/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
- * offset from MSR_P4_BSU_ESCR0.  It will be the max for all platforms (for now)
- */
-#define NMI_MAX_COUNTER_BITS 66
-#define NMI_MAX_COUNTER_LONGS BITS_TO_LONGS(NMI_MAX_COUNTER_BITS)
-
-static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner[NMI_MAX_COUNTER_LONGS]);
-static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[NMI_MAX_COUNTER_LONGS]);
-
 static cpumask_t backtrace_mask = CPU_MASK_NONE;
+
 /* nmi_active:
  * >0: the lapic NMI watchdog is active, but can be disabled
  * <0: the lapic NMI watchdog has not been set up, and cannot
@@ -63,206 +46,11 @@ atomic_t nmi_active = ATOMIC_INIT(0);              /* oprofile uses this */
 unsigned int nmi_watchdog = NMI_DEFAULT;
 static unsigned int nmi_hz = HZ;
 
-struct nmi_watchdog_ctlblk {
-       int enabled;
-       u64 check_bit;
-       unsigned int cccr_msr;
-       unsigned int perfctr_msr;  /* the MSR to reset in NMI handler */
-       unsigned int evntsel_msr;  /* the MSR to select the events to handle */
-};
-static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
+static DEFINE_PER_CPU(short, wd_enabled);
 
 /* local prototypes */
 static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
 
-extern void show_registers(struct pt_regs *regs);
-extern int unknown_nmi_panic;
-
-/* converts an msr to an appropriate reservation bit */
-static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
-{
-       /* returns the bit offset of the performance counter register */
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               return (msr - MSR_K7_PERFCTR0);
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-                       return (msr - MSR_ARCH_PERFMON_PERFCTR0);
-
-               switch (boot_cpu_data.x86) {
-               case 6:
-                       return (msr - MSR_P6_PERFCTR0);
-               case 15:
-                       return (msr - MSR_P4_BPU_PERFCTR0);
-               }
-       }
-       return 0;
-}
-
-/* converts an msr to an appropriate reservation bit */
-static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
-{
-       /* returns the bit offset of the event selection register */
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               return (msr - MSR_K7_EVNTSEL0);
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-                       return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
-
-               switch (boot_cpu_data.x86) {
-               case 6:
-                       return (msr - MSR_P6_EVNTSEL0);
-               case 15:
-                       return (msr - MSR_P4_BSU_ESCR0);
-               }
-       }
-       return 0;
-}
-
-/* checks for a bit availability (hack for oprofile) */
-int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
-{
-       int cpu;
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-       for_each_possible_cpu (cpu) {
-               if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)[0]))
-                       return 0;
-       }
-       return 1;
-}
-
-/* checks the an msr for availability */
-int avail_to_resrv_perfctr_nmi(unsigned int msr)
-{
-       unsigned int counter;
-       int cpu;
-
-       counter = nmi_perfctr_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       for_each_possible_cpu (cpu) {
-               if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)[0]))
-                       return 0;
-       }
-       return 1;
-}
-
-static int __reserve_perfctr_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_perfctr_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       if (!test_and_set_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)[0]))
-               return 1;
-       return 0;
-}
-
-static void __release_perfctr_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_perfctr_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       clear_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)[0]);
-}
-
-int reserve_perfctr_nmi(unsigned int msr)
-{
-       int cpu, i;
-       for_each_possible_cpu (cpu) {
-               if (!__reserve_perfctr_nmi(cpu, msr)) {
-                       for_each_possible_cpu (i) {
-                               if (i >= cpu)
-                                       break;
-                               __release_perfctr_nmi(i, msr);
-                       }
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-void release_perfctr_nmi(unsigned int msr)
-{
-       int cpu;
-       for_each_possible_cpu (cpu) {
-               __release_perfctr_nmi(cpu, msr);
-       }
-}
-
-int __reserve_evntsel_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_evntsel_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       if (!test_and_set_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]))
-               return 1;
-       return 0;
-}
-
-static void __release_evntsel_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_evntsel_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       clear_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]);
-}
-
-int reserve_evntsel_nmi(unsigned int msr)
-{
-       int cpu, i;
-       for_each_possible_cpu (cpu) {
-               if (!__reserve_evntsel_nmi(cpu, msr)) {
-                       for_each_possible_cpu (i) {
-                               if (i >= cpu)
-                                       break;
-                               __release_evntsel_nmi(i, msr);
-                       }
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-void release_evntsel_nmi(unsigned int msr)
-{
-       int cpu;
-       for_each_possible_cpu (cpu) {
-               __release_evntsel_nmi(cpu, msr);
-       }
-}
-
-static __cpuinit inline int nmi_known_cpu(void)
-{
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6)
-                       || (boot_cpu_data.x86 == 16));
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-                       return 1;
-               else
-                       return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6));
-       }
-       return 0;
-}
-
 static int endflag __initdata = 0;
 
 #ifdef CONFIG_SMP
@@ -284,28 +72,6 @@ static __init void nmi_cpu_busy(void *data)
 }
 #endif
 
-static unsigned int adjust_for_32bit_ctr(unsigned int hz)
-{
-       u64 counter_val;
-       unsigned int retval = hz;
-
-       /*
-        * On Intel CPUs with P6/ARCH_PERFMON only 32 bits in the counter
-        * are writable, with higher bits sign extending from bit 31.
-        * So, we can only program the counter with 31 bit values and
-        * 32nd bit should be 1, for 33.. to be 1.
-        * Find the appropriate nmi_hz
-        */
-       counter_val = (u64)cpu_khz * 1000;
-       do_div(counter_val, retval);
-       if (counter_val > 0x7fffffffULL) {
-               u64 count = (u64)cpu_khz * 1000;
-               do_div(count, 0x7fffffffUL);
-               retval = count + 1;
-       }
-       return retval;
-}
-
 static int __init check_nmi_watchdog(void)
 {
        unsigned int *prev_nmi_count;
@@ -338,14 +104,14 @@ static int __init check_nmi_watchdog(void)
                if (!cpu_isset(cpu, cpu_callin_map))
                        continue;
 #endif
-               if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
+               if (!per_cpu(wd_enabled, cpu))
                        continue;
                if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) {
                        printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
                                cpu,
                                prev_nmi_count[cpu],
                                nmi_count(cpu));
-                       per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
+                       per_cpu(wd_enabled, cpu) = 0;
                        atomic_dec(&nmi_active);
                }
        }
@@ -359,16 +125,8 @@ static int __init check_nmi_watchdog(void)
 
        /* now that we know it works we can reduce NMI frequency to
           something more reasonable; makes a difference in some configs */
-       if (nmi_watchdog == NMI_LOCAL_APIC) {
-               struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-               nmi_hz = 1;
-
-               if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
-                   wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-                       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-               }
-       }
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               nmi_hz = lapic_adjust_nmi_hz(1);
 
        kfree(prev_nmi_count);
        return 0;
@@ -391,85 +149,8 @@ static int __init setup_nmi_watchdog(char *str)
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-static void disable_lapic_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-
-       if (atomic_read(&nmi_active) <= 0)
-               return;
-
-       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
-
-       BUG_ON(atomic_read(&nmi_active) != 0);
-}
-
-static void enable_lapic_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-
-       /* are we already enabled */
-       if (atomic_read(&nmi_active) != 0)
-               return;
-
-       /* are we lapic aware */
-       if (nmi_known_cpu() <= 0)
-               return;
 
-       on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
-       touch_nmi_watchdog();
-}
-
-void disable_timer_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_IO_APIC);
-
-       if (atomic_read(&nmi_active) <= 0)
-               return;
-
-       disable_irq(0);
-       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
-
-       BUG_ON(atomic_read(&nmi_active) != 0);
-}
-
-void enable_timer_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_IO_APIC);
-
-       if (atomic_read(&nmi_active) == 0) {
-               touch_nmi_watchdog();
-               on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
-               enable_irq(0);
-       }
-}
-
-static void __acpi_nmi_disable(void *__unused)
-{
-       apic_write_around(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
-}
-
-/*
- * Disable timer based NMIs on all CPUs:
- */
-void acpi_nmi_disable(void)
-{
-       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
-               on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
-}
-
-static void __acpi_nmi_enable(void *__unused)
-{
-       apic_write_around(APIC_LVT0, APIC_DM_NMI);
-}
-
-/*
- * Enable timer based NMIs on all CPUs:
- */
-void acpi_nmi_enable(void)
-{
-       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
-               on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
-}
+/* Suspend/resume support */
 
 #ifdef CONFIG_PM
 
@@ -516,7 +197,7 @@ static int __init init_lapic_nmi_sysfs(void)
        if (nmi_watchdog != NMI_LOCAL_APIC)
                return 0;
 
-       if ( atomic_read(&nmi_active) < 0 )
+       if (atomic_read(&nmi_active) < 0)
                return 0;
 
        error = sysdev_class_register(&nmi_sysclass);
@@ -529,433 +210,69 @@ late_initcall(init_lapic_nmi_sysfs);
 
 #endif /* CONFIG_PM */
 
-/*
- * Activate the NMI watchdog via the local APIC.
- * Original code written by Keith Owens.
- */
-
-static void write_watchdog_counter(unsigned int perfctr_msr, const char *descr)
-{
-       u64 count = (u64)cpu_khz * 1000;
-
-       do_div(count, nmi_hz);
-       if(descr)
-               Dprintk("setting %s to -0x%08Lx\n", descr, count);
-       wrmsrl(perfctr_msr, 0 - count);
-}
-
-static void write_watchdog_counter32(unsigned int perfctr_msr,
-               const char *descr)
-{
-       u64 count = (u64)cpu_khz * 1000;
-
-       do_div(count, nmi_hz);
-       if(descr)
-               Dprintk("setting %s to -0x%08Lx\n", descr, count);
-       wrmsr(perfctr_msr, (u32)(-count), 0);
-}
-
-/* Note that these events don't tick when the CPU idles. This means
-   the frequency varies with CPU load. */
-
-#define K7_EVNTSEL_ENABLE      (1 << 22)
-#define K7_EVNTSEL_INT         (1 << 20)
-#define K7_EVNTSEL_OS          (1 << 17)
-#define K7_EVNTSEL_USR         (1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
-#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-
-static int setup_k7_watchdog(void)
-{
-       unsigned int perfctr_msr, evntsel_msr;
-       unsigned int evntsel;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       perfctr_msr = MSR_K7_PERFCTR0;
-       evntsel_msr = MSR_K7_EVNTSEL0;
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       wrmsrl(perfctr_msr, 0UL);
-
-       evntsel = K7_EVNTSEL_INT
-               | K7_EVNTSEL_OS
-               | K7_EVNTSEL_USR
-               | K7_NMI_EVENT;
-
-       /* setup the timer */
-       wrmsr(evntsel_msr, evntsel, 0);
-       write_watchdog_counter(perfctr_msr, "K7_PERFCTR0");
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       evntsel |= K7_EVNTSEL_ENABLE;
-       wrmsr(evntsel_msr, evntsel, 0);
-
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = 0;  //unused
-       wd->check_bit = 1ULL<<63;
-       return 1;
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
-}
-
-static void stop_k7_watchdog(void)
-{
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       wrmsr(wd->evntsel_msr, 0, 0);
-
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
-}
-
-#define P6_EVNTSEL0_ENABLE     (1 << 22)
-#define P6_EVNTSEL_INT         (1 << 20)
-#define P6_EVNTSEL_OS          (1 << 17)
-#define P6_EVNTSEL_USR         (1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
-#define P6_NMI_EVENT           P6_EVENT_CPU_CLOCKS_NOT_HALTED
-
-static int setup_p6_watchdog(void)
-{
-       unsigned int perfctr_msr, evntsel_msr;
-       unsigned int evntsel;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       perfctr_msr = MSR_P6_PERFCTR0;
-       evntsel_msr = MSR_P6_EVNTSEL0;
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       wrmsrl(perfctr_msr, 0UL);
-
-       evntsel = P6_EVNTSEL_INT
-               | P6_EVNTSEL_OS
-               | P6_EVNTSEL_USR
-               | P6_NMI_EVENT;
-
-       /* setup the timer */
-       wrmsr(evntsel_msr, evntsel, 0);
-       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-       write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0");
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       evntsel |= P6_EVNTSEL0_ENABLE;
-       wrmsr(evntsel_msr, evntsel, 0);
-
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = 0;  //unused
-       wd->check_bit = 1ULL<<39;
-       return 1;
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
-}
-
-static void stop_p6_watchdog(void)
-{
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       wrmsr(wd->evntsel_msr, 0, 0);
-
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
-}
-
-/* Note that these events don't tick when the CPU idles. This means
-   the frequency varies with CPU load. */
-
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
-#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
-#define P4_ESCR_OS             (1<<3)
-#define P4_ESCR_USR            (1<<2)
-#define P4_CCCR_OVF_PMI0       (1<<26)
-#define P4_CCCR_OVF_PMI1       (1<<27)
-#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
-#define P4_CCCR_COMPLEMENT     (1<<19)
-#define P4_CCCR_COMPARE                (1<<18)
-#define P4_CCCR_REQUIRED       (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE         (1<<12)
-#define P4_CCCR_OVF            (1<<31)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
-   CRU_ESCR0 (with any non-null event selector) through a complemented
-   max threshold. [IA32-Vol3, Section 14.9.9] */
-
-static int setup_p4_watchdog(void)
+static void __acpi_nmi_enable(void *__unused)
 {
-       unsigned int perfctr_msr, evntsel_msr, cccr_msr;
-       unsigned int evntsel, cccr_val;
-       unsigned int misc_enable, dummy;
-       unsigned int ht_num;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
-       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
-               return 0;
-
-#ifdef CONFIG_SMP
-       /* detect which hyperthread we are on */
-       if (smp_num_siblings == 2) {
-               unsigned int ebx, apicid;
-
-               ebx = cpuid_ebx(1);
-               apicid = (ebx >> 24) & 0xff;
-               ht_num = apicid & 1;
-       } else
-#endif
-               ht_num = 0;
-
-       /* performance counters are shared resources
-        * assign each hyperthread its own set
-        * (re-use the ESCR0 register, seems safe
-        * and keeps the cccr_val the same)
-        */
-       if (!ht_num) {
-               /* logical cpu 0 */
-               perfctr_msr = MSR_P4_IQ_PERFCTR0;
-               evntsel_msr = MSR_P4_CRU_ESCR0;
-               cccr_msr = MSR_P4_IQ_CCCR0;
-               cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
-       } else {
-               /* logical cpu 1 */
-               perfctr_msr = MSR_P4_IQ_PERFCTR1;
-               evntsel_msr = MSR_P4_CRU_ESCR0;
-               cccr_msr = MSR_P4_IQ_CCCR1;
-               cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
-       }
-
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       evntsel = P4_ESCR_EVENT_SELECT(0x3F)
-               | P4_ESCR_OS
-               | P4_ESCR_USR;
-
-       cccr_val |= P4_CCCR_THRESHOLD(15)
-                | P4_CCCR_COMPLEMENT
-                | P4_CCCR_COMPARE
-                | P4_CCCR_REQUIRED;
-
-       wrmsr(evntsel_msr, evntsel, 0);
-       wrmsr(cccr_msr, cccr_val, 0);
-       write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0");
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       cccr_val |= P4_CCCR_ENABLE;
-       wrmsr(cccr_msr, cccr_val, 0);
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = cccr_msr;
-       wd->check_bit = 1ULL<<39;
-       return 1;
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
+       apic_write_around(APIC_LVT0, APIC_DM_NMI);
 }
 
-static void stop_p4_watchdog(void)
+/*
+ * Enable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_enable(void)
 {
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       wrmsr(wd->cccr_msr, 0, 0);
-       wrmsr(wd->evntsel_msr, 0, 0);
-
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
+       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+               on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
 }
 
-#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
-
-static int setup_intel_arch_watchdog(void)
+static void __acpi_nmi_disable(void *__unused)
 {
-       unsigned int ebx;
-       union cpuid10_eax eax;
-       unsigned int unused;
-       unsigned int perfctr_msr, evntsel_msr;
-       unsigned int evntsel;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebx indicates event present.
-        */
-       cpuid(10, &(eax.full), &ebx, &unused, &unused);
-       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
-           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               goto fail;
-
-       perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
-       evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
-
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       wrmsrl(perfctr_msr, 0UL);
-
-       evntsel = ARCH_PERFMON_EVENTSEL_INT
-               | ARCH_PERFMON_EVENTSEL_OS
-               | ARCH_PERFMON_EVENTSEL_USR
-               | ARCH_PERFMON_NMI_EVENT_SEL
-               | ARCH_PERFMON_NMI_EVENT_UMASK;
-
-       /* setup the timer */
-       wrmsr(evntsel_msr, evntsel, 0);
-       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-       write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0");
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
-       wrmsr(evntsel_msr, evntsel, 0);
-
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = 0;  //unused
-       wd->check_bit = 1ULL << (eax.split.bit_width - 1);
-       return 1;
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
+       apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
 }
 
-static void stop_intel_arch_watchdog(void)
+/*
+ * Disable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_disable(void)
 {
-       unsigned int ebx;
-       union cpuid10_eax eax;
-       unsigned int unused;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebx indicates event present.
-        */
-       cpuid(10, &(eax.full), &ebx, &unused, &unused);
-       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
-           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               return;
-
-       wrmsr(wd->evntsel_msr, 0, 0);
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
+       if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+               on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
 }
 
 void setup_apic_nmi_watchdog (void *unused)
 {
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       /* only support LOCAL and IO APICs for now */
-       if ((nmi_watchdog != NMI_LOCAL_APIC) &&
-           (nmi_watchdog != NMI_IO_APIC))
-               return;
-
-       if (wd->enabled == 1)
-               return;
+       if (__get_cpu_var(wd_enabled))
+               return;
 
        /* cheap hack to support suspend/resume */
        /* if cpu0 is not active neither should the other cpus */
        if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0))
                return;
 
-       if (nmi_watchdog == NMI_LOCAL_APIC) {
-               switch (boot_cpu_data.x86_vendor) {
-               case X86_VENDOR_AMD:
-                       if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
-                               boot_cpu_data.x86 != 16)
-                               return;
-                       if (!setup_k7_watchdog())
-                               return;
-                       break;
-               case X86_VENDOR_INTEL:
-                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                               if (!setup_intel_arch_watchdog())
-                                       return;
-                               break;
-                       }
-                       switch (boot_cpu_data.x86) {
-                       case 6:
-                               if (boot_cpu_data.x86_model > 0xd)
-                                       return;
-
-                               if (!setup_p6_watchdog())
-                                       return;
-                               break;
-                       case 15:
-                               if (boot_cpu_data.x86_model > 0x4)
-                                       return;
-
-                               if (!setup_p4_watchdog())
-                                       return;
-                               break;
-                       default:
-                               return;
-                       }
-                       break;
-               default:
+       switch (nmi_watchdog) {
+       case NMI_LOCAL_APIC:
+               __get_cpu_var(wd_enabled) = 1; /* enable it before to avoid race with handler */
+               if (lapic_watchdog_init(nmi_hz) < 0) {
+                       __get_cpu_var(wd_enabled) = 0;
                        return;
                }
+               /* FALL THROUGH */
+       case NMI_IO_APIC:
+               __get_cpu_var(wd_enabled) = 1;
+               atomic_inc(&nmi_active);
        }
-       wd->enabled = 1;
-       atomic_inc(&nmi_active);
 }
 
 void stop_apic_nmi_watchdog(void *unused)
 {
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
        /* only support LOCAL and IO APICs for now */
        if ((nmi_watchdog != NMI_LOCAL_APIC) &&
            (nmi_watchdog != NMI_IO_APIC))
                return;
-
-       if (wd->enabled == 0)
+       if (__get_cpu_var(wd_enabled) == 0)
                return;
-
-       if (nmi_watchdog == NMI_LOCAL_APIC) {
-               switch (boot_cpu_data.x86_vendor) {
-               case X86_VENDOR_AMD:
-                       stop_k7_watchdog();
-                       break;
-               case X86_VENDOR_INTEL:
-                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                               stop_intel_arch_watchdog();
-                               break;
-                       }
-                       switch (boot_cpu_data.x86) {
-                       case 6:
-                               if (boot_cpu_data.x86_model > 0xd)
-                                       break;
-                               stop_p6_watchdog();
-                               break;
-                       case 15:
-                               if (boot_cpu_data.x86_model > 0x4)
-                                       break;
-                               stop_p4_watchdog();
-                               break;
-                       }
-                       break;
-               default:
-                       return;
-               }
-       }
-       wd->enabled = 0;
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               lapic_watchdog_stop();
+       __get_cpu_var(wd_enabled) = 0;
        atomic_dec(&nmi_active);
 }
 
@@ -1011,8 +328,6 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
        unsigned int sum;
        int touched = 0;
        int cpu = smp_processor_id();
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-       u64 dummy;
        int rc=0;
 
        /* check for other users first */
@@ -1055,53 +370,20 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                alert_counter[cpu] = 0;
        }
        /* see if the nmi watchdog went off */
-       if (wd->enabled) {
-               if (nmi_watchdog == NMI_LOCAL_APIC) {
-                       rdmsrl(wd->perfctr_msr, dummy);
-                       if (dummy & wd->check_bit){
-                               /* this wasn't a watchdog timer interrupt */
-                               goto done;
-                       }
-
-                       /* only Intel P4 uses the cccr msr */
-                       if (wd->cccr_msr != 0) {
-                               /*
-                                * P4 quirks:
-                                * - An overflown perfctr will assert its interrupt
-                                *   until the OVF flag in its CCCR is cleared.
-                                * - LVTPC is masked on interrupt and must be
-                                *   unmasked by the LVTPC handler.
-                                */
-                               rdmsrl(wd->cccr_msr, dummy);
-                               dummy &= ~P4_CCCR_OVF;
-                               wrmsrl(wd->cccr_msr, dummy);
-                               apic_write(APIC_LVTPC, APIC_DM_NMI);
-                               /* start the cycle over again */
-                               write_watchdog_counter(wd->perfctr_msr, NULL);
-                       }
-                       else if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
-                                wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-                               /* P6 based Pentium M need to re-unmask
-                                * the apic vector but it doesn't hurt
-                                * other P6 variant.
-                                * ArchPerfom/Core Duo also needs this */
-                               apic_write(APIC_LVTPC, APIC_DM_NMI);
-                               /* P6/ARCH_PERFMON has 32 bit counter write */
-                               write_watchdog_counter32(wd->perfctr_msr, NULL);
-                       } else {
-                               /* start the cycle over again */
-                               write_watchdog_counter(wd->perfctr_msr, NULL);
-                       }
-                       rc = 1;
-               } else if (nmi_watchdog == NMI_IO_APIC) {
-                       /* don't know how to accurately check for this.
-                        * just assume it was a watchdog timer interrupt
-                        * This matches the old behaviour.
-                        */
-                       rc = 1;
-               }
+       if (!__get_cpu_var(wd_enabled))
+               return rc;
+       switch (nmi_watchdog) {
+       case NMI_LOCAL_APIC:
+               rc |= lapic_wd_event(nmi_hz);
+               break;
+       case NMI_IO_APIC:
+               /* don't know how to accurately check for this.
+                * just assume it was a watchdog timer interrupt
+                * This matches the old behaviour.
+                */
+               rc = 1;
+               break;
        }
-done:
        return rc;
 }
 
@@ -1146,7 +428,7 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
        }
 
        if (nmi_watchdog == NMI_DEFAULT) {
-               if (nmi_known_cpu() > 0)
+               if (lapic_watchdog_ok())
                        nmi_watchdog = NMI_LOCAL_APIC;
                else
                        nmi_watchdog = NMI_IO_APIC;
@@ -1182,11 +464,3 @@ void __trigger_all_cpu_backtrace(void)
 
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
-EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
-EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
-EXPORT_SYMBOL(reserve_perfctr_nmi);
-EXPORT_SYMBOL(release_perfctr_nmi);
-EXPORT_SYMBOL(reserve_evntsel_nmi);
-EXPORT_SYMBOL(release_evntsel_nmi);
-EXPORT_SYMBOL(disable_timer_nmi_watchdog);
-EXPORT_SYMBOL(enable_timer_nmi_watchdog);
index 2ec331e..5c10f37 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/efi.h>
 #include <linux/bcd.h>
 #include <linux/start_kernel.h>
+#include <linux/highmem.h>
 
 #include <asm/bug.h>
 #include <asm/paravirt.h>
@@ -35,7 +36,7 @@
 #include <asm/timer.h>
 
 /* nop stub */
-static void native_nop(void)
+void _paravirt_nop(void)
 {
 }
 
@@ -54,331 +55,148 @@ char *memory_setup(void)
 #define DEF_NATIVE(name, code)                                 \
        extern const char start_##name[], end_##name[];         \
        asm("start_" #name ": " code "; end_" #name ":")
-DEF_NATIVE(cli, "cli");
-DEF_NATIVE(sti, "sti");
-DEF_NATIVE(popf, "push %eax; popf");
-DEF_NATIVE(pushf, "pushf; pop %eax");
-DEF_NATIVE(pushf_cli, "pushf; pop %eax; cli");
+
+DEF_NATIVE(irq_disable, "cli");
+DEF_NATIVE(irq_enable, "sti");
+DEF_NATIVE(restore_fl, "push %eax; popf");
+DEF_NATIVE(save_fl, "pushf; pop %eax");
 DEF_NATIVE(iret, "iret");
-DEF_NATIVE(sti_sysexit, "sti; sysexit");
+DEF_NATIVE(irq_enable_sysexit, "sti; sysexit");
+DEF_NATIVE(read_cr2, "mov %cr2, %eax");
+DEF_NATIVE(write_cr3, "mov %eax, %cr3");
+DEF_NATIVE(read_cr3, "mov %cr3, %eax");
+DEF_NATIVE(clts, "clts");
+DEF_NATIVE(read_tsc, "rdtsc");
 
-static const struct native_insns
-{
-       const char *start, *end;
-} native_insns[] = {
-       [PARAVIRT_IRQ_DISABLE] = { start_cli, end_cli },
-       [PARAVIRT_IRQ_ENABLE] = { start_sti, end_sti },
-       [PARAVIRT_RESTORE_FLAGS] = { start_popf, end_popf },
-       [PARAVIRT_SAVE_FLAGS] = { start_pushf, end_pushf },
-       [PARAVIRT_SAVE_FLAGS_IRQ_DISABLE] = { start_pushf_cli, end_pushf_cli },
-       [PARAVIRT_INTERRUPT_RETURN] = { start_iret, end_iret },
-       [PARAVIRT_STI_SYSEXIT] = { start_sti_sysexit, end_sti_sysexit },
-};
+DEF_NATIVE(ud2a, "ud2a");
 
 static unsigned native_patch(u8 type, u16 clobbers, void *insns, unsigned len)
 {
-       unsigned int insn_len;
-
-       /* Don't touch it if we don't have a replacement */
-       if (type >= ARRAY_SIZE(native_insns) || !native_insns[type].start)
-               return len;
-
-       insn_len = native_insns[type].end - native_insns[type].start;
-
-       /* Similarly if we can't fit replacement. */
-       if (len < insn_len)
-               return len;
+       const unsigned char *start, *end;
+       unsigned ret;
+
+       switch(type) {
+#define SITE(x)        case PARAVIRT_PATCH(x): start = start_##x; end = end_##x; goto patch_site
+               SITE(irq_disable);
+               SITE(irq_enable);
+               SITE(restore_fl);
+               SITE(save_fl);
+               SITE(iret);
+               SITE(irq_enable_sysexit);
+               SITE(read_cr2);
+               SITE(read_cr3);
+               SITE(write_cr3);
+               SITE(clts);
+               SITE(read_tsc);
+#undef SITE
+
+       patch_site:
+               ret = paravirt_patch_insns(insns, len, start, end);
+               break;
 
-       memcpy(insns, native_insns[type].start, insn_len);
-       return insn_len;
-}
+       case PARAVIRT_PATCH(make_pgd):
+       case PARAVIRT_PATCH(make_pte):
+       case PARAVIRT_PATCH(pgd_val):
+       case PARAVIRT_PATCH(pte_val):
+#ifdef CONFIG_X86_PAE
+       case PARAVIRT_PATCH(make_pmd):
+       case PARAVIRT_PATCH(pmd_val):
+#endif
+               /* These functions end up returning exactly what
+                  they're passed, in the same registers. */
+               ret = paravirt_patch_nop();
+               break;
 
-static unsigned long native_get_debugreg(int regno)
-{
-       unsigned long val = 0;  /* Damn you, gcc! */
-
-       switch (regno) {
-       case 0:
-               asm("movl %%db0, %0" :"=r" (val)); break;
-       case 1:
-               asm("movl %%db1, %0" :"=r" (val)); break;
-       case 2:
-               asm("movl %%db2, %0" :"=r" (val)); break;
-       case 3:
-               asm("movl %%db3, %0" :"=r" (val)); break;
-       case 6:
-               asm("movl %%db6, %0" :"=r" (val)); break;
-       case 7:
-               asm("movl %%db7, %0" :"=r" (val)); break;
        default:
-               BUG();
-       }
-       return val;
-}
-
-static void native_set_debugreg(int regno, unsigned long value)
-{
-       switch (regno) {
-       case 0:
-               asm("movl %0,%%db0"     : /* no output */ :"r" (value));
-               break;
-       case 1:
-               asm("movl %0,%%db1"     : /* no output */ :"r" (value));
-               break;
-       case 2:
-               asm("movl %0,%%db2"     : /* no output */ :"r" (value));
+               ret = paravirt_patch_default(type, clobbers, insns, len);
                break;
-       case 3:
-               asm("movl %0,%%db3"     : /* no output */ :"r" (value));
-               break;
-       case 6:
-               asm("movl %0,%%db6"     : /* no output */ :"r" (value));
-               break;
-       case 7:
-               asm("movl %0,%%db7"     : /* no output */ :"r" (value));
-               break;
-       default:
-               BUG();
        }
-}
-
-void init_IRQ(void)
-{
-       paravirt_ops.init_IRQ();
-}
-
-static void native_clts(void)
-{
-       asm volatile ("clts");
-}
-
-static unsigned long native_read_cr0(void)
-{
-       unsigned long val;
-       asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
-       return val;
-}
-
-static void native_write_cr0(unsigned long val)
-{
-       asm volatile("movl %0,%%cr0": :"r" (val));
-}
-
-static unsigned long native_read_cr2(void)
-{
-       unsigned long val;
-       asm volatile("movl %%cr2,%0\n\t" :"=r" (val));
-       return val;
-}
-
-static void native_write_cr2(unsigned long val)
-{
-       asm volatile("movl %0,%%cr2": :"r" (val));
-}
-
-static unsigned long native_read_cr3(void)
-{
-       unsigned long val;
-       asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
-       return val;
-}
-
-static void native_write_cr3(unsigned long val)
-{
-       asm volatile("movl %0,%%cr3": :"r" (val));
-}
-
-static unsigned long native_read_cr4(void)
-{
-       unsigned long val;
-       asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
-       return val;
-}
-
-static unsigned long native_read_cr4_safe(void)
-{
-       unsigned long val;
-       /* This could fault if %cr4 does not exist */
-       asm("1: movl %%cr4, %0          \n"
-               "2:                             \n"
-               ".section __ex_table,\"a\"      \n"
-               ".long 1b,2b                    \n"
-               ".previous                      \n"
-               : "=r" (val): "0" (0));
-       return val;
-}
-
-static void native_write_cr4(unsigned long val)
-{
-       asm volatile("movl %0,%%cr4": :"r" (val));
-}
-
-static unsigned long native_save_fl(void)
-{
-       unsigned long f;
-       asm volatile("pushfl ; popl %0":"=g" (f): /* no input */);
-       return f;
-}
-
-static void native_restore_fl(unsigned long f)
-{
-       asm volatile("pushl %0 ; popfl": /* no output */
-                            :"g" (f)
-                            :"memory", "cc");
-}
-
-static void native_irq_disable(void)
-{
-       asm volatile("cli": : :"memory");
-}
-
-static void native_irq_enable(void)
-{
-       asm volatile("sti": : :"memory");
-}
-
-static void native_safe_halt(void)
-{
-       asm volatile("sti; hlt": : :"memory");
-}
 
-static void native_halt(void)
-{
-       asm volatile("hlt": : :"memory");
+       return ret;
 }
 
-static void native_wbinvd(void)
+unsigned paravirt_patch_nop(void)
 {
-       asm volatile("wbinvd": : :"memory");
+       return 0;
 }
 
-static unsigned long long native_read_msr(unsigned int msr, int *err)
+unsigned paravirt_patch_ignore(unsigned len)
 {
-       unsigned long long val;
-
-       asm volatile("2: rdmsr ; xorl %0,%0\n"
-                    "1:\n\t"
-                    ".section .fixup,\"ax\"\n\t"
-                    "3:  movl %3,%0 ; jmp 1b\n\t"
-                    ".previous\n\t"
-                    ".section __ex_table,\"a\"\n"
-                    "   .align 4\n\t"
-                    "   .long  2b,3b\n\t"
-                    ".previous"
-                    : "=r" (*err), "=A" (val)
-                    : "c" (msr), "i" (-EFAULT));
-
-       return val;
+       return len;
 }
 
-static int native_write_msr(unsigned int msr, unsigned long long val)
+unsigned paravirt_patch_call(void *target, u16 tgt_clobbers,
+                            void *site, u16 site_clobbers,
+                            unsigned len)
 {
-       int err;
-       asm volatile("2: wrmsr ; xorl %0,%0\n"
-                    "1:\n\t"
-                    ".section .fixup,\"ax\"\n\t"
-                    "3:  movl %4,%0 ; jmp 1b\n\t"
-                    ".previous\n\t"
-                    ".section __ex_table,\"a\"\n"
-                    "   .align 4\n\t"
-                    "   .long  2b,3b\n\t"
-                    ".previous"
-                    : "=a" (err)
-                    : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)),
-                      "i" (-EFAULT));
-       return err;
-}
+       unsigned char *call = site;
+       unsigned long delta = (unsigned long)target - (unsigned long)(call+5);
 
-static unsigned long long native_read_tsc(void)
-{
-       unsigned long long val;
-       asm volatile("rdtsc" : "=A" (val));
-       return val;
-}
+       if (tgt_clobbers & ~site_clobbers)
+               return len;     /* target would clobber too much for this site */
+       if (len < 5)
+               return len;     /* call too long for patch site */
 
-static unsigned long long native_read_pmc(void)
-{
-       unsigned long long val;
-       asm volatile("rdpmc" : "=A" (val));
-       return val;
-}
+       *call++ = 0xe8;         /* call */
+       *(unsigned long *)call = delta;
 
-static void native_load_tr_desc(void)
-{
-       asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+       return 5;
 }
 
-static void native_load_gdt(const struct Xgt_desc_struct *dtr)
+unsigned paravirt_patch_jmp(void *target, void *site, unsigned len)
 {
-       asm volatile("lgdt %0"::"m" (*dtr));
-}
+       unsigned char *jmp = site;
+       unsigned long delta = (unsigned long)target - (unsigned long)(jmp+5);
 
-static void native_load_idt(const struct Xgt_desc_struct *dtr)
-{
-       asm volatile("lidt %0"::"m" (*dtr));
-}
+       if (len < 5)
+               return len;     /* call too long for patch site */
 
-static void native_store_gdt(struct Xgt_desc_struct *dtr)
-{
-       asm ("sgdt %0":"=m" (*dtr));
-}
+       *jmp++ = 0xe9;          /* jmp */
+       *(unsigned long *)jmp = delta;
 
-static void native_store_idt(struct Xgt_desc_struct *dtr)
-{
-       asm ("sidt %0":"=m" (*dtr));
+       return 5;
 }
 
-static unsigned long native_store_tr(void)
+unsigned paravirt_patch_default(u8 type, u16 clobbers, void *site, unsigned len)
 {
-       unsigned long tr;
-       asm ("str %0":"=r" (tr));
-       return tr;
-}
+       void *opfunc = *((void **)&paravirt_ops + type);
+       unsigned ret;
 
-static void native_load_tls(struct thread_struct *t, unsigned int cpu)
-{
-#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
-       C(0); C(1); C(2);
-#undef C
-}
+       if (opfunc == NULL)
+               /* If there's no function, patch it with a ud2a (BUG) */
+               ret = paravirt_patch_insns(site, len, start_ud2a, end_ud2a);
+       else if (opfunc == paravirt_nop)
+               /* If the operation is a nop, then nop the callsite */
+               ret = paravirt_patch_nop();
+       else if (type == PARAVIRT_PATCH(iret) ||
+                type == PARAVIRT_PATCH(irq_enable_sysexit))
+               /* If operation requires a jmp, then jmp */
+               ret = paravirt_patch_jmp(opfunc, site, len);
+       else
+               /* Otherwise call the function; assume target could
+                  clobber any caller-save reg */
+               ret = paravirt_patch_call(opfunc, CLBR_ANY,
+                                         site, clobbers, len);
 
-static inline void native_write_dt_entry(void *dt, int entry, u32 entry_low, u32 entry_high)
-{
-       u32 *lp = (u32 *)((char *)dt + entry*8);
-       lp[0] = entry_low;
-       lp[1] = entry_high;
+       return ret;
 }
 
-static void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high)
+unsigned paravirt_patch_insns(void *site, unsigned len,
+                             const char *start, const char *end)
 {
-       native_write_dt_entry(dt, entrynum, low, high);
-}
+       unsigned insn_len = end - start;
 
-static void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high)
-{
-       native_write_dt_entry(dt, entrynum, low, high);
-}
-
-static void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high)
-{
-       native_write_dt_entry(dt, entrynum, low, high);
-}
+       if (insn_len > len || start == NULL)
+               insn_len = len;
+       else
+               memcpy(site, start, insn_len);
 
-static void native_load_esp0(struct tss_struct *tss,
-                                     struct thread_struct *thread)
-{
-       tss->esp0 = thread->esp0;
-
-       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
-       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
-               tss->ss1 = thread->sysenter_cs;
-               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
-       }
+       return insn_len;
 }
 
-static void native_io_delay(void)
+void init_IRQ(void)
 {
-       asm volatile("outb %al,$0x80");
+       paravirt_ops.init_IRQ();
 }
 
 static void native_flush_tlb(void)
@@ -395,83 +213,11 @@ static void native_flush_tlb_global(void)
        __native_flush_tlb_global();
 }
 
-static void native_flush_tlb_single(u32 addr)
+static void native_flush_tlb_single(unsigned long addr)
 {
        __native_flush_tlb_single(addr);
 }
 
-#ifndef CONFIG_X86_PAE
-static void native_set_pte(pte_t *ptep, pte_t pteval)
-{
-       *ptep = pteval;
-}
-
-static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
-{
-       *ptep = pteval;
-}
-
-static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
-{
-       *pmdp = pmdval;
-}
-
-#else /* CONFIG_X86_PAE */
-
-static void native_set_pte(pte_t *ptep, pte_t pte)
-{
-       ptep->pte_high = pte.pte_high;
-       smp_wmb();
-       ptep->pte_low = pte.pte_low;
-}
-
-static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
-{
-       ptep->pte_high = pte.pte_high;
-       smp_wmb();
-       ptep->pte_low = pte.pte_low;
-}
-
-static void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
-{
-       ptep->pte_low = 0;
-       smp_wmb();
-       ptep->pte_high = pte.pte_high;
-       smp_wmb();
-       ptep->pte_low = pte.pte_low;
-}
-
-static void native_set_pte_atomic(pte_t *ptep, pte_t pteval)
-{
-       set_64bit((unsigned long long *)ptep,pte_val(pteval));
-}
-
-static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
-{
-       set_64bit((unsigned long long *)pmdp,pmd_val(pmdval));
-}
-
-static void native_set_pud(pud_t *pudp, pud_t pudval)
-{
-       *pudp = pudval;
-}
-
-static void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-       ptep->pte_low = 0;
-       smp_wmb();
-       ptep->pte_high = 0;
-}
-
-static void native_pmd_clear(pmd_t *pmd)
-{
-       u32 *tmp = (u32 *)pmd;
-       *tmp = 0;
-       smp_wmb();
-       *(tmp + 1) = 0;
-}
-#endif /* CONFIG_X86_PAE */
-
 /* These are in entry.S */
 extern void native_iret(void);
 extern void native_irq_enable_sysexit(void);
@@ -487,10 +233,11 @@ struct paravirt_ops paravirt_ops = {
        .name = "bare hardware",
        .paravirt_enabled = 0,
        .kernel_rpl = 0,
+       .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
 
        .patch = native_patch,
        .banner = default_banner,
-       .arch_setup = native_nop,
+       .arch_setup = paravirt_nop,
        .memory_setup = machine_specific_memory_setup,
        .get_wallclock = native_get_wallclock,
        .set_wallclock = native_set_wallclock,
@@ -517,8 +264,8 @@ struct paravirt_ops paravirt_ops = {
        .safe_halt = native_safe_halt,
        .halt = native_halt,
        .wbinvd = native_wbinvd,
-       .read_msr = native_read_msr,
-       .write_msr = native_write_msr,
+       .read_msr = native_read_msr_safe,
+       .write_msr = native_write_msr_safe,
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
        .get_scheduled_cycles = native_read_tsc,
@@ -531,9 +278,9 @@ struct paravirt_ops paravirt_ops = {
        .store_idt = native_store_idt,
        .store_tr = native_store_tr,
        .load_tls = native_load_tls,
-       .write_ldt_entry = native_write_ldt_entry,
-       .write_gdt_entry = native_write_gdt_entry,
-       .write_idt_entry = native_write_idt_entry,
+       .write_ldt_entry = write_dt_entry,
+       .write_gdt_entry = write_dt_entry,
+       .write_idt_entry = write_dt_entry,
        .load_esp0 = native_load_esp0,
 
        .set_iopl_mask = native_set_iopl_mask,
@@ -545,44 +292,57 @@ struct paravirt_ops paravirt_ops = {
        .apic_read = native_apic_read,
        .setup_boot_clock = setup_boot_APIC_clock,
        .setup_secondary_clock = setup_secondary_APIC_clock,
+       .startup_ipi_hook = paravirt_nop,
 #endif
-       .set_lazy_mode = (void *)native_nop,
+       .set_lazy_mode = paravirt_nop,
+
+       .pagetable_setup_start = native_pagetable_setup_start,
+       .pagetable_setup_done = native_pagetable_setup_done,
 
        .flush_tlb_user = native_flush_tlb,
        .flush_tlb_kernel = native_flush_tlb_global,
        .flush_tlb_single = native_flush_tlb_single,
+       .flush_tlb_others = native_flush_tlb_others,
 
-       .map_pt_hook = (void *)native_nop,
-
-       .alloc_pt = (void *)native_nop,
-       .alloc_pd = (void *)native_nop,
-       .alloc_pd_clone = (void *)native_nop,
-       .release_pt = (void *)native_nop,
-       .release_pd = (void *)native_nop,
+       .alloc_pt = paravirt_nop,
+       .alloc_pd = paravirt_nop,
+       .alloc_pd_clone = paravirt_nop,
+       .release_pt = paravirt_nop,
+       .release_pd = paravirt_nop,
 
        .set_pte = native_set_pte,
        .set_pte_at = native_set_pte_at,
        .set_pmd = native_set_pmd,
-       .pte_update = (void *)native_nop,
-       .pte_update_defer = (void *)native_nop,
+       .pte_update = paravirt_nop,
+       .pte_update_defer = paravirt_nop,
+
+#ifdef CONFIG_HIGHPTE
+       .kmap_atomic_pte = kmap_atomic,
+#endif
+
 #ifdef CONFIG_X86_PAE
        .set_pte_atomic = native_set_pte_atomic,
        .set_pte_present = native_set_pte_present,
        .set_pud = native_set_pud,
        .pte_clear = native_pte_clear,
        .pmd_clear = native_pmd_clear,
+
+       .pmd_val = native_pmd_val,
+       .make_pmd = native_make_pmd,
 #endif
 
+       .pte_val = native_pte_val,
+       .pgd_val = native_pgd_val,
+
+       .make_pte = native_make_pte,
+       .make_pgd = native_make_pgd,
+
        .irq_enable_sysexit = native_irq_enable_sysexit,
        .iret = native_iret,
 
-       .startup_ipi_hook = (void *)native_nop,
+       .dup_mmap = paravirt_nop,
+       .exit_mmap = paravirt_nop,
+       .activate_mm = paravirt_nop,
 };
 
-/*
- * NOTE: CONFIG_PARAVIRT is experimental and the paravirt_ops
- * semantics are subject to change. Hence we only do this
- * internal-only export of this, until it gets sorted out and
- * all lowlevel CPU ops used by modules are separately exported.
- */
-EXPORT_SYMBOL_GPL(paravirt_ops);
+EXPORT_SYMBOL(paravirt_ops);
index 393a67d..6199947 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/random.h>
 #include <linux/personality.h>
 #include <linux/tick.h>
+#include <linux/percpu.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -57,7 +58,6 @@
 
 #include <asm/tlbflush.h>
 #include <asm/cpu.h>
-#include <asm/pda.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -66,6 +66,12 @@ static int hlt_counter;
 unsigned long boot_option_idle_override = 0;
 EXPORT_SYMBOL(boot_option_idle_override);
 
+DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
+EXPORT_PER_CPU_SYMBOL(current_task);
+
+DEFINE_PER_CPU(int, cpu_number);
+EXPORT_PER_CPU_SYMBOL(cpu_number);
+
 /*
  * Return saved PC of a blocked thread.
  */
@@ -272,25 +278,24 @@ void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
        }
 }
 
-static int __init idle_setup (char *str)
+static int __init idle_setup(char *str)
 {
-       if (!strncmp(str, "poll", 4)) {
+       if (!strcmp(str, "poll")) {
                printk("using polling idle threads.\n");
                pm_idle = poll_idle;
 #ifdef CONFIG_X86_SMP
                if (smp_num_siblings > 1)
                        printk("WARNING: polling idle and HT enabled, performance may degrade.\n");
 #endif
-       } else if (!strncmp(str, "halt", 4)) {
-               printk("using halt in idle threads.\n");
-               pm_idle = default_idle;
-       }
+       } else if (!strcmp(str, "mwait"))
+               force_mwait = 1;
+       else
+               return -1;
 
        boot_option_idle_override = 1;
-       return 1;
+       return 0;
 }
-
-__setup("idle=", idle_setup);
+early_param("idle", idle_setup);
 
 void show_regs(struct pt_regs * regs)
 {
@@ -343,7 +348,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 
        regs.xds = __USER_DS;
        regs.xes = __USER_DS;
-       regs.xfs = __KERNEL_PDA;
+       regs.xfs = __KERNEL_PERCPU;
        regs.orig_eax = -1;
        regs.eip = (unsigned long) kernel_thread_helper;
        regs.xcs = __KERNEL_CS | get_kernel_rpl();
@@ -376,7 +381,7 @@ void exit_thread(void)
                t->io_bitmap_max = 0;
                tss->io_bitmap_owner = NULL;
                tss->io_bitmap_max = 0;
-               tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+               tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
                put_cpu();
        }
 }
@@ -555,7 +560,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
                 * Disable the bitmap via an invalid offset. We still cache
                 * the previous bitmap owner and the IO bitmap contents:
                 */
-               tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+               tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
                return;
        }
 
@@ -565,7 +570,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
                 * matches the next task, we dont have to do anything but
                 * to set a valid offset in the TSS:
                 */
-               tss->io_bitmap_base = IO_BITMAP_OFFSET;
+               tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
                return;
        }
        /*
@@ -577,7 +582,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
         * redundant copies when the currently switched task does not
         * perform any I/O during its timeslice.
         */
-       tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+       tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
 }
 
 /*
@@ -712,7 +717,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        if (prev->gs | next->gs)
                loadsegment(gs, next->gs);
 
-       write_pda(pcurrent, next_p);
+       x86_write_percpu(current_task, next_p);
 
        return prev_p;
 }
index 34874c3..9f6ab17 100644 (file)
@@ -3,12 +3,10 @@
  */
 #include <linux/pci.h>
 #include <linux/irq.h>
-#include <asm/pci-direct.h>
-#include <asm/genapic.h>
-#include <asm/cpu.h>
 
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
-static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
+
+static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
 {
        u8 config, rev;
        u32 word;
@@ -16,12 +14,14 @@ static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
        /* BIOS may enable hardware IRQ balancing for
         * E7520/E7320/E7525(revision ID 0x9 and below)
         * based platforms.
-        * For those platforms, make sure that the genapic is set to 'flat'
+        * Disable SW irqbalance/affinity on those platforms.
         */
        pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
        if (rev > 0x9)
                return;
 
+       printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+
        /* enable access to config space*/
        pci_read_config_byte(dev, 0xf4, &config);
        pci_write_config_byte(dev, 0xf4, config|0x2);
@@ -29,44 +29,6 @@ static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
        /* read xTPR register */
        raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
-       if (!(word & (1 << 13))) {
-#ifdef CONFIG_X86_64
-               if (genapic !=  &apic_flat)
-                       panic("APIC mode must be flat on this system\n");
-#elif defined(CONFIG_X86_GENERICARCH)
-               if (genapic != &apic_default)
-                       panic("APIC mode must be default(flat) on this system. Use apic=default\n");
-#endif
-       }
-
-       /* put back the original value for config space*/
-       if (!(config & 0x2))
-               pci_write_config_byte(dev, 0xf4, config);
-}
-
-void __init quirk_intel_irqbalance(void)
-{
-       u8 config, rev;
-       u32 word;
-
-       /* BIOS may enable hardware IRQ balancing for
-        * E7520/E7320/E7525(revision ID 0x9 and below)
-        * based platforms.
-        * Disable SW irqbalance/affinity on those platforms.
-        */
-       rev = read_pci_config_byte(0, 0, 0, PCI_CLASS_REVISION);
-       if (rev > 0x9)
-               return;
-
-       printk(KERN_INFO "Intel E7520/7320/7525 detected.");
-
-       /* enable access to config space */
-       config = read_pci_config_byte(0, 0, 0, 0xf4);
-       write_pci_config_byte(0, 0, 0, 0xf4, config|0x2);
-
-       /* read xTPR register */
-       word = read_pci_config_16(0, 0, 0x40, 0x4c);
-
        if (!(word & (1 << 13))) {
                printk(KERN_INFO "Disabling irq balancing and affinity\n");
 #ifdef CONFIG_IRQBALANCE
@@ -75,25 +37,14 @@ void __init quirk_intel_irqbalance(void)
                noirqdebug_setup("");
 #ifdef CONFIG_PROC_FS
                no_irq_affinity = 1;
-#endif
-#ifdef CONFIG_HOTPLUG_CPU
-               printk(KERN_INFO "Disabling cpu hotplug control\n");
-               enable_cpu_hotplug = 0;
-#endif
-#ifdef CONFIG_X86_64
-               /* force the genapic selection to flat mode so that
-                * interrupts can be redirected to more than one CPU.
-                */
-               genapic_force = &apic_flat;
 #endif
        }
 
-       /* put back the original value for config space */
+       /* put back the original value for config space*/
        if (!(config & 0x2))
-               write_pci_config_byte(0, 0, 0, 0xf4, config);
+               pci_write_config_byte(dev, 0xf4, config);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  verify_quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  verify_quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7520_MCH,  verify_quirk_intel_irqbalance);
-
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7520_MCH,  quirk_intel_irqbalance);
 #endif
index 3514b41..50dfc65 100644 (file)
@@ -17,7 +17,8 @@
 #include <asm/apic.h>
 #include <asm/desc.h>
 #include "mach_reboot.h"
-#include <linux/reboot_fixups.h>
+#include <asm/reboot_fixups.h>
+#include <asm/reboot.h>
 
 /*
  * Power off function, if any
@@ -197,8 +198,6 @@ static unsigned char jump_to_bios [] =
  */
 void machine_real_restart(unsigned char *code, int length)
 {
-       unsigned long flags;
-
        local_irq_disable();
 
        /* Write zero to CMOS register number 0x0f, which the BIOS POST
@@ -211,9 +210,9 @@ void machine_real_restart(unsigned char *code, int length)
           safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
         */
 
-       spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&rtc_lock);
        CMOS_WRITE(0x00, 0x8f);
-       spin_unlock_irqrestore(&rtc_lock, flags);
+       spin_unlock(&rtc_lock);
 
        /* Remap the kernel at virtual address zero, as well as offset zero
           from the kernel segment.  This assumes the kernel segment starts at
@@ -280,7 +279,7 @@ void machine_real_restart(unsigned char *code, int length)
 EXPORT_SYMBOL(machine_real_restart);
 #endif
 
-void machine_shutdown(void)
+static void native_machine_shutdown(void)
 {
 #ifdef CONFIG_SMP
        int reboot_cpu_id;
@@ -316,7 +315,11 @@ void machine_shutdown(void)
 #endif
 }
 
-void machine_emergency_restart(void)
+void __attribute__((weak)) mach_reboot_fixups(void)
+{
+}
+
+static void native_machine_emergency_restart(void)
 {
        if (!reboot_thru_bios) {
                if (efi_enabled) {
@@ -340,17 +343,17 @@ void machine_emergency_restart(void)
        machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
 }
 
-void machine_restart(char * __unused)
+static void native_machine_restart(char * __unused)
 {
        machine_shutdown();
        machine_emergency_restart();
 }
 
-void machine_halt(void)
+static void native_machine_halt(void)
 {
 }
 
-void machine_power_off(void)
+static void native_machine_power_off(void)
 {
        if (pm_power_off) {
                machine_shutdown();
@@ -359,3 +362,35 @@ void machine_power_off(void)
 }
 
 
+struct machine_ops machine_ops = {
+       .power_off = native_machine_power_off,
+       .shutdown = native_machine_shutdown,
+       .emergency_restart = native_machine_emergency_restart,
+       .restart = native_machine_restart,
+       .halt = native_machine_halt,
+};
+
+void machine_power_off(void)
+{
+       machine_ops.power_off();
+}
+
+void machine_shutdown(void)
+{
+       machine_ops.shutdown();
+}
+
+void machine_emergency_restart(void)
+{
+       machine_ops.emergency_restart();
+}
+
+void machine_restart(char *cmd)
+{
+       machine_ops.restart(cmd);
+}
+
+void machine_halt(void)
+{
+       machine_ops.halt();
+}
index 99aab41..2d78d91 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <asm/delay.h>
 #include <linux/pci.h>
-#include <linux/reboot_fixups.h>
+#include <asm/reboot_fixups.h>
 
 static void cs5530a_warm_reset(struct pci_dev *dev)
 {
index 0e89778..89a45a9 100644 (file)
@@ -165,20 +165,20 @@ void fastcall send_IPI_self(int vector)
 }
 
 /*
- * This is only used on smaller machines.
+ * This is used to send an IPI with no shorthand notation (the destination is
+ * specified in bits 56 to 63 of the ICR).
  */
-void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+static inline void __send_IPI_dest_field(unsigned long mask, int vector)
 {
-       unsigned long mask = cpus_addr(cpumask)[0];
        unsigned long cfg;
-       unsigned long flags;
 
-       local_irq_save(flags);
-       WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
        /*
         * Wait for idle.
         */
-       apic_wait_icr_idle();
+       if (unlikely(vector == NMI_VECTOR))
+               safe_apic_wait_icr_idle();
+       else
+               apic_wait_icr_idle();
                
        /*
         * prepare target chip field
@@ -195,13 +195,25 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
         * Send the IPI. The write to APIC_ICR fires this off.
         */
        apic_write_around(APIC_ICR, cfg);
+}
+
+/*
+ * This is only used on smaller machines.
+ */
+void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+{
+       unsigned long mask = cpus_addr(cpumask)[0];
+       unsigned long flags;
 
+       local_irq_save(flags);
+       WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
+       __send_IPI_dest_field(mask, vector);
        local_irq_restore(flags);
 }
 
 void send_IPI_mask_sequence(cpumask_t mask, int vector)
 {
-       unsigned long cfg, flags;
+       unsigned long flags;
        unsigned int query_cpu;
 
        /*
@@ -211,30 +223,10 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector)
         */ 
 
        local_irq_save(flags);
-
        for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) {
                if (cpu_isset(query_cpu, mask)) {
-               
-                       /*
-                        * Wait for idle.
-                        */
-                       apic_wait_icr_idle();
-               
-                       /*
-                        * prepare target chip field
-                        */
-                       cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu));
-                       apic_write_around(APIC_ICR2, cfg);
-               
-                       /*
-                        * program the ICR 
-                        */
-                       cfg = __prepare_ICR(0, vector);
-                       
-                       /*
-                        * Send the IPI. The write to APIC_ICR fires this off.
-                        */
-                       apic_write_around(APIC_ICR, cfg);
+                       __send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
+                                             vector);
                }
        }
        local_irq_restore(flags);
@@ -256,7 +248,6 @@ static cpumask_t flush_cpumask;
 static struct mm_struct * flush_mm;
 static unsigned long flush_va;
 static DEFINE_SPINLOCK(tlbstate_lock);
-#define FLUSH_ALL      0xffffffff
 
 /*
  * We cannot call mmdrop() because we are in interrupt context, 
@@ -338,7 +329,7 @@ fastcall void smp_invalidate_interrupt(struct pt_regs *regs)
                 
        if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
                if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
-                       if (flush_va == FLUSH_ALL)
+                       if (flush_va == TLB_FLUSH_ALL)
                                local_flush_tlb();
                        else
                                __flush_tlb_one(flush_va);
@@ -353,9 +344,11 @@ out:
        put_cpu_no_resched();
 }
 
-static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
-                                               unsigned long va)
+void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+                            unsigned long va)
 {
+       cpumask_t cpumask = *cpumaskp;
+
        /*
         * A couple of (to be removed) sanity checks:
         *
@@ -366,10 +359,12 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
        BUG_ON(cpu_isset(smp_processor_id(), cpumask));
        BUG_ON(!mm);
 
+#ifdef CONFIG_HOTPLUG_CPU
        /* If a CPU which we ran on has gone down, OK. */
        cpus_and(cpumask, cpumask, cpu_online_map);
-       if (cpus_empty(cpumask))
+       if (unlikely(cpus_empty(cpumask)))
                return;
+#endif
 
        /*
         * i'm not happy about this global shared spinlock in the
@@ -380,17 +375,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
        
        flush_mm = mm;
        flush_va = va;
-#if NR_CPUS <= BITS_PER_LONG
-       atomic_set_mask(cpumask, &flush_cpumask);
-#else
-       {
-               int k;
-               unsigned long *flush_mask = (unsigned long *)&flush_cpumask;
-               unsigned long *cpu_mask = (unsigned long *)&cpumask;
-               for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k)
-                       atomic_set_mask(cpu_mask[k], &flush_mask[k]);
-       }
-#endif
+       cpus_or(flush_cpumask, cpumask, flush_cpumask);
        /*
         * We have to send the IPI only to
         * CPUs affected.
@@ -417,7 +402,7 @@ void flush_tlb_current_task(void)
 
        local_flush_tlb();
        if (!cpus_empty(cpu_mask))
-               flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
+               flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
        preempt_enable();
 }
 
@@ -436,7 +421,7 @@ void flush_tlb_mm (struct mm_struct * mm)
                        leave_mm(smp_processor_id());
        }
        if (!cpus_empty(cpu_mask))
-               flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
+               flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
 
        preempt_enable();
 }
@@ -483,7 +468,7 @@ void flush_tlb_all(void)
  * it goes straight through and wastes no time serializing
  * anything. Worst case is that we lose a reschedule ...
  */
-void smp_send_reschedule(int cpu)
+void native_smp_send_reschedule(int cpu)
 {
        WARN_ON(cpu_is_offline(cpu));
        send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
@@ -515,36 +500,78 @@ void unlock_ipi_call_lock(void)
 
 static struct call_data_struct *call_data;
 
+static void __smp_call_function(void (*func) (void *info), void *info,
+                               int nonatomic, int wait)
+{
+       struct call_data_struct data;
+       int cpus = num_online_cpus() - 1;
+
+       if (!cpus)
+               return;
+
+       data.func = func;
+       data.info = info;
+       atomic_set(&data.started, 0);
+       data.wait = wait;
+       if (wait)
+               atomic_set(&data.finished, 0);
+
+       call_data = &data;
+       mb();
+       
+       /* Send a message to all other CPUs and wait for them to respond */
+       send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+
+       /* Wait for response */
+       while (atomic_read(&data.started) != cpus)
+               cpu_relax();
+
+       if (wait)
+               while (atomic_read(&data.finished) != cpus)
+                       cpu_relax();
+}
+
+
 /**
- * smp_call_function(): Run a function on all other CPUs.
+ * smp_call_function_mask(): Run a function on a set of other CPUs.
+ * @mask: The set of cpus to run on.  Must not include the current 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 (atomically) 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.
+  * Returns 0 on success, else a negative status code.
+ *
+ * If @wait is true, then returns once @func has returned; otherwise
+ * it returns just before the target cpu calls @func.
  *
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler or from a bottom half handler.
  */
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-                       int wait)
+int native_smp_call_function_mask(cpumask_t mask,
+                                 void (*func)(void *), void *info,
+                                 int wait)
 {
        struct call_data_struct data;
+       cpumask_t allbutself;
        int cpus;
 
+       /* Can deadlock when called with interrupts disabled */
+       WARN_ON(irqs_disabled());
+
        /* Holding any lock stops cpus from going down. */
        spin_lock(&call_lock);
-       cpus = num_online_cpus() - 1;
+
+       allbutself = cpu_online_map;
+       cpu_clear(smp_processor_id(), allbutself);
+
+       cpus_and(mask, mask, allbutself);
+       cpus = cpus_weight(mask);
+
        if (!cpus) {
                spin_unlock(&call_lock);
                return 0;
        }
 
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
        data.func = func;
        data.info = info;
        atomic_set(&data.started, 0);
@@ -554,9 +581,12 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
 
        call_data = &data;
        mb();
-       
-       /* Send a message to all other CPUs and wait for them to respond */
-       send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+
+       /* Send a message to other CPUs */
+       if (cpus_equal(mask, allbutself))
+               send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+       else
+               send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
 
        /* Wait for response */
        while (atomic_read(&data.started) != cpus)
@@ -569,15 +599,68 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
 
        return 0;
 }
+
+/**
+ * smp_call_function(): Run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: Unused.
+ * @wait: If true, wait (atomically) until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code.
+ *
+ * If @wait is true, then returns once @func has returned; otherwise
+ * it returns just before the target cpu calls @func.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+                     int wait)
+{
+       return smp_call_function_mask(cpu_online_map, func, info, wait);
+}
 EXPORT_SYMBOL(smp_call_function);
 
+/**
+ * smp_call_function_single - Run a function on another CPU
+ * @cpu: The target CPU.  Cannot be the calling CPU.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: Unused.
+ * @wait: If true, wait until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code.
+ *
+ * If @wait is true, then returns once @func has returned; otherwise
+ * it returns just before the target cpu calls @func.
+ */
+int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+                            int nonatomic, int wait)
+{
+       /* prevent preemption and reschedule on another processor */
+       int ret;
+       int me = get_cpu();
+       if (cpu == me) {
+               WARN_ON(1);
+               put_cpu();
+               return -EBUSY;
+       }
+
+       ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+
+       put_cpu();
+       return ret;
+}
+EXPORT_SYMBOL(smp_call_function_single);
+
 static void stop_this_cpu (void * dummy)
 {
+       local_irq_disable();
        /*
         * Remove this CPU:
         */
        cpu_clear(smp_processor_id(), cpu_online_map);
-       local_irq_disable();
        disable_local_APIC();
        if (cpu_data[smp_processor_id()].hlt_works_ok)
                for(;;) halt();
@@ -588,13 +671,18 @@ static void stop_this_cpu (void * dummy)
  * this function calls the 'stop' function on all other CPUs in the system.
  */
 
-void smp_send_stop(void)
+void native_smp_send_stop(void)
 {
-       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       /* Don't deadlock on the call lock in panic */
+       int nolock = !spin_trylock(&call_lock);
+       unsigned long flags;
 
-       local_irq_disable();
+       local_irq_save(flags);
+       __smp_call_function(stop_this_cpu, NULL, 0, 0);
+       if (!nolock)
+               spin_unlock(&call_lock);
        disable_local_APIC();
-       local_irq_enable();
+       local_irq_restore(flags);
 }
 
 /*
@@ -633,77 +721,6 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
        }
 }
 
-/*
- * this function sends a 'generic call function' IPI to one other CPU
- * in the system.
- *
- * cpu is a standard Linux logical CPU number.
- */
-static void
-__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
-                               int nonatomic, int wait)
-{
-       struct call_data_struct data;
-       int cpus = 1;
-
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-
-       call_data = &data;
-       wmb();
-       /* Send a message to all other CPUs and wait for them to respond */
-       send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
-
-       /* Wait for response */
-       while (atomic_read(&data.started) != cpus)
-               cpu_relax();
-
-       if (!wait)
-               return;
-
-       while (atomic_read(&data.finished) != cpus)
-               cpu_relax();
-}
-
-/*
- * 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)
-{
-       /* prevent preemption and reschedule on another processor */
-       int me = get_cpu();
-       if (cpu == me) {
-               WARN_ON(1);
-               put_cpu();
-               return -EBUSY;
-       }
-
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-
-       spin_lock_bh(&call_lock);
-       __smp_call_function_single(cpu, func, info, nonatomic, wait);
-       spin_unlock_bh(&call_lock);
-       put_cpu();
-       return 0;
-}
-EXPORT_SYMBOL(smp_call_function_single);
-
 static int convert_apicid_to_cpu(int apic_id)
 {
        int i;
@@ -730,3 +747,14 @@ int safe_smp_processor_id(void)
 
        return cpuid >= 0 ? cpuid : 0;
 }
+
+struct smp_ops smp_ops = {
+       .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
+       .smp_prepare_cpus = native_smp_prepare_cpus,
+       .cpu_up = native_cpu_up,
+       .smp_cpus_done = native_smp_cpus_done,
+
+       .smp_send_stop = native_smp_send_stop,
+       .smp_send_reschedule = native_smp_send_reschedule,
+       .smp_call_function_mask = native_smp_call_function_mask,
+};
index 4ff55e6..a4b7ad2 100644 (file)
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 #include <asm/nmi.h>
-#include <asm/pda.h>
-#include <asm/genapic.h>
 
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
 #include <asm/vmi.h>
+#include <asm/mtrr.h>
 
 /* Set if we find a B stepping CPU */
 static int __devinitdata smp_b_stepping;
@@ -100,6 +99,9 @@ EXPORT_SYMBOL(x86_cpu_to_apicid);
 
 u8 apicid_2_node[MAX_APICID];
 
+DEFINE_PER_CPU(unsigned long, this_cpu_off);
+EXPORT_PER_CPU_SYMBOL(this_cpu_off);
+
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -156,7 +158,7 @@ static void __cpuinit smp_store_cpu_info(int id)
 
        *c = boot_cpu_data;
        if (id!=0)
-               identify_cpu(c);
+               identify_secondary_cpu(c);
        /*
         * Mask B, Pentium, but not Pentium MMX
         */
@@ -379,14 +381,14 @@ set_cpu_sibling_map(int cpu)
 static void __cpuinit start_secondary(void *unused)
 {
        /*
-        * Don't put *anything* before secondary_cpu_init(), SMP
-        * booting is too fragile that we want to limit the
-        * things done here to the most necessary things.
+        * Don't put *anything* before cpu_init(), SMP booting is too
+        * fragile that we want to limit the things done here to the
+        * most necessary things.
         */
 #ifdef CONFIG_VMI
        vmi_bringup();
 #endif
-       secondary_cpu_init();
+       cpu_init();
        preempt_disable();
        smp_callin();
        while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
@@ -440,12 +442,6 @@ static void __cpuinit start_secondary(void *unused)
  */
 void __devinit initialize_secondary(void)
 {
-       /*
-        * switch to the per CPU GDT we already set up
-        * in do_boot_cpu()
-        */
-       cpu_set_gdt(current_thread_info()->cpu);
-
        /*
         * We don't actually need to load the full TSS,
         * basically just the stack pointer and the eip.
@@ -463,7 +459,6 @@ extern struct {
        void * esp;
        unsigned short ss;
 } stack_start;
-extern struct i386_pda *start_pda;
 
 #ifdef CONFIG_NUMA
 
@@ -521,12 +516,12 @@ static void unmap_cpu_to_logical_apicid(int cpu)
        unmap_cpu_to_node(cpu);
 }
 
-#if APIC_DEBUG
 static inline void __inquire_remote_apic(int apicid)
 {
        int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
        char *names[] = { "ID", "VERSION", "SPIV" };
-       int timeout, status;
+       int timeout;
+       unsigned long status;
 
        printk("Inquiring remote APIC #%d...\n", apicid);
 
@@ -536,7 +531,9 @@ static inline void __inquire_remote_apic(int apicid)
                /*
                 * Wait for idle.
                 */
-               apic_wait_icr_idle();
+               status = safe_apic_wait_icr_idle();
+               if (status)
+                       printk("a previous APIC delivery may have failed\n");
 
                apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
                apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
@@ -550,14 +547,13 @@ static inline void __inquire_remote_apic(int apicid)
                switch (status) {
                case APIC_ICR_RR_VALID:
                        status = apic_read(APIC_RRR);
-                       printk("%08x\n", status);
+                       printk("%lx\n", status);
                        break;
                default:
                        printk("failed\n");
                }
        }
 }
-#endif
 
 #ifdef WAKE_SECONDARY_VIA_NMI
 /* 
@@ -568,8 +564,8 @@ static inline void __inquire_remote_apic(int apicid)
 static int __devinit
 wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
 {
-       unsigned long send_status = 0, accept_status = 0;
-       int timeout, maxlvt;
+       unsigned long send_status, accept_status = 0;
+       int maxlvt;
 
        /* Target chip */
        apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
@@ -579,12 +575,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
        apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        /*
         * Give the other CPU some time to accept the IPI.
@@ -614,8 +605,8 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
 static int __devinit
 wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
 {
-       unsigned long send_status = 0, accept_status = 0;
-       int maxlvt, timeout, num_starts, j;
+       unsigned long send_status, accept_status = 0;
+       int maxlvt, num_starts, j;
 
        /*
         * Be paranoid about clearing APIC errors.
@@ -640,12 +631,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
                                | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        mdelay(10);
 
@@ -658,12 +644,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
        apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        atomic_set(&init_deasserted, 1);
 
@@ -719,12 +700,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
                Dprintk("Startup point 1.\n");
 
                Dprintk("Waiting for send to finish...\n");
-               timeout = 0;
-               do {
-                       Dprintk("+");
-                       udelay(100);
-                       send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-               } while (send_status && (timeout++ < 1000));
+               send_status = safe_apic_wait_icr_idle();
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -788,6 +764,25 @@ static inline struct task_struct * alloc_idle_task(int cpu)
 #define alloc_idle_task(cpu) fork_idle(cpu)
 #endif
 
+/* Initialize the CPU's GDT.  This is either the boot CPU doing itself
+   (still using the master per-cpu area), or a CPU doing it for a
+   secondary which will soon come up. */
+static __cpuinit void init_gdt(int cpu)
+{
+       struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+       pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a,
+                       (u32 *)&gdt[GDT_ENTRY_PERCPU].b,
+                       __per_cpu_offset[cpu], 0xFFFFF,
+                       0x80 | DESCTYPE_S | 0x2, 0x8);
+
+       per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
+       per_cpu(cpu_number, cpu) = cpu;
+}
+
+/* Defined in head.S */
+extern struct Xgt_desc_struct early_gdt_descr;
+
 static int __cpuinit do_boot_cpu(int apicid, int cpu)
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
@@ -801,6 +796,12 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
        unsigned long start_eip;
        unsigned short nmi_high = 0, nmi_low = 0;
 
+       /*
+        * Save current MTRR state in case it was changed since early boot
+        * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+        */
+       mtrr_save_state();
+
        /*
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
@@ -809,13 +810,9 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
        if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
 
-       /* Pre-allocate and initialize the CPU's GDT and PDA so it
-          doesn't have to do any memory allocation during the
-          delicate CPU-bringup phase. */
-       if (!init_gdt(cpu, idle)) {
-               printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu);
-               return -1;      /* ? */
-       }
+       init_gdt(cpu);
+       per_cpu(current_task, cpu) = idle;
+       early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
 
        idle->thread.eip = (unsigned long) start_secondary;
        /* start_eip had better be page-aligned! */
@@ -941,7 +938,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
        DECLARE_COMPLETION_ONSTACK(done);
        struct warm_boot_cpu_info info;
        int     apicid, ret;
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
 
        apicid = x86_cpu_to_apicid[cpu];
        if (apicid == BAD_APICID) {
@@ -949,18 +945,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
                goto exit;
        }
 
-       /*
-        * the CPU isn't initialized at boot time, allocate gdt table here.
-        * cpu_init will initialize it
-        */
-       if (!cpu_gdt_descr->address) {
-               cpu_gdt_descr->address = get_zeroed_page(GFP_KERNEL);
-               if (!cpu_gdt_descr->address)
-                       printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
-                       ret = -ENOMEM;
-                       goto exit;
-       }
-
        info.complete = &done;
        info.apicid = apicid;
        info.cpu = cpu;
@@ -1173,7 +1157,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 
 /* These are wrappers to interface to the new boot process.  Someone
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init native_smp_prepare_cpus(unsigned int max_cpus)
 {
        smp_commenced_mask = cpumask_of_cpu(0);
        cpu_callin_map = cpumask_of_cpu(0);
@@ -1181,13 +1165,18 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        smp_boot_cpus(max_cpus);
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+void __init native_smp_prepare_boot_cpu(void)
 {
-       cpu_set(smp_processor_id(), cpu_online_map);
-       cpu_set(smp_processor_id(), cpu_callout_map);
-       cpu_set(smp_processor_id(), cpu_present_map);
-       cpu_set(smp_processor_id(), cpu_possible_map);
-       per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+       unsigned int cpu = smp_processor_id();
+
+       init_gdt(cpu);
+       switch_to_new_gdt();
+
+       cpu_set(cpu, cpu_online_map);
+       cpu_set(cpu, cpu_callout_map);
+       cpu_set(cpu, cpu_present_map);
+       cpu_set(cpu, cpu_possible_map);
+       __get_cpu_var(cpu_state) = CPU_ONLINE;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1277,7 +1266,7 @@ void __cpu_die(unsigned int cpu)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit native_cpu_up(unsigned int cpu)
 {
        unsigned long flags;
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1319,15 +1308,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
                touch_nmi_watchdog();
        }
 
-#ifdef CONFIG_X86_GENERICARCH
-       if (num_online_cpus() > 8 && genapic == &apic_default)
-               panic("Default flat APIC routing can't be used with > 8 cpus\n");
-#endif
-
        return 0;
 }
 
-void __init smp_cpus_done(unsigned int max_cpus)
+void __init native_smp_cpus_done(unsigned int max_cpus)
 {
 #ifdef CONFIG_X86_IO_APIC
        setup_ioapic_dest();
index 13ca54a..ff4ee6f 100644 (file)
 #include <asm/msr.h>
 #include <asm/pgtable.h>
 #include <asm/unistd.h>
+#include <asm/elf.h>
+#include <asm/tlbflush.h>
+
+enum {
+       VDSO_DISABLED = 0,
+       VDSO_ENABLED = 1,
+       VDSO_COMPAT = 2,
+};
+
+#ifdef CONFIG_COMPAT_VDSO
+#define VDSO_DEFAULT   VDSO_COMPAT
+#else
+#define VDSO_DEFAULT   VDSO_ENABLED
+#endif
 
 /*
  * Should the kernel map a VDSO page into processes and pass its
  * address down to glibc upon exec()?
  */
-#ifdef CONFIG_PARAVIRT
-unsigned int __read_mostly vdso_enabled = 0;
-#else
-unsigned int __read_mostly vdso_enabled = 1;
-#endif
+unsigned int __read_mostly vdso_enabled = VDSO_DEFAULT;
 
 EXPORT_SYMBOL_GPL(vdso_enabled);
 
@@ -46,6 +56,123 @@ __setup("vdso=", vdso_setup);
 
 extern asmlinkage void sysenter_entry(void);
 
+static __init void reloc_symtab(Elf32_Ehdr *ehdr,
+                               unsigned offset, unsigned size)
+{
+       Elf32_Sym *sym = (void *)ehdr + offset;
+       unsigned nsym = size / sizeof(*sym);
+       unsigned i;
+
+       for(i = 0; i < nsym; i++, sym++) {
+               if (sym->st_shndx == SHN_UNDEF ||
+                   sym->st_shndx == SHN_ABS)
+                       continue;  /* skip */
+
+               if (sym->st_shndx > SHN_LORESERVE) {
+                       printk(KERN_INFO "VDSO: unexpected st_shndx %x\n",
+                              sym->st_shndx);
+                       continue;
+               }
+
+               switch(ELF_ST_TYPE(sym->st_info)) {
+               case STT_OBJECT:
+               case STT_FUNC:
+               case STT_SECTION:
+               case STT_FILE:
+                       sym->st_value += VDSO_HIGH_BASE;
+               }
+       }
+}
+
+static __init void reloc_dyn(Elf32_Ehdr *ehdr, unsigned offset)
+{
+       Elf32_Dyn *dyn = (void *)ehdr + offset;
+
+       for(; dyn->d_tag != DT_NULL; dyn++)
+               switch(dyn->d_tag) {
+               case DT_PLTGOT:
+               case DT_HASH:
+               case DT_STRTAB:
+               case DT_SYMTAB:
+               case DT_RELA:
+               case DT_INIT:
+               case DT_FINI:
+               case DT_REL:
+               case DT_DEBUG:
+               case DT_JMPREL:
+               case DT_VERSYM:
+               case DT_VERDEF:
+               case DT_VERNEED:
+               case DT_ADDRRNGLO ... DT_ADDRRNGHI:
+                       /* definitely pointers needing relocation */
+                       dyn->d_un.d_ptr += VDSO_HIGH_BASE;
+                       break;
+
+               case DT_ENCODING ... OLD_DT_LOOS-1:
+               case DT_LOOS ... DT_HIOS-1:
+                       /* Tags above DT_ENCODING are pointers if
+                          they're even */
+                       if (dyn->d_tag >= DT_ENCODING &&
+                           (dyn->d_tag & 1) == 0)
+                               dyn->d_un.d_ptr += VDSO_HIGH_BASE;
+                       break;
+
+               case DT_VERDEFNUM:
+               case DT_VERNEEDNUM:
+               case DT_FLAGS_1:
+               case DT_RELACOUNT:
+               case DT_RELCOUNT:
+               case DT_VALRNGLO ... DT_VALRNGHI:
+                       /* definitely not pointers */
+                       break;
+
+               case OLD_DT_LOOS ... DT_LOOS-1:
+               case DT_HIOS ... DT_VALRNGLO-1:
+               default:
+                       if (dyn->d_tag > DT_ENCODING)
+                               printk(KERN_INFO "VDSO: unexpected DT_tag %x\n",
+                                      dyn->d_tag);
+                       break;
+               }
+}
+
+static __init void relocate_vdso(Elf32_Ehdr *ehdr)
+{
+       Elf32_Phdr *phdr;
+       Elf32_Shdr *shdr;
+       int i;
+
+       BUG_ON(memcmp(ehdr->e_ident, ELFMAG, 4) != 0 ||
+              !elf_check_arch(ehdr) ||
+              ehdr->e_type != ET_DYN);
+
+       ehdr->e_entry += VDSO_HIGH_BASE;
+
+       /* rebase phdrs */
+       phdr = (void *)ehdr + ehdr->e_phoff;
+       for (i = 0; i < ehdr->e_phnum; i++) {
+               phdr[i].p_vaddr += VDSO_HIGH_BASE;
+
+               /* relocate dynamic stuff */
+               if (phdr[i].p_type == PT_DYNAMIC)
+                       reloc_dyn(ehdr, phdr[i].p_offset);
+       }
+
+       /* rebase sections */
+       shdr = (void *)ehdr + ehdr->e_shoff;
+       for(i = 0; i < ehdr->e_shnum; i++) {
+               if (!(shdr[i].sh_flags & SHF_ALLOC))
+                       continue;
+
+               shdr[i].sh_addr += VDSO_HIGH_BASE;
+
+               if (shdr[i].sh_type == SHT_SYMTAB ||
+                   shdr[i].sh_type == SHT_DYNSYM)
+                       reloc_symtab(ehdr, shdr[i].sh_offset,
+                                    shdr[i].sh_size);
+       }
+}
+
 void enable_sep_cpu(void)
 {
        int cpu = get_cpu();
@@ -56,14 +183,33 @@ void enable_sep_cpu(void)
                return;
        }
 
-       tss->ss1 = __KERNEL_CS;
-       tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
+       tss->x86_tss.ss1 = __KERNEL_CS;
+       tss->x86_tss.esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
        wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-       wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
+       wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.esp1, 0);
        wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
        put_cpu();      
 }
 
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+       gate_vma.vm_mm = NULL;
+       gate_vma.vm_start = FIXADDR_USER_START;
+       gate_vma.vm_end = FIXADDR_USER_END;
+       gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+       gate_vma.vm_page_prot = __P101;
+       /*
+        * Make sure the vDSO gets into every core dump.
+        * Dumping its contents makes post-mortem fully interpretable later
+        * without matching up the same kernel and hardware config to see
+        * what PC values meant.
+        */
+       gate_vma.vm_flags |= VM_ALWAYSDUMP;
+       return 0;
+}
+
 /*
  * These symbols are defined by vsyscall.o to mark the bounds
  * of the ELF DSO images included therein.
@@ -72,31 +218,48 @@ extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 static struct page *syscall_pages[1];
 
+static void map_compat_vdso(int map)
+{
+       static int vdso_mapped;
+
+       if (map == vdso_mapped)
+               return;
+
+       vdso_mapped = map;
+
+       __set_fixmap(FIX_VDSO, page_to_pfn(syscall_pages[0]) << PAGE_SHIFT,
+                    map ? PAGE_READONLY_EXEC : PAGE_NONE);
+
+       /* flush stray tlbs */
+       flush_tlb_all();
+}
+
 int __init sysenter_setup(void)
 {
        void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+       const void *vsyscall;
+       size_t vsyscall_len;
+
        syscall_pages[0] = virt_to_page(syscall_page);
 
-#ifdef CONFIG_COMPAT_VDSO
-       __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY_EXEC);
+       gate_vma_init();
+
        printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
-#endif
 
        if (!boot_cpu_has(X86_FEATURE_SEP)) {
-               memcpy(syscall_page,
-                      &vsyscall_int80_start,
-                      &vsyscall_int80_end - &vsyscall_int80_start);
-               return 0;
+               vsyscall = &vsyscall_int80_start;
+               vsyscall_len = &vsyscall_int80_end - &vsyscall_int80_start;
+       } else {
+               vsyscall = &vsyscall_sysenter_start;
+               vsyscall_len = &vsyscall_sysenter_end - &vsyscall_sysenter_start;
        }
 
-       memcpy(syscall_page,
-              &vsyscall_sysenter_start,
-              &vsyscall_sysenter_end - &vsyscall_sysenter_start);
+       memcpy(syscall_page, vsyscall, vsyscall_len);
+       relocate_vdso(syscall_page);
 
        return 0;
 }
 
-#ifndef CONFIG_COMPAT_VDSO
 /* Defined in vsyscall-sysenter.S */
 extern void SYSENTER_RETURN;
 
@@ -105,36 +268,52 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
 {
        struct mm_struct *mm = current->mm;
        unsigned long addr;
-       int ret;
+       int ret = 0;
+       bool compat;
 
        down_write(&mm->mmap_sem);
-       addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
-       if (IS_ERR_VALUE(addr)) {
-               ret = addr;
-               goto up_fail;
-       }
 
-       /*
-        * MAYWRITE to allow gdb to COW and set breakpoints
-        *
-        * Make sure the vDSO gets into every core dump.
-        * Dumping its contents makes post-mortem fully interpretable later
-        * without matching up the same kernel and hardware config to see
-        * what PC values meant.
-        */
-       ret = install_special_mapping(mm, addr, PAGE_SIZE,
-                                     VM_READ|VM_EXEC|
-                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-                                     VM_ALWAYSDUMP,
-                                     syscall_pages);
-       if (ret)
-               goto up_fail;
+       /* Test compat mode once here, in case someone
+          changes it via sysctl */
+       compat = (vdso_enabled == VDSO_COMPAT);
+
+       map_compat_vdso(compat);
+
+       if (compat)
+               addr = VDSO_HIGH_BASE;
+       else {
+               addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+               if (IS_ERR_VALUE(addr)) {
+                       ret = addr;
+                       goto up_fail;
+               }
+
+               /*
+                * MAYWRITE to allow gdb to COW and set breakpoints
+                *
+                * Make sure the vDSO gets into every core dump.
+                * Dumping its contents makes post-mortem fully
+                * interpretable later without matching up the same
+                * kernel and hardware config to see what PC values
+                * meant.
+                */
+               ret = install_special_mapping(mm, addr, PAGE_SIZE,
+                                             VM_READ|VM_EXEC|
+                                             VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+                                             VM_ALWAYSDUMP,
+                                             syscall_pages);
+
+               if (ret)
+                       goto up_fail;
+       }
 
        current->mm->context.vdso = (void *)addr;
        current_thread_info()->sysenter_return =
-                                   (void *)VDSO_SYM(&SYSENTER_RETURN);
-up_fail:
+               (void *)VDSO_SYM(&SYSENTER_RETURN);
+
+  up_fail:
        up_write(&mm->mmap_sem);
+
        return ret;
 }
 
@@ -147,6 +326,11 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 
 struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
 {
+       struct mm_struct *mm = tsk->mm;
+
+       /* Check to see if this task was created in compat vdso mode */
+       if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE)
+               return &gate_vma;
        return NULL;
 }
 
@@ -159,4 +343,3 @@ int in_gate_area_no_task(unsigned long addr)
 {
        return 0;
 }
-#endif
index 94e5cb0..a665df6 100644 (file)
@@ -70,8 +70,6 @@
 
 #include <asm/i8259.h>
 
-int pit_latch_buggy;              /* extern */
-
 #include "do_timer.h"
 
 unsigned int cpu_khz;  /* Detected as we calibrate the TSC */
index 2f1814c..f62815f 100644 (file)
@@ -29,7 +29,7 @@
  *
  *     TYPE              VALUE
  *     R_386_32          startup_32_smp
- *     R_386_32          boot_gdt_table
+ *     R_386_32          boot_gdt
  */
 
 #include <linux/linkage.h>
@@ -62,8 +62,8 @@ r_base = .
         * to 32 bit.
         */
 
-       lidtl   boot_idt - r_base       # load idt with 0, 0
-       lgdtl   boot_gdt - r_base       # load gdt with whatever is appropriate
+       lidtl   boot_idt_descr - r_base # load idt with 0, 0
+       lgdtl   boot_gdt_descr - r_base # load gdt with whatever is appropriate
 
        xor     %ax, %ax
        inc     %ax             # protected mode (PE) bit
@@ -73,11 +73,11 @@ r_base = .
 
        # These need to be in the same 64K segment as the above;
        # hence we don't use the boot_gdt_descr defined in head.S
-boot_gdt:
+boot_gdt_descr:
        .word   __BOOT_DS + 7                   # gdt limit
-       .long   boot_gdt_table-__PAGE_OFFSET    # gdt base
+       .long   boot_gdt - __PAGE_OFFSET        # gdt base
 
-boot_idt:
+boot_idt_descr:
        .word   0                               # idt limit = 0
        .long   0                               # idt base = 0L
 
index af0d3f7..f21b41e 100644 (file)
@@ -476,8 +476,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
                              siginfo_t *info)
 {
        struct task_struct *tsk = current;
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = trapnr;
 
        if (regs->eflags & VM_MASK) {
                if (vm86)
@@ -489,6 +487,18 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
                goto kernel_trap;
 
        trap_signal: {
+               /*
+                * We want error_code and trap_no set for userspace faults and
+                * kernelspace faults which result in die(), but not
+                * kernelspace faults which are fixed up.  die() gives the
+                * process no chance to handle the signal and notice the
+                * kernel fault information, so that won't result in polluting
+                * the information about previously queued, but not yet
+                * delivered, faults.  See also do_general_protection below.
+                */
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
+
                if (info)
                        force_sig_info(signr, info, tsk);
                else
@@ -497,8 +507,11 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
        }
 
        kernel_trap: {
-               if (!fixup_exception(regs))
+               if (!fixup_exception(regs)) {
+                       tsk->thread.error_code = error_code;
+                       tsk->thread.trap_no = trapnr;
                        die(str, regs, error_code);
+               }
                return;
        }
 
@@ -583,7 +596,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
         * and we set the offset field correctly. Then we let the CPU to
         * restart the faulting instruction.
         */
-       if (tss->io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
+       if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
            thread->io_bitmap_ptr) {
                memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
                       thread->io_bitmap_max);
@@ -596,16 +609,13 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
                                thread->io_bitmap_max, 0xff,
                                tss->io_bitmap_max - thread->io_bitmap_max);
                tss->io_bitmap_max = thread->io_bitmap_max;
-               tss->io_bitmap_base = IO_BITMAP_OFFSET;
+               tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
                tss->io_bitmap_owner = thread;
                put_cpu();
                return;
        }
        put_cpu();
 
-       current->thread.error_code = error_code;
-       current->thread.trap_no = 13;
-
        if (regs->eflags & VM_MASK)
                goto gp_in_vm86;
 
@@ -624,6 +634,8 @@ gp_in_vm86:
 
 gp_in_kernel:
        if (!fixup_exception(regs)) {
+               current->thread.error_code = error_code;
+               current->thread.trap_no = 13;
                if (notify_die(DIE_GPF, "general protection fault", regs,
                                error_code, 13, SIGSEGV) == NOTIFY_STOP)
                        return;
@@ -1018,9 +1030,7 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
 fastcall unsigned long patch_espfix_desc(unsigned long uesp,
                                          unsigned long kesp)
 {
-       int cpu = smp_processor_id();
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-       struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address;
+       struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
        unsigned long base = (kesp - uesp) & -THREAD_SIZE;
        unsigned long new_kesp = kesp - base;
        unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
index 6cb8f53..f64b81f 100644 (file)
@@ -200,13 +200,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
        struct cpufreq_freqs *freq = data;
 
-       if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
-               write_seqlock_irq(&xtime_lock);
-
        if (!ref_freq) {
                if (!freq->old){
                        ref_freq = freq->new;
-                       goto end;
+                       return 0;
                }
                ref_freq = freq->old;
                loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
@@ -233,13 +230,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
                                 * TSC based sched_clock turns
                                 * to junk w/ cpufreq
                                 */
-                               mark_tsc_unstable();
+                               mark_tsc_unstable("cpufreq changes");
                        }
                }
        }
-end:
-       if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
-               write_sequnlock_irq(&xtime_lock);
 
        return 0;
 }
@@ -281,11 +275,12 @@ static struct clocksource clocksource_tsc = {
                                  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-void mark_tsc_unstable(void)
+void mark_tsc_unstable(char *reason)
 {
        if (!tsc_unstable) {
                tsc_unstable = 1;
                tsc_enabled = 0;
+               printk("Marking TSC unstable due to: %s.\n", reason);
                /* Can be called before registration */
                if (clocksource_tsc.mult)
                        clocksource_change_rating(&clocksource_tsc, 0);
diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S
new file mode 100644 (file)
index 0000000..e51a869
--- /dev/null
@@ -0,0 +1,65 @@
+/* Check if CPU has some minimum CPUID bits
+   This runs in 16bit mode so that the caller can still use the BIOS
+   to output errors on the screen */
+#include <asm/cpufeature.h>
+
+verify_cpu:
+       pushfl                          # Save caller passed flags
+       pushl   $0                      # Kill any dangerous flags
+       popfl
+
+#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4
+       pushfl
+       orl     $(1<<18),(%esp)         # try setting AC
+       popfl
+       pushfl
+       popl    %eax
+       testl   $(1<<18),%eax
+       jz      bad
+#endif
+#if REQUIRED_MASK1 != 0
+       pushfl                          # standard way to check for cpuid
+       popl    %eax
+       movl    %eax,%ebx
+       xorl    $0x200000,%eax
+       pushl   %eax
+       popfl
+       pushfl
+       popl    %eax
+       cmpl    %eax,%ebx
+       pushfl                          # standard way to check for cpuid
+       popl    %eax
+       movl    %eax,%ebx
+       xorl    $0x200000,%eax
+       pushl   %eax
+       popfl
+       pushfl
+       popl    %eax
+       cmpl    %eax,%ebx
+       jz      bad                     # REQUIRED_MASK1 != 0 requires CPUID
+
+       movl    $0x0,%eax               # See if cpuid 1 is implemented
+       cpuid
+       cmpl    $0x1,%eax
+       jb      bad                     # no cpuid 1
+
+       movl    $0x1,%eax               # Does the cpu have what it takes
+       cpuid
+
+#if CONFIG_X86_MINIMUM_CPU_MODEL > 4
+#error add proper model checking here
+#endif
+
+       andl    $REQUIRED_MASK1,%edx
+       xorl    $REQUIRED_MASK1,%edx
+       jnz     bad
+#endif /* REQUIRED_MASK1 */
+
+       popfl
+       xor     %eax,%eax
+       ret
+
+bad:
+       popfl
+       movl    $1,%eax
+       ret
index 697a70e..c8726c4 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/cpu.h>
 #include <linux/bootmem.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <asm/vmi.h>
 #include <asm/io.h>
 #include <asm/fixmap.h>
@@ -56,7 +57,7 @@ static int disable_noidle;
 static int disable_vmi_timer;
 
 /* Cached VMI operations */
-struct {
+static struct {
        void (*cpuid)(void /* non-c */);
        void (*_set_ldt)(u32 selector);
        void (*set_tr)(u32 selector);
@@ -65,16 +66,15 @@ struct {
        void (*release_page)(u32, u32);
        void (*set_pte)(pte_t, pte_t *, unsigned);
        void (*update_pte)(pte_t *, unsigned);
-       void (*set_linear_mapping)(int, u32, u32, u32);
-       void (*flush_tlb)(int);
+       void (*set_linear_mapping)(int, void *, u32, u32);
+       void (*_flush_tlb)(int);
        void (*set_initial_ap_state)(int, int);
        void (*halt)(void);
        void (*set_lazy_mode)(int mode);
 } vmi_ops;
 
-/* XXX move this to alternative.h */
-extern struct paravirt_patch __start_parainstructions[],
-       __stop_parainstructions[];
+/* Cached VMI operations */
+struct vmi_timer_ops vmi_timer_ops;
 
 /*
  * VMI patching routines.
@@ -83,11 +83,6 @@ extern struct paravirt_patch __start_parainstructions[],
 #define MNEM_JMP  0xe9
 #define MNEM_RET  0xc3
 
-static char irq_save_disable_callout[] = {
-       MNEM_CALL, 0, 0, 0, 0,
-       MNEM_CALL, 0, 0, 0, 0,
-       MNEM_RET
-};
 #define IRQ_PATCH_INT_MASK 0
 #define IRQ_PATCH_DISABLE  5
 
@@ -135,33 +130,17 @@ static unsigned patch_internal(int call, unsigned len, void *insns)
 static unsigned vmi_patch(u8 type, u16 clobbers, void *insns, unsigned len)
 {
        switch (type) {
-               case PARAVIRT_IRQ_DISABLE:
+               case PARAVIRT_PATCH(irq_disable):
                        return patch_internal(VMI_CALL_DisableInterrupts, len, insns);
-               case PARAVIRT_IRQ_ENABLE:
+               case PARAVIRT_PATCH(irq_enable):
                        return patch_internal(VMI_CALL_EnableInterrupts, len, insns);
-               case PARAVIRT_RESTORE_FLAGS:
+               case PARAVIRT_PATCH(restore_fl):
                        return patch_internal(VMI_CALL_SetInterruptMask, len, insns);
-               case PARAVIRT_SAVE_FLAGS:
+               case PARAVIRT_PATCH(save_fl):
                        return patch_internal(VMI_CALL_GetInterruptMask, len, insns);
-               case PARAVIRT_SAVE_FLAGS_IRQ_DISABLE:
-                       if (len >= 10) {
-                               patch_internal(VMI_CALL_GetInterruptMask, len, insns);
-                               patch_internal(VMI_CALL_DisableInterrupts, len-5, insns+5);
-                               return 10;
-                       } else {
-                               /*
-                                * You bastards didn't leave enough room to
-                                * patch save_flags_irq_disable inline.  Patch
-                                * to a helper
-                                */
-                               BUG_ON(len < 5);
-                               *(char *)insns = MNEM_CALL;
-                               patch_offset(insns, irq_save_disable_callout);
-                               return 5;
-                       }
-               case PARAVIRT_INTERRUPT_RETURN:
+               case PARAVIRT_PATCH(iret):
                        return patch_internal(VMI_CALL_IRET, len, insns);
-               case PARAVIRT_STI_SYSEXIT:
+               case PARAVIRT_PATCH(irq_enable_sysexit):
                        return patch_internal(VMI_CALL_SYSEXIT, len, insns);
                default:
                        break;
@@ -230,24 +209,24 @@ static void vmi_set_tr(void)
 static void vmi_load_esp0(struct tss_struct *tss,
                                   struct thread_struct *thread)
 {
-       tss->esp0 = thread->esp0;
+       tss->x86_tss.esp0 = thread->esp0;
 
        /* This can only happen when SEP is enabled, no need to test "SEP"arately */
-       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
-               tss->ss1 = thread->sysenter_cs;
+       if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
+               tss->x86_tss.ss1 = thread->sysenter_cs;
                wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
        }
-       vmi_ops.set_kernel_stack(__KERNEL_DS, tss->esp0);
+       vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.esp0);
 }
 
 static void vmi_flush_tlb_user(void)
 {
-       vmi_ops.flush_tlb(VMI_FLUSH_TLB);
+       vmi_ops._flush_tlb(VMI_FLUSH_TLB);
 }
 
 static void vmi_flush_tlb_kernel(void)
 {
-       vmi_ops.flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
+       vmi_ops._flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
 }
 
 /* Stub to do nothing at all; used for delays and unimplemented calls */
@@ -255,18 +234,6 @@ static void vmi_nop(void)
 {
 }
 
-/* For NO_IDLE_HZ, we stop the clock when halting the kernel */
-static fastcall void vmi_safe_halt(void)
-{
-       int idle = vmi_stop_hz_timer();
-       vmi_ops.halt();
-       if (idle) {
-               local_irq_disable();
-               vmi_account_time_restart_hz_timer();
-               local_irq_enable();
-       }
-}
-
 #ifdef CONFIG_DEBUG_PAGE_TYPE
 
 #ifdef CONFIG_X86_PAE
@@ -370,8 +337,11 @@ static void vmi_check_page_type(u32 pfn, int type)
 #define vmi_check_page_type(p,t) do { } while (0)
 #endif
 
-static void vmi_map_pt_hook(int type, pte_t *va, u32 pfn)
+#ifdef CONFIG_HIGHPTE
+static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type)
 {
+       void *va = kmap_atomic(page, type);
+
        /*
         * Internally, the VMI ROM must map virtual addresses to physical
         * addresses for processing MMU updates.  By the time MMU updates
@@ -385,8 +355,11 @@ static void vmi_map_pt_hook(int type, pte_t *va, u32 pfn)
         *  args:                 SLOT                 VA    COUNT PFN
         */
        BUG_ON(type != KM_PTE0 && type != KM_PTE1);
-       vmi_ops.set_linear_mapping((type - KM_PTE0)+1, (u32)va, 1, pfn);
+       vmi_ops.set_linear_mapping((type - KM_PTE0)+1, va, 1, page_to_pfn(page));
+
+       return va;
 }
+#endif
 
 static void vmi_allocate_pt(u32 pfn)
 {
@@ -443,13 +416,13 @@ static void vmi_release_pd(u32 pfn)
         ((level) | (is_current_as(mm, user) ?                           \
                 (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
 
-static void vmi_update_pte(struct mm_struct *mm, u32 addr, pte_t *ptep)
+static void vmi_update_pte(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
        vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
 }
 
-static void vmi_update_pte_defer(struct mm_struct *mm, u32 addr, pte_t *ptep)
+static void vmi_update_pte_defer(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
        vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0));
@@ -462,7 +435,7 @@ static void vmi_set_pte(pte_t *ptep, pte_t pte)
        vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT);
 }
 
-static void vmi_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
+static void vmi_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
 {
        vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
        vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
@@ -516,7 +489,7 @@ static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
        vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
 }
 
-void vmi_pmd_clear(pmd_t *pmd)
+static void vmi_pmd_clear(pmd_t *pmd)
 {
        const pte_t pte = { 0 };
        vmi_check_page_type(__pa(pmd) >> PAGE_SHIFT, VMI_PAGE_PMD);
@@ -525,8 +498,6 @@ void vmi_pmd_clear(pmd_t *pmd)
 #endif
 
 #ifdef CONFIG_SMP
-extern void setup_pda(void);
-
 static void __devinit
 vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
                     unsigned long start_esp)
@@ -551,13 +522,11 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
 
        ap.ds = __USER_DS;
        ap.es = __USER_DS;
-       ap.fs = __KERNEL_PDA;
+       ap.fs = __KERNEL_PERCPU;
        ap.gs = 0;
 
        ap.eflags = 0;
 
-       setup_pda();
-
 #ifdef CONFIG_X86_PAE
        /* efer should match BSP efer. */
        if (cpu_has_nx) {
@@ -575,9 +544,9 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
 }
 #endif
 
-static void vmi_set_lazy_mode(int mode)
+static void vmi_set_lazy_mode(enum paravirt_lazy_mode mode)
 {
-       static DEFINE_PER_CPU(int, lazy_mode);
+       static DEFINE_PER_CPU(enum paravirt_lazy_mode, lazy_mode);
 
        if (!vmi_ops.set_lazy_mode)
                return;
@@ -685,7 +654,7 @@ void vmi_bringup(void)
 {
        /* We must establish the lowmem mapping for MMU ops to work */
        if (vmi_ops.set_linear_mapping)
-               vmi_ops.set_linear_mapping(0, __PAGE_OFFSET, max_low_pfn, 0);
+               vmi_ops.set_linear_mapping(0, (void *)__PAGE_OFFSET, max_low_pfn, 0);
 }
 
 /*
@@ -740,7 +709,6 @@ do {                                                                \
        }                                                       \
 } while (0)
 
-
 /*
  * Activate the VMI interface and switch into paravirtualized mode
  */
@@ -796,12 +764,6 @@ static inline int __init activate_vmi(void)
        para_fill(irq_disable, DisableInterrupts);
        para_fill(irq_enable, EnableInterrupts);
 
-       /* irq_save_disable !!! sheer pain */
-       patch_offset(&irq_save_disable_callout[IRQ_PATCH_INT_MASK],
-                    (char *)paravirt_ops.save_fl);
-       patch_offset(&irq_save_disable_callout[IRQ_PATCH_DISABLE],
-                    (char *)paravirt_ops.irq_disable);
-
        para_fill(wbinvd, WBINVD);
        para_fill(read_tsc, RDTSC);
 
@@ -831,8 +793,8 @@ static inline int __init activate_vmi(void)
        para_wrap(set_lazy_mode, vmi_set_lazy_mode, set_lazy_mode, SetLazyMode);
 
        /* user and kernel flush are just handled with different flags to FlushTLB */
-       para_wrap(flush_tlb_user, vmi_flush_tlb_user, flush_tlb, FlushTLB);
-       para_wrap(flush_tlb_kernel, vmi_flush_tlb_kernel, flush_tlb, FlushTLB);
+       para_wrap(flush_tlb_user, vmi_flush_tlb_user, _flush_tlb, FlushTLB);
+       para_wrap(flush_tlb_kernel, vmi_flush_tlb_kernel, _flush_tlb, FlushTLB);
        para_fill(flush_tlb_single, InvalPage);
 
        /*
@@ -878,8 +840,13 @@ static inline int __init activate_vmi(void)
                paravirt_ops.release_pt = vmi_release_pt;
                paravirt_ops.release_pd = vmi_release_pd;
        }
-       para_wrap(map_pt_hook, vmi_map_pt_hook, set_linear_mapping,
-                 SetLinearMapping);
+
+       /* Set linear is needed in all cases */
+       vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
+#ifdef CONFIG_HIGHPTE
+       if (vmi_ops.set_linear_mapping)
+               paravirt_ops.kmap_atomic_pte = vmi_kmap_atomic_pte;
+#endif
 
        /*
         * These MUST always be patched.  Don't support indirect jumps
@@ -920,8 +887,8 @@ static inline int __init activate_vmi(void)
                paravirt_ops.get_wallclock = vmi_get_wallclock;
                paravirt_ops.set_wallclock = vmi_set_wallclock;
 #ifdef CONFIG_X86_LOCAL_APIC
-               paravirt_ops.setup_boot_clock = vmi_timer_setup_boot_alarm;
-               paravirt_ops.setup_secondary_clock = vmi_timer_setup_secondary_alarm;
+               paravirt_ops.setup_boot_clock = vmi_time_bsp_init;
+               paravirt_ops.setup_secondary_clock = vmi_time_ap_init;
 #endif
                paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles;
                paravirt_ops.get_cpu_khz = vmi_cpu_khz;
@@ -933,11 +900,7 @@ static inline int __init activate_vmi(void)
                disable_vmi_timer = 1;
        }
 
-       /* No idle HZ mode only works if VMI timer and no idle is enabled */
-       if (disable_noidle || disable_vmi_timer)
-               para_fill(safe_halt, Halt);
-       else
-               para_wrap(safe_halt, vmi_safe_halt, halt, Halt);
+       para_fill(safe_halt, Halt);
 
        /*
         * Alternative instruction rewriting doesn't happen soon enough
@@ -945,7 +908,7 @@ static inline int __init activate_vmi(void)
         * to do this before IRQs get reenabled.  Fortunately, it is
         * idempotent.
         */
-       apply_paravirt(__start_parainstructions, __stop_parainstructions);
+       apply_paravirt(__parainstructions, __parainstructions_end);
 
        vmi_bringup();
 
diff --git a/arch/i386/kernel/vmiclock.c b/arch/i386/kernel/vmiclock.c
new file mode 100644 (file)
index 0000000..26a37f8
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * VMI paravirtual timer support routines.
+ *
+ * Copyright (C) 2007, VMware, 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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/smp.h>
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
+#include <asm/vmi.h>
+#include <asm/vmi_time.h>
+#include <asm/arch_hooks.h>
+#include <asm/apicdef.h>
+#include <asm/apic.h>
+#include <asm/timer.h>
+
+#include <irq_vectors.h>
+#include "io_ports.h"
+
+#define VMI_ONESHOT  (VMI_ALARM_IS_ONESHOT  | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
+#define VMI_PERIODIC (VMI_ALARM_IS_PERIODIC | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
+
+static DEFINE_PER_CPU(struct clock_event_device, local_events);
+
+static inline u32 vmi_counter(u32 flags)
+{
+       /* Given VMI_ONESHOT or VMI_PERIODIC, return the corresponding
+        * cycle counter. */
+       return flags & VMI_ALARM_COUNTER_MASK;
+}
+
+/* paravirt_ops.get_wallclock = vmi_get_wallclock */
+unsigned long vmi_get_wallclock(void)
+{
+       unsigned long long wallclock;
+       wallclock = vmi_timer_ops.get_wallclock(); // nsec
+       (void)do_div(wallclock, 1000000000);       // sec
+
+       return wallclock;
+}
+
+/* paravirt_ops.set_wallclock = vmi_set_wallclock */
+int vmi_set_wallclock(unsigned long now)
+{
+       return 0;
+}
+
+/* paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles */
+unsigned long long vmi_get_sched_cycles(void)
+{
+       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE);
+}
+
+/* paravirt_ops.get_cpu_khz = vmi_cpu_khz */
+unsigned long vmi_cpu_khz(void)
+{
+       unsigned long long khz;
+       khz = vmi_timer_ops.get_cycle_frequency();
+       (void)do_div(khz, 1000);
+       return khz;
+}
+
+static inline unsigned int vmi_get_timer_vector(void)
+{
+#ifdef CONFIG_X86_IO_APIC
+       return FIRST_DEVICE_VECTOR;
+#else
+       return FIRST_EXTERNAL_VECTOR;
+#endif
+}
+
+/** vmi clockchip */
+#ifdef CONFIG_X86_LOCAL_APIC
+static unsigned int startup_timer_irq(unsigned int irq)
+{
+       unsigned long val = apic_read(APIC_LVTT);
+       apic_write(APIC_LVTT, vmi_get_timer_vector());
+
+       return (val & APIC_SEND_PENDING);
+}
+
+static void mask_timer_irq(unsigned int irq)
+{
+       unsigned long val = apic_read(APIC_LVTT);
+       apic_write(APIC_LVTT, val | APIC_LVT_MASKED);
+}
+
+static void unmask_timer_irq(unsigned int irq)
+{
+       unsigned long val = apic_read(APIC_LVTT);
+       apic_write(APIC_LVTT, val & ~APIC_LVT_MASKED);
+}
+
+static void ack_timer_irq(unsigned int irq)
+{
+       ack_APIC_irq();
+}
+
+static struct irq_chip vmi_chip __read_mostly = {
+       .name           = "VMI-LOCAL",
+       .startup        = startup_timer_irq,
+       .mask           = mask_timer_irq,
+       .unmask         = unmask_timer_irq,
+       .ack            = ack_timer_irq
+};
+#endif
+
+/** vmi clockevent */
+#define VMI_ALARM_WIRED_IRQ0    0x00000000
+#define VMI_ALARM_WIRED_LVTT    0x00010000
+static int vmi_wiring = VMI_ALARM_WIRED_IRQ0;
+
+static inline int vmi_get_alarm_wiring(void)
+{
+       return vmi_wiring;
+}
+
+static void vmi_timer_set_mode(enum clock_event_mode mode,
+                              struct clock_event_device *evt)
+{
+       cycle_t now, cycles_per_hz;
+       BUG_ON(!irqs_disabled());
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_ONESHOT:
+               break;
+       case CLOCK_EVT_MODE_PERIODIC:
+               cycles_per_hz = vmi_timer_ops.get_cycle_frequency();
+               (void)do_div(cycles_per_hz, HZ);
+               now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_PERIODIC));
+               vmi_timer_ops.set_alarm(VMI_PERIODIC, now, cycles_per_hz);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               switch (evt->mode) {
+               case CLOCK_EVT_MODE_ONESHOT:
+                       vmi_timer_ops.cancel_alarm(VMI_ONESHOT);
+                       break;
+               case CLOCK_EVT_MODE_PERIODIC:
+                       vmi_timer_ops.cancel_alarm(VMI_PERIODIC);
+                       break;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static int vmi_timer_next_event(unsigned long delta,
+                               struct clock_event_device *evt)
+{
+       /* Unfortunately, set_next_event interface only passes relative
+        * expiry, but we want absolute expiry.  It'd be better if were
+        * were passed an aboslute expiry, since a bunch of time may
+        * have been stolen between the time the delta is computed and
+        * when we set the alarm below. */
+       cycle_t now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_ONESHOT));
+
+       BUG_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
+       vmi_timer_ops.set_alarm(VMI_ONESHOT, now + delta, 0);
+       return 0;
+}
+
+static struct clock_event_device vmi_clockevent = {
+       .name           = "vmi-timer",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 22,
+       .set_mode       = vmi_timer_set_mode,
+       .set_next_event = vmi_timer_next_event,
+       .rating         = 1000,
+       .irq            = 0,
+};
+
+static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = &__get_cpu_var(local_events);
+       evt->event_handler(evt);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction vmi_clock_action  = {
+       .name           = "vmi-timer",
+       .handler        = vmi_timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_NOBALANCING,
+       .mask           = CPU_MASK_ALL,
+};
+
+static void __devinit vmi_time_init_clockevent(void)
+{
+       cycle_t cycles_per_msec;
+       struct clock_event_device *evt;
+
+       int cpu = smp_processor_id();
+       evt = &__get_cpu_var(local_events);
+
+       /* Use cycles_per_msec since div_sc params are 32-bits. */
+       cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
+       (void)do_div(cycles_per_msec, 1000);
+
+       memcpy(evt, &vmi_clockevent, sizeof(*evt));
+       /* Must pick .shift such that .mult fits in 32-bits.  Choosing
+        * .shift to be 22 allows 2^(32-22) cycles per nano-seconds
+        * before overflow. */
+       evt->mult = div_sc(cycles_per_msec, NSEC_PER_MSEC, evt->shift);
+       /* Upper bound is clockevent's use of ulong for cycle deltas. */
+       evt->max_delta_ns = clockevent_delta2ns(ULONG_MAX, evt);
+       evt->min_delta_ns = clockevent_delta2ns(1, evt);
+       evt->cpumask = cpumask_of_cpu(cpu);
+
+       printk(KERN_WARNING "vmi: registering clock event %s. mult=%lu shift=%u\n",
+              evt->name, evt->mult, evt->shift);
+       clockevents_register_device(evt);
+}
+
+void __init vmi_time_init(void)
+{
+       /* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */
+       outb_p(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
+
+       vmi_time_init_clockevent();
+       setup_irq(0, &vmi_clock_action);
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+void __devinit vmi_time_bsp_init(void)
+{
+       /*
+        * On APIC systems, we want local timers to fire on each cpu.  We do
+        * this by programming LVTT to deliver timer events to the IRQ handler
+        * for IRQ-0, since we can't re-use the APIC local timer handler
+        * without interfering with that code.
+        */
+       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+       local_irq_disable();
+#ifdef CONFIG_X86_SMP
+       /*
+        * XXX handle_percpu_irq only defined for SMP; we need to switch over
+        * to using it, since this is a local interrupt, which each CPU must
+        * handle individually without locking out or dropping simultaneous
+        * local timers on other CPUs.  We also don't want to trigger the
+        * quirk workaround code for interrupts which gets invoked from
+        * handle_percpu_irq via eoi, so we use our own IRQ chip.
+        */
+       set_irq_chip_and_handler_name(0, &vmi_chip, handle_percpu_irq, "lvtt");
+#else
+       set_irq_chip_and_handler_name(0, &vmi_chip, handle_edge_irq, "lvtt");
+#endif
+       vmi_wiring = VMI_ALARM_WIRED_LVTT;
+       apic_write(APIC_LVTT, vmi_get_timer_vector());
+       local_irq_enable();
+       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
+}
+
+void __devinit vmi_time_ap_init(void)
+{
+       vmi_time_init_clockevent();
+       apic_write(APIC_LVTT, vmi_get_timer_vector());
+}
+#endif
+
+/** vmi clocksource */
+
+static cycle_t read_real_cycles(void)
+{
+       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+}
+
+static struct clocksource clocksource_vmi = {
+       .name                   = "vmi-timer",
+       .rating                 = 450,
+       .read                   = read_real_cycles,
+       .mask                   = CLOCKSOURCE_MASK(64),
+       .mult                   = 0, /* to be set */
+       .shift                  = 22,
+       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init init_vmi_clocksource(void)
+{
+       cycle_t cycles_per_msec;
+
+       if (!vmi_timer_ops.get_cycle_frequency)
+               return 0;
+       /* Use khz2mult rather than hz2mult since hz arg is only 32-bits. */
+       cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
+       (void)do_div(cycles_per_msec, 1000);
+
+       /* Note that clocksource.{mult, shift} converts in the opposite direction
+        * as clockevents.  */
+       clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
+                                                   clocksource_vmi.shift);
+
+       printk(KERN_WARNING "vmi: registering clock source khz=%lld\n", cycles_per_msec);
+       return clocksource_register(&clocksource_vmi);
+
+}
+module_init(init_vmi_clocksource);
diff --git a/arch/i386/kernel/vmitime.c b/arch/i386/kernel/vmitime.c
deleted file mode 100644 (file)
index 9dfb177..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * VMI paravirtual timer support routines.
- *
- * Copyright (C) 2005, VMware, 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, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to dhecht@vmware.com
- *
- */
-
-/*
- * Portions of this code from arch/i386/kernel/timers/timer_tsc.c.
- * Portions of the CONFIG_NO_IDLE_HZ code from arch/s390/kernel/time.c.
- * See comments there for proper credits.
- */
-
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/jiffies.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/rcupdate.h>
-#include <linux/clocksource.h>
-
-#include <asm/timer.h>
-#include <asm/io.h>
-#include <asm/apic.h>
-#include <asm/div64.h>
-#include <asm/timer.h>
-#include <asm/desc.h>
-
-#include <asm/vmi.h>
-#include <asm/vmi_time.h>
-
-#include <mach_timer.h>
-#include <io_ports.h>
-
-#ifdef CONFIG_X86_LOCAL_APIC
-#define VMI_ALARM_WIRING VMI_ALARM_WIRED_LVTT
-#else
-#define VMI_ALARM_WIRING VMI_ALARM_WIRED_IRQ0
-#endif
-
-/* Cached VMI operations */
-struct vmi_timer_ops vmi_timer_ops;
-
-#ifdef CONFIG_NO_IDLE_HZ
-
-/* /proc/sys/kernel/hz_timer state. */
-int sysctl_hz_timer;
-
-/* Some stats */
-static DEFINE_PER_CPU(unsigned long, vmi_idle_no_hz_irqs);
-static DEFINE_PER_CPU(unsigned long, vmi_idle_no_hz_jiffies);
-static DEFINE_PER_CPU(unsigned long, idle_start_jiffies);
-
-#endif /* CONFIG_NO_IDLE_HZ */
-
-/* Number of alarms per second. By default this is CONFIG_VMI_ALARM_HZ. */
-static int alarm_hz = CONFIG_VMI_ALARM_HZ;
-
-/* Cache of the value get_cycle_frequency / HZ. */
-static signed long long cycles_per_jiffy;
-
-/* Cache of the value get_cycle_frequency / alarm_hz. */
-static signed long long cycles_per_alarm;
-
-/* The number of cycles accounted for by the 'jiffies'/'xtime' count.
- * Protected by xtime_lock. */
-static unsigned long long real_cycles_accounted_system;
-
-/* The number of cycles accounted for by update_process_times(), per cpu. */
-static DEFINE_PER_CPU(unsigned long long, process_times_cycles_accounted_cpu);
-
-/* The number of stolen cycles accounted, per cpu. */
-static DEFINE_PER_CPU(unsigned long long, stolen_cycles_accounted_cpu);
-
-/* Clock source. */
-static cycle_t read_real_cycles(void)
-{
-       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
-}
-
-static cycle_t read_available_cycles(void)
-{
-       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE);
-}
-
-#if 0
-static cycle_t read_stolen_cycles(void)
-{
-       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_STOLEN);
-}
-#endif  /*  0  */
-
-static struct clocksource clocksource_vmi = {
-       .name                   = "vmi-timer",
-       .rating                 = 450,
-       .read                   = read_real_cycles,
-       .mask                   = CLOCKSOURCE_MASK(64),
-       .mult                   = 0, /* to be set */
-       .shift                  = 22,
-       .flags                  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
-/* Timer interrupt handler. */
-static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id);
-
-static struct irqaction vmi_timer_irq  = {
-       .handler = vmi_timer_interrupt,
-       .flags = IRQF_DISABLED,
-       .mask = CPU_MASK_NONE,
-       .name = "VMI-alarm",
-};
-
-/* Alarm rate */
-static int __init vmi_timer_alarm_rate_setup(char* str)
-{
-       int alarm_rate;
-       if (get_option(&str, &alarm_rate) == 1 && alarm_rate > 0) {
-               alarm_hz = alarm_rate;
-               printk(KERN_WARNING "VMI timer alarm HZ set to %d\n", alarm_hz);
-       }
-       return 1;
-}
-__setup("vmi_timer_alarm_hz=", vmi_timer_alarm_rate_setup);
-
-
-/* Initialization */
-static void vmi_get_wallclock_ts(struct timespec *ts)
-{
-       unsigned long long wallclock;
-       wallclock = vmi_timer_ops.get_wallclock(); // nsec units
-       ts->tv_nsec = do_div(wallclock, 1000000000);
-       ts->tv_sec = wallclock;
-}
-
-unsigned long vmi_get_wallclock(void)
-{
-       struct timespec ts;
-       vmi_get_wallclock_ts(&ts);
-       return ts.tv_sec;
-}
-
-int vmi_set_wallclock(unsigned long now)
-{
-       return -1;
-}
-
-unsigned long long vmi_get_sched_cycles(void)
-{
-       return read_available_cycles();
-}
-
-unsigned long vmi_cpu_khz(void)
-{
-       unsigned long long khz;
-
-       khz = vmi_timer_ops.get_cycle_frequency();
-       (void)do_div(khz, 1000);
-       return khz;
-}
-
-void __init vmi_time_init(void)
-{
-       unsigned long long cycles_per_sec, cycles_per_msec;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       setup_irq(0, &vmi_timer_irq);
-#ifdef CONFIG_X86_LOCAL_APIC
-       set_intr_gate(LOCAL_TIMER_VECTOR, apic_vmi_timer_interrupt);
-#endif
-
-       real_cycles_accounted_system = read_real_cycles();
-       per_cpu(process_times_cycles_accounted_cpu, 0) = read_available_cycles();
-
-       cycles_per_sec = vmi_timer_ops.get_cycle_frequency();
-       cycles_per_jiffy = cycles_per_sec;
-       (void)do_div(cycles_per_jiffy, HZ);
-       cycles_per_alarm = cycles_per_sec;
-       (void)do_div(cycles_per_alarm, alarm_hz);
-       cycles_per_msec = cycles_per_sec;
-       (void)do_div(cycles_per_msec, 1000);
-
-       printk(KERN_WARNING "VMI timer cycles/sec = %llu ; cycles/jiffy = %llu ;"
-              "cycles/alarm = %llu\n", cycles_per_sec, cycles_per_jiffy,
-              cycles_per_alarm);
-
-       clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
-                                                   clocksource_vmi.shift);
-       if (clocksource_register(&clocksource_vmi))
-               printk(KERN_WARNING "Error registering VMITIME clocksource.");
-
-       /* Disable PIT. */
-       outb_p(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
-
-       /* schedule the alarm. do this in phase with process_times_cycles_accounted_cpu
-        * reduce the latency calling update_process_times. */
-       vmi_timer_ops.set_alarm(
-                     VMI_ALARM_WIRED_IRQ0 | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
-                     per_cpu(process_times_cycles_accounted_cpu, 0) + cycles_per_alarm,
-                     cycles_per_alarm);
-
-       local_irq_restore(flags);
-}
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
-void __init vmi_timer_setup_boot_alarm(void)
-{
-       local_irq_disable();
-
-       /* Route the interrupt to the correct vector. */
-       apic_write_around(APIC_LVTT, LOCAL_TIMER_VECTOR);
-
-       /* Cancel the IRQ0 wired alarm, and setup the LVTT alarm. */
-       vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
-       vmi_timer_ops.set_alarm(
-                     VMI_ALARM_WIRED_LVTT | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
-                     per_cpu(process_times_cycles_accounted_cpu, 0) + cycles_per_alarm,
-                     cycles_per_alarm);
-       local_irq_enable();
-}
-
-/* Initialize the time accounting variables for an AP on an SMP system.
- * Also, set the local alarm for the AP. */
-void __devinit vmi_timer_setup_secondary_alarm(void)
-{
-       int cpu = smp_processor_id();
-
-       /* Route the interrupt to the correct vector. */
-       apic_write_around(APIC_LVTT, LOCAL_TIMER_VECTOR);
-
-       per_cpu(process_times_cycles_accounted_cpu, cpu) = read_available_cycles();
-
-       vmi_timer_ops.set_alarm(
-                     VMI_ALARM_WIRED_LVTT | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
-                     per_cpu(process_times_cycles_accounted_cpu, cpu) + cycles_per_alarm,
-                     cycles_per_alarm);
-}
-
-#endif
-
-/* Update system wide (real) time accounting (e.g. jiffies, xtime). */
-static void vmi_account_real_cycles(unsigned long long cur_real_cycles)
-{
-       long long cycles_not_accounted;
-
-       write_seqlock(&xtime_lock);
-
-       cycles_not_accounted = cur_real_cycles - real_cycles_accounted_system;
-       while (cycles_not_accounted >= cycles_per_jiffy) {
-               /* systems wide jiffies. */
-               do_timer(1);
-
-               cycles_not_accounted -= cycles_per_jiffy;
-               real_cycles_accounted_system += cycles_per_jiffy;
-       }
-
-       write_sequnlock(&xtime_lock);
-}
-
-/* Update per-cpu process times. */
-static void vmi_account_process_times_cycles(struct pt_regs *regs, int cpu,
-                                            unsigned long long cur_process_times_cycles)
-{
-       long long cycles_not_accounted;
-       cycles_not_accounted = cur_process_times_cycles -
-               per_cpu(process_times_cycles_accounted_cpu, cpu);
-
-       while (cycles_not_accounted >= cycles_per_jiffy) {
-               /* Account time to the current process.  This includes
-                * calling into the scheduler to decrement the timeslice
-                * and possibly reschedule.*/
-               update_process_times(user_mode(regs));
-               /* XXX handle /proc/profile multiplier.  */
-               profile_tick(CPU_PROFILING);
-
-               cycles_not_accounted -= cycles_per_jiffy;
-               per_cpu(process_times_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
-       }
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-/* Update per-cpu idle times.  Used when a no-hz halt is ended. */
-static void vmi_account_no_hz_idle_cycles(int cpu,
-                                         unsigned long long cur_process_times_cycles)
-{
-       long long cycles_not_accounted;
-       unsigned long no_idle_hz_jiffies = 0;
-
-       cycles_not_accounted = cur_process_times_cycles -
-               per_cpu(process_times_cycles_accounted_cpu, cpu);
-
-       while (cycles_not_accounted >= cycles_per_jiffy) {
-               no_idle_hz_jiffies++;
-               cycles_not_accounted -= cycles_per_jiffy;
-               per_cpu(process_times_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
-       }
-       /* Account time to the idle process. */
-       account_steal_time(idle_task(cpu), jiffies_to_cputime(no_idle_hz_jiffies));
-}
-#endif
-
-/* Update per-cpu stolen time. */
-static void vmi_account_stolen_cycles(int cpu,
-                                     unsigned long long cur_real_cycles,
-                                     unsigned long long cur_avail_cycles)
-{
-       long long stolen_cycles_not_accounted;
-       unsigned long stolen_jiffies = 0;
-
-       if (cur_real_cycles < cur_avail_cycles)
-               return;
-
-       stolen_cycles_not_accounted = cur_real_cycles - cur_avail_cycles -
-               per_cpu(stolen_cycles_accounted_cpu, cpu);
-
-       while (stolen_cycles_not_accounted >= cycles_per_jiffy) {
-               stolen_jiffies++;
-               stolen_cycles_not_accounted -= cycles_per_jiffy;
-               per_cpu(stolen_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
-       }
-       /* HACK: pass NULL to force time onto cpustat->steal. */
-       account_steal_time(NULL, jiffies_to_cputime(stolen_jiffies));
-}
-
-/* Body of either IRQ0 interrupt handler (UP no local-APIC) or
- * local-APIC LVTT interrupt handler (UP & local-APIC or SMP). */
-static void vmi_local_timer_interrupt(int cpu)
-{
-       unsigned long long cur_real_cycles, cur_process_times_cycles;
-
-       cur_real_cycles = read_real_cycles();
-       cur_process_times_cycles = read_available_cycles();
-       /* Update system wide (real) time state (xtime, jiffies). */
-       vmi_account_real_cycles(cur_real_cycles);
-       /* Update per-cpu process times. */
-       vmi_account_process_times_cycles(get_irq_regs(), cpu, cur_process_times_cycles);
-        /* Update time stolen from this cpu by the hypervisor. */
-       vmi_account_stolen_cycles(cpu, cur_real_cycles, cur_process_times_cycles);
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-
-/* Must be called only from idle loop, with interrupts disabled. */
-int vmi_stop_hz_timer(void)
-{
-       /* Note that cpu_set, cpu_clear are (SMP safe) atomic on x86. */
-
-       unsigned long seq, next;
-       unsigned long long real_cycles_expiry;
-       int cpu = smp_processor_id();
-
-       BUG_ON(!irqs_disabled());
-       if (sysctl_hz_timer != 0)
-               return 0;
-
-       cpu_set(cpu, nohz_cpu_mask);
-       smp_mb();
-
-       if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
-           (next = next_timer_interrupt(),
-            time_before_eq(next, jiffies + HZ/CONFIG_VMI_ALARM_HZ))) {
-               cpu_clear(cpu, nohz_cpu_mask);
-               return 0;
-       }
-
-       /* Convert jiffies to the real cycle counter. */
-       do {
-               seq = read_seqbegin(&xtime_lock);
-               real_cycles_expiry = real_cycles_accounted_system +
-                       (long)(next - jiffies) * cycles_per_jiffy;
-       } while (read_seqretry(&xtime_lock, seq));
-
-       /* This cpu is going idle. Disable the periodic alarm. */
-       vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
-       per_cpu(idle_start_jiffies, cpu) = jiffies;
-       /* Set the real time alarm to expire at the next event. */
-       vmi_timer_ops.set_alarm(
-               VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL,
-               real_cycles_expiry, 0);
-       return 1;
-}
-
-static void vmi_reenable_hz_timer(int cpu)
-{
-       /* For /proc/vmi/info idle_hz stat. */
-       per_cpu(vmi_idle_no_hz_jiffies, cpu) += jiffies - per_cpu(idle_start_jiffies, cpu);
-       per_cpu(vmi_idle_no_hz_irqs, cpu)++;
-
-       /* Don't bother explicitly cancelling the one-shot alarm -- at
-        * worse we will receive a spurious timer interrupt. */
-       vmi_timer_ops.set_alarm(
-                     VMI_ALARM_WIRING | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
-                     per_cpu(process_times_cycles_accounted_cpu, cpu) + cycles_per_alarm,
-                     cycles_per_alarm);
-       /* Indicate this cpu is no longer nohz idle. */
-       cpu_clear(cpu, nohz_cpu_mask);
-}
-
-/* Called from interrupt handlers when (local) HZ timer is disabled. */
-void vmi_account_time_restart_hz_timer(void)
-{
-       unsigned long long cur_real_cycles, cur_process_times_cycles;
-       int cpu = smp_processor_id();
-
-       BUG_ON(!irqs_disabled());
-       /* Account the time during which the HZ timer was disabled. */
-       cur_real_cycles = read_real_cycles();
-       cur_process_times_cycles = read_available_cycles();
-       /* Update system wide (real) time state (xtime, jiffies). */
-       vmi_account_real_cycles(cur_real_cycles);
-       /* Update per-cpu idle times. */
-       vmi_account_no_hz_idle_cycles(cpu, cur_process_times_cycles);
-        /* Update time stolen from this cpu by the hypervisor. */
-       vmi_account_stolen_cycles(cpu, cur_real_cycles, cur_process_times_cycles);
-       /* Reenable the hz timer. */
-       vmi_reenable_hz_timer(cpu);
-}
-
-#endif /* CONFIG_NO_IDLE_HZ */
-
-/* UP (and no local-APIC) VMI-timer alarm interrupt handler.
- * Handler for IRQ0. Not used when SMP or X86_LOCAL_APIC after
- * APIC setup and setup_boot_vmi_alarm() is called.  */
-static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
-{
-       vmi_local_timer_interrupt(smp_processor_id());
-       return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
-/* SMP VMI-timer alarm interrupt handler. Handler for LVTT vector.
- * Also used in UP when CONFIG_X86_LOCAL_APIC.
- * The wrapper code is from arch/i386/kernel/apic.c#smp_apic_timer_interrupt. */
-void smp_apic_vmi_timer_interrupt(struct pt_regs *regs)
-{
-       struct pt_regs *old_regs = set_irq_regs(regs);
-       int cpu = smp_processor_id();
-
-       /*
-        * the NMI deadlock-detector uses this.
-        */
-        per_cpu(irq_stat,cpu).apic_timer_irqs++;
-
-       /*
-        * NOTE! We'd better ACK the irq immediately,
-        * because timer handling can be slow.
-        */
-       ack_APIC_irq();
-
-       /*
-        * update_process_times() expects us to have done irq_enter().
-        * Besides, if we don't timer interrupts ignore the global
-        * interrupt lock, which is the WrongThing (tm) to do.
-        */
-       irq_enter();
-       vmi_local_timer_interrupt(cpu);
-       irq_exit();
-       set_irq_regs(old_regs);
-}
-
-#endif  /* CONFIG_X86_LOCAL_APIC */
index 6f38f81..23e8614 100644 (file)
@@ -26,12 +26,11 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
 ENTRY(phys_startup_32)
 jiffies = jiffies_64;
-_proxy_pda = 1;
 
 PHDRS {
        text PT_LOAD FLAGS(5);  /* R_E */
        data PT_LOAD FLAGS(7);  /* RWE */
-       note PT_NOTE FLAGS(4);  /* R__ */
+       note PT_NOTE FLAGS(0);  /* ___ */
 }
 SECTIONS
 {
@@ -61,8 +60,6 @@ SECTIONS
        __stop___ex_table = .;
   }
 
-  RODATA
-
   BUG_TABLE
 
   . = ALIGN(4);
@@ -72,6 +69,8 @@ SECTIONS
        __tracedata_end = .;
   }
 
+  RODATA
+
   /* writeable */
   . = ALIGN(4096);
   .data : AT(ADDR(.data) - LOAD_OFFSET) {      /* Data */
@@ -117,22 +116,11 @@ SECTIONS
 
   /* might get freed after init */
   . = ALIGN(4096);
-  .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) {
-       __smp_alt_begin = .;
-       __smp_alt_instructions = .;
-       *(.smp_altinstructions)
-       __smp_alt_instructions_end = .;
-  }
-  . = ALIGN(4);
   .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
        __smp_locks = .;
        *(.smp_locks)
        __smp_locks_end = .;
   }
-  .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) {
-       *(.smp_altinstr_replacement)
-       __smp_alt_end = .;
-  }
   /* will be freed after init
    * Following ALIGN() is required to make sure no other data falls on the
    * same page where __smp_alt_end is pointing as that page might be freed
@@ -178,9 +166,9 @@ SECTIONS
   }
   . = ALIGN(4);
   .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
-       __start_parainstructions = .;
+       __parainstructions = .;
        *(.parainstructions)
-       __stop_parainstructions = .;
+       __parainstructions_end = .;
   }
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
@@ -194,7 +182,7 @@ SECTIONS
        __initramfs_end = .;
   }
 #endif
-  . = ALIGN(L1_CACHE_BYTES);
+  . = ALIGN(4096);
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
        __per_cpu_start = .;
        *(.data.percpu)
index f66cd11..4a8b0ed 100644 (file)
@@ -7,7 +7,7 @@
 
 SECTIONS
 {
-  . = VDSO_PRELINK + SIZEOF_HEADERS;
+  . = VDSO_PRELINK_asm + SIZEOF_HEADERS;
 
   .hash           : { *(.hash) }               :text
   .gnu.hash       : { *(.gnu.hash) }
@@ -21,7 +21,7 @@ SECTIONS
      For the layouts to match, we need to skip more than enough
      space for the dynamic symbol table et al.  If this amount
      is insufficient, ld -shared will barf.  Just increase it here.  */
-  . = VDSO_PRELINK + 0x400;
+  . = VDSO_PRELINK_asm + 0x400;
 
   .text           : { *(.text) }               :text =0x90909090
   .note                  : { *(.note.*) }              :text :note
index 97db385..afd0045 100644 (file)
@@ -43,7 +43,7 @@ EXPORT_SYMBOL(find_next_bit);
  */
 int find_next_zero_bit(const unsigned long *addr, int size, int offset)
 {
-       unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+       const unsigned long *p = addr + (offset >> 5);
        int set = 0, bit = offset & 31, res;
 
        if (bit) {
@@ -64,7 +64,7 @@ int find_next_zero_bit(const unsigned long *addr, int size, int offset)
        /*
         * No zero yet, search remaining full bytes for a zero
         */
-       res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
+       res = find_first_zero_bit(p, size - 32 * (p - addr));
        return (offset + set + res);
 }
 EXPORT_SYMBOL(find_next_zero_bit);
index 75ffd02..adbccd0 100644 (file)
@@ -25,6 +25,8 @@
  *             2 of the License, or (at your option) any later version.
  */
 
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
 #include <asm/errno.h>
                                
 /*
@@ -36,8 +38,6 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
  */
                
 .text
-.align 4
-.globl csum_partial                                                            
                
 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
 
@@ -48,9 +48,14 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
           * Fortunately, it is easy to convert 2-byte alignment to 4-byte
           * alignment for the unrolled loop.
           */           
-csum_partial:  
+ENTRY(csum_partial)
+       CFI_STARTPROC
        pushl %esi
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET esi, 0
        pushl %ebx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ebx, 0
        movl 20(%esp),%eax      # Function arg: unsigned int sum
        movl 16(%esp),%ecx      # Function arg: int len
        movl 12(%esp),%esi      # Function arg: unsigned char *buff
@@ -128,16 +133,27 @@ csum_partial:
        roll $8, %eax
 8:
        popl %ebx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ebx
        popl %esi
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE esi
        ret
+       CFI_ENDPROC
+ENDPROC(csum_partial)
 
 #else
 
 /* Version for PentiumII/PPro */
 
-csum_partial:
+ENTRY(csum_partial)
+       CFI_STARTPROC
        pushl %esi
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET esi, 0
        pushl %ebx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ebx, 0
        movl 20(%esp),%eax      # Function arg: unsigned int sum
        movl 16(%esp),%ecx      # Function arg: int len
        movl 12(%esp),%esi      # Function arg: const unsigned char *buf
@@ -245,8 +261,14 @@ csum_partial:
        roll $8, %eax
 90: 
        popl %ebx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ebx
        popl %esi
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE esi
        ret
+       CFI_ENDPROC
+ENDPROC(csum_partial)
                                
 #endif
 
@@ -278,19 +300,24 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
        .long 9999b, 6002f      ;       \
        .previous
 
-.align 4
-.globl csum_partial_copy_generic
-                               
 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
 
 #define ARGBASE 16             
 #define FP             12
                
-csum_partial_copy_generic:
+ENTRY(csum_partial_copy_generic)
+       CFI_STARTPROC
        subl  $4,%esp   
+       CFI_ADJUST_CFA_OFFSET 4
        pushl %edi
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edi, 0
        pushl %esi
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET esi, 0
        pushl %ebx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ebx, 0
        movl ARGBASE+16(%esp),%eax      # sum
        movl ARGBASE+12(%esp),%ecx      # len
        movl ARGBASE+4(%esp),%esi       # src
@@ -400,10 +427,19 @@ DST(      movb %cl, (%edi)        )
 .previous
 
        popl %ebx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ebx
        popl %esi
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE esi
        popl %edi
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE edi
        popl %ecx                       # equivalent to addl $4,%esp
+       CFI_ADJUST_CFA_OFFSET -4
        ret     
+       CFI_ENDPROC
+ENDPROC(csum_partial_copy_generic)
 
 #else
 
@@ -421,10 +457,17 @@ DST(      movb %cl, (%edi)        )
 
 #define ARGBASE 12
                
-csum_partial_copy_generic:
+ENTRY(csum_partial_copy_generic)
+       CFI_STARTPROC
        pushl %ebx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ebx, 0
        pushl %edi
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edi, 0
        pushl %esi
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET esi, 0
        movl ARGBASE+4(%esp),%esi       #src
        movl ARGBASE+8(%esp),%edi       #dst    
        movl ARGBASE+12(%esp),%ecx      #len
@@ -485,9 +528,17 @@ DST(       movb %dl, (%edi)         )
 .previous                              
 
        popl %esi
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE esi
        popl %edi
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE edi
        popl %ebx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ebx
        ret
+       CFI_ENDPROC
+ENDPROC(csum_partial_copy_generic)
                                
 #undef ROUND
 #undef ROUND1          
index 62d7f17..6d84b53 100644 (file)
@@ -8,6 +8,8 @@
  * return an error value in addition to the "real"
  * return value.
  */
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
 #include <asm/thread_info.h>
 
 
  */
 
 .text
-.align 4
-.globl __get_user_1
-__get_user_1:
+ENTRY(__get_user_1)
+       CFI_STARTPROC
        GET_THREAD_INFO(%edx)
        cmpl TI_addr_limit(%edx),%eax
        jae bad_get_user
 1:     movzbl (%eax),%edx
        xorl %eax,%eax
        ret
+       CFI_ENDPROC
+ENDPROC(__get_user_1)
 
-.align 4
-.globl __get_user_2
-__get_user_2:
+ENTRY(__get_user_2)
+       CFI_STARTPROC
        addl $1,%eax
        jc bad_get_user
        GET_THREAD_INFO(%edx)
@@ -45,10 +47,11 @@ __get_user_2:
 2:     movzwl -1(%eax),%edx
        xorl %eax,%eax
        ret
+       CFI_ENDPROC
+ENDPROC(__get_user_2)
 
-.align 4
-.globl __get_user_4
-__get_user_4:
+ENTRY(__get_user_4)
+       CFI_STARTPROC
        addl $3,%eax
        jc bad_get_user
        GET_THREAD_INFO(%edx)
@@ -57,11 +60,16 @@ __get_user_4:
 3:     movl -3(%eax),%edx
        xorl %eax,%eax
        ret
+       CFI_ENDPROC
+ENDPROC(__get_user_4)
 
 bad_get_user:
+       CFI_STARTPROC
        xorl %edx,%edx
        movl $-14,%eax
        ret
+       CFI_ENDPROC
+END(bad_get_user)
 
 .section __ex_table,"a"
        .long 1b,bad_get_user
index a32d9f5..f58fba1 100644 (file)
@@ -8,6 +8,8 @@
  * return an error value in addition to the "real"
  * return value.
  */
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
 #include <asm/thread_info.h>
 
 
  * as they get called from within inline assembly.
  */
 
-#define ENTER  pushl %ebx ; GET_THREAD_INFO(%ebx)
-#define EXIT   popl %ebx ; ret
+#define ENTER  CFI_STARTPROC ; \
+               pushl %ebx ; \
+               CFI_ADJUST_CFA_OFFSET 4 ; \
+               CFI_REL_OFFSET ebx, 0 ; \
+               GET_THREAD_INFO(%ebx)
+#define EXIT   popl %ebx ; \
+               CFI_ADJUST_CFA_OFFSET -4 ; \
+               CFI_RESTORE ebx ; \
+               ret ; \
+               CFI_ENDPROC
 
 .text
-.align 4
-.globl __put_user_1
-__put_user_1:
+ENTRY(__put_user_1)
        ENTER
        cmpl TI_addr_limit(%ebx),%ecx
        jae bad_put_user
 1:     movb %al,(%ecx)
        xorl %eax,%eax
        EXIT
+ENDPROC(__put_user_1)
 
-.align 4
-.globl __put_user_2
-__put_user_2:
+ENTRY(__put_user_2)
        ENTER
        movl TI_addr_limit(%ebx),%ebx
        subl $1,%ebx
@@ -48,10 +55,9 @@ __put_user_2:
 2:     movw %ax,(%ecx)
        xorl %eax,%eax
        EXIT
+ENDPROC(__put_user_2)
 
-.align 4
-.globl __put_user_4
-__put_user_4:
+ENTRY(__put_user_4)
        ENTER
        movl TI_addr_limit(%ebx),%ebx
        subl $3,%ebx
@@ -60,10 +66,9 @@ __put_user_4:
 3:     movl %eax,(%ecx)
        xorl %eax,%eax
        EXIT
+ENDPROC(__put_user_4)
 
-.align 4
-.globl __put_user_8
-__put_user_8:
+ENTRY(__put_user_8)
        ENTER
        movl TI_addr_limit(%ebx),%ebx
        subl $7,%ebx
@@ -73,10 +78,16 @@ __put_user_8:
 5:     movl %edx,4(%ecx)
        xorl %eax,%eax
        EXIT
+ENDPROC(__put_user_8)
 
 bad_put_user:
+       CFI_STARTPROC simple
+       CFI_DEF_CFA esp, 2*4
+       CFI_OFFSET eip, -1*4
+       CFI_OFFSET ebx, -2*4
        movl $-14,%eax
        EXIT
+END(bad_put_user)
 
 .section __ex_table,"a"
        .long 1b,bad_put_user
index 086b372..9f38b12 100644 (file)
@@ -716,7 +716,6 @@ do {                                                                        \
 unsigned long __copy_to_user_ll(void __user *to, const void *from,
                                unsigned long n)
 {
-       BUG_ON((long) n < 0);
 #ifndef CONFIG_X86_WP_WORKS_OK
        if (unlikely(boot_cpu_data.wp_works_ok == 0) &&
                        ((unsigned long )to) < TASK_SIZE) {
@@ -785,7 +784,6 @@ EXPORT_SYMBOL(__copy_to_user_ll);
 unsigned long __copy_from_user_ll(void *to, const void __user *from,
                                        unsigned long n)
 {
-       BUG_ON((long)n < 0);
        if (movsl_is_ok(to, from, n))
                __copy_user_zeroing(to, from, n);
        else
@@ -797,7 +795,6 @@ EXPORT_SYMBOL(__copy_from_user_ll);
 unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
                                         unsigned long n)
 {
-       BUG_ON((long)n < 0);
        if (movsl_is_ok(to, from, n))
                __copy_user(to, from, n);
        else
@@ -810,7 +807,6 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
 unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
                                        unsigned long n)
 {
-       BUG_ON((long)n < 0);
 #ifdef CONFIG_X86_INTEL_USERCOPY
        if ( n > 64 && cpu_has_xmm2)
                 n = __copy_user_zeroing_intel_nocache(to, from, n);
@@ -825,7 +821,6 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
                                        unsigned long n)
 {
-       BUG_ON((long)n < 0);
 #ifdef CONFIG_X86_INTEL_USERCOPY
        if ( n > 64 && cpu_has_xmm2)
                 n = __copy_user_intel_nocache(to, from, n);
@@ -853,7 +848,6 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
 unsigned long
 copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-       BUG_ON((long) n < 0);
        if (access_ok(VERIFY_WRITE, to, n))
                n = __copy_to_user(to, from, n);
        return n;
@@ -879,7 +873,6 @@ EXPORT_SYMBOL(copy_to_user);
 unsigned long
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-       BUG_ON((long) n < 0);
        if (access_ok(VERIFY_READ, from, n))
                n = __copy_from_user(to, from, n);
        else
index 8a210fa..e932d34 100644 (file)
@@ -45,7 +45,7 @@ static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
 };
 
 
-static int probe_bigsmp(void)
+static int __init probe_bigsmp(void)
 { 
        if (def_to_bigsmp)
                dmi_bigsmp = 1;
index b8963a5..b47f951 100644 (file)
@@ -25,4 +25,45 @@ static int probe_es7000(void)
        return 0;
 }
 
+extern void es7000_sw_apic(void);
+static void __init enable_apic_mode(void)
+{
+       es7000_sw_apic();
+       return;
+}
+
+static __init int mps_oem_check(struct mp_config_table *mpc, char *oem,
+               char *productid)
+{
+       if (mpc->mpc_oemptr) {
+               struct mp_config_oemtable *oem_table =
+                       (struct mp_config_oemtable *)mpc->mpc_oemptr;
+               if (!strncmp(oem, "UNISYS", 6))
+                       return parse_unisys_oem((char *)oem_table);
+       }
+       return 0;
+}
+
+#ifdef CONFIG_ACPI
+/* Hook from generic ACPI tables.c */
+static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       unsigned long oem_addr;
+       if (!find_unisys_acpi_oem_table(&oem_addr)) {
+               if (es7000_check_dsdt())
+                       return parse_unisys_oem((char *)oem_addr);
+               else {
+                       setup_unisys();
+                       return 1;
+               }
+       }
+       return 0;
+}
+#else
+static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       return 0;
+}
+#endif
+
 struct genapic apic_es7000 = APIC_INIT("es7000", probe_es7000);
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 74aeedf..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);
@@ -580,39 +573,18 @@ do_boot_cpu(__u8 cpu)
        /* init_tasks (in sched.c) is indexed logically */
        stack_start.esp = (void *) idle->thread.esp;
 
-       /* Pre-allocate and initialize the CPU's GDT and PDA so it
-          doesn't have to do any memory allocation during the
-          delicate CPU-bringup phase. */
-       if (!init_gdt(cpu, idle)) {
-               printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu);
-               cpucount--;
-               return;
-       }
-
+       init_gdt(cpu, idle);
        irq_ctx_init(cpu);
 
        /* Note: Don't modify initial ss override */
        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);
@@ -655,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",
@@ -772,12 +740,6 @@ initialize_secondary(void)
        set_current(hard_get_current());
 #endif
 
-       /*
-        * switch to the per CPU GDT we already set up
-        * in do_boot_cpu()
-        */
-       cpu_set_gdt(current_thread_info()->cpu);
-
        /*
         * We don't actually need to load the full TSS,
         * basically just the stack pointer and the eip.
@@ -1082,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());
 
@@ -1116,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)
@@ -1130,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 b8c4e25..f534c29 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/highmem.h>
+#include <linux/bootmem.h>             /* for max_low_pfn */
 #include <linux/module.h>
 #include <linux/kprobes.h>
 #include <linux/uaccess.h>
@@ -301,7 +302,6 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
        struct mm_struct *mm;
        struct vm_area_struct * vma;
        unsigned long address;
-       unsigned long page;
        int write, si_code;
 
        /* get the address */
@@ -510,7 +510,9 @@ no_context:
        bust_spinlocks(1);
 
        if (oops_may_print()) {
-       #ifdef CONFIG_X86_PAE
+               __typeof__(pte_val(__pte(0))) page;
+
+#ifdef CONFIG_X86_PAE
                if (error_code & 16) {
                        pte_t *pte = lookup_address(address);
 
@@ -519,7 +521,7 @@ no_context:
                                        "NX-protected page - exploit attempt? "
                                        "(uid: %d)\n", current->uid);
                }
-       #endif
+#endif
                if (address < PAGE_SIZE)
                        printk(KERN_ALERT "BUG: unable to handle kernel NULL "
                                        "pointer dereference");
@@ -529,25 +531,38 @@ no_context:
                printk(" at virtual address %08lx\n",address);
                printk(KERN_ALERT " printing eip:\n");
                printk("%08lx\n", regs->eip);
-       }
-       page = read_cr3();
-       page = ((unsigned long *) __va(page))[address >> 22];
-       if (oops_may_print())
+
+               page = read_cr3();
+               page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
+#ifdef CONFIG_X86_PAE
+               printk(KERN_ALERT "*pdpt = %016Lx\n", page);
+               if ((page >> PAGE_SHIFT) < max_low_pfn
+                   && page & _PAGE_PRESENT) {
+                       page &= PAGE_MASK;
+                       page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT)
+                                                                & (PTRS_PER_PMD - 1)];
+                       printk(KERN_ALERT "*pde = %016Lx\n", page);
+                       page &= ~_PAGE_NX;
+               }
+#else
                printk(KERN_ALERT "*pde = %08lx\n", page);
-       /*
-        * We must not directly access the pte in the highpte
-        * case, the page table might be allocated in highmem.
-        * And lets rather not kmap-atomic the pte, just in case
-        * it's allocated already.
-        */
-#ifndef CONFIG_HIGHPTE
-       if ((page & 1) && oops_may_print()) {
-               page &= PAGE_MASK;
-               address &= 0x003ff000;
-               page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
-               printk(KERN_ALERT "*pte = %08lx\n", page);
-       }
 #endif
+
+               /*
+                * We must not directly access the pte in the highpte
+                * case if the page table is located in highmem.
+                * And let's rather not kmap-atomic the pte, just in case
+                * it's allocated already.
+                */
+               if ((page >> PAGE_SHIFT) < max_low_pfn
+                   && (page & _PAGE_PRESENT)) {
+                       page &= PAGE_MASK;
+                       page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
+                                                                & (PTRS_PER_PTE - 1)];
+                       printk(KERN_ALERT "*pte = %0*Lx\n", sizeof(page)*2, (u64)page);
+               }
+       }
+
        tsk->thread.cr2 = address;
        tsk->thread.trap_no = 14;
        tsk->thread.error_code = error_code;
@@ -588,7 +603,6 @@ do_sigbus:
        force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
 }
 
-#ifndef CONFIG_X86_PAE
 void vmalloc_sync_all(void)
 {
        /*
@@ -601,6 +615,9 @@ void vmalloc_sync_all(void)
        static unsigned long start = TASK_SIZE;
        unsigned long address;
 
+       if (SHARED_KERNEL_PMD)
+               return;
+
        BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK);
        for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) {
                if (!test_bit(pgd_index(address), insync)) {
@@ -623,4 +640,3 @@ void vmalloc_sync_all(void)
                        start = address + PGDIR_SIZE;
        }
 }
-#endif
index ac70d09..ad8d86c 100644 (file)
@@ -26,7 +26,7 @@ void kunmap(struct page *page)
  * However when holding an atomic kmap is is not legal to sleep, so atomic
  * kmaps are appropriate for short, tight code paths only.
  */
-void *kmap_atomic(struct page *page, enum km_type type)
+void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
 {
        enum fixed_addresses idx;
        unsigned long vaddr;
@@ -41,12 +41,17 @@ void *kmap_atomic(struct page *page, enum km_type type)
                return page_address(page);
 
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-       set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+       set_pte(kmap_pte-idx, mk_pte(page, prot));
        arch_flush_lazy_mmu_mode();
 
        return (void*) vaddr;
 }
 
+void *kmap_atomic(struct page *page, enum km_type type)
+{
+       return kmap_atomic_prot(page, type, kmap_prot);
+}
+
 void kunmap_atomic(void *kvaddr, enum km_type type)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
@@ -67,6 +72,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
 #endif
        }
 
+       arch_flush_lazy_mmu_mode();
        pagefault_enable();
 }
 
index ae43688..dbe16f6 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/pfn.h>
 #include <linux/poison.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
@@ -42,6 +43,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/paravirt.h>
 
 unsigned int __VMALLOC_RESERVE = 128 << 20;
 
@@ -61,17 +63,18 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
        pmd_t *pmd_table;
                
 #ifdef CONFIG_X86_PAE
-       pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-       paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
-       set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
-       pud = pud_offset(pgd, 0);
-       if (pmd_table != pmd_offset(pud, 0)) 
-               BUG();
-#else
+       if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
+               pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+
+               paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
+               set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+               pud = pud_offset(pgd, 0);
+               if (pmd_table != pmd_offset(pud, 0))
+                       BUG();
+       }
+#endif
        pud = pud_offset(pgd, 0);
        pmd_table = pmd_offset(pud, 0);
-#endif
-
        return pmd_table;
 }
 
@@ -81,14 +84,12 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
  */
 static pte_t * __init one_page_table_init(pmd_t *pmd)
 {
-       if (pmd_none(*pmd)) {
+       if (!(pmd_val(*pmd) & _PAGE_PRESENT)) {
                pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+
                paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT);
                set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
-               if (page_table != pte_offset_kernel(pmd, 0))
-                       BUG();  
-
-               return page_table;
+               BUG_ON(page_table != pte_offset_kernel(pmd, 0));
        }
        
        return pte_offset_kernel(pmd, 0);
@@ -108,7 +109,6 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
 static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
 {
        pgd_t *pgd;
-       pud_t *pud;
        pmd_t *pmd;
        int pgd_idx, pmd_idx;
        unsigned long vaddr;
@@ -119,13 +119,10 @@ static void __init page_table_range_init (unsigned long start, unsigned long end
        pgd = pgd_base + pgd_idx;
 
        for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
-               if (pgd_none(*pgd)) 
-                       one_md_table_init(pgd);
-               pud = pud_offset(pgd, vaddr);
-               pmd = pmd_offset(pud, vaddr);
+               pmd = one_md_table_init(pgd);
+               pmd = pmd + pmd_index(vaddr);
                for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
-                       if (pmd_none(*pmd)) 
-                               one_page_table_init(pmd);
+                       one_page_table_init(pmd);
 
                        vaddr += PMD_SIZE;
                }
@@ -167,20 +164,22 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
                        /* Map with big pages if possible, otherwise create normal page tables. */
                        if (cpu_has_pse) {
                                unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
-
                                if (is_kernel_text(address) || is_kernel_text(address2))
                                        set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
                                else
                                        set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
+
                                pfn += PTRS_PER_PTE;
                        } else {
                                pte = one_page_table_init(pmd);
 
-                               for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
-                                               if (is_kernel_text(address))
-                                                       set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
-                                               else
-                                                       set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
+                               for (pte_ofs = 0;
+                                    pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
+                                    pte++, pfn++, pte_ofs++, address += PAGE_SIZE) {
+                                       if (is_kernel_text(address))
+                                               set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+                                       else
+                                               set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
                                }
                        }
                }
@@ -337,24 +336,78 @@ extern void __init remap_numa_kva(void);
 #define remap_numa_kva() do {} while (0)
 #endif
 
-static void __init pagetable_init (void)
+void __init native_pagetable_setup_start(pgd_t *base)
 {
-       unsigned long vaddr;
-       pgd_t *pgd_base = swapper_pg_dir;
-
 #ifdef CONFIG_X86_PAE
        int i;
-       /* Init entries of the first-level page table to the zero page */
-       for (i = 0; i < PTRS_PER_PGD; i++)
-               set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
+
+       /*
+        * Init entries of the first-level page table to the
+        * zero page, if they haven't already been set up.
+        *
+        * In a normal native boot, we'll be running on a
+        * pagetable rooted in swapper_pg_dir, but not in PAE
+        * mode, so this will end up clobbering the mappings
+        * for the lower 24Mbytes of the address space,
+        * without affecting the kernel address space.
+        */
+       for (i = 0; i < USER_PTRS_PER_PGD; i++)
+               set_pgd(&base[i],
+                       __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
+
+       /* Make sure kernel address space is empty so that a pagetable
+          will be allocated for it. */
+       memset(&base[USER_PTRS_PER_PGD], 0,
+              KERNEL_PGD_PTRS * sizeof(pgd_t));
 #else
        paravirt_alloc_pd(__pa(swapper_pg_dir) >> PAGE_SHIFT);
 #endif
+}
+
+void __init native_pagetable_setup_done(pgd_t *base)
+{
+#ifdef CONFIG_X86_PAE
+       /*
+        * Add low memory identity-mappings - SMP needs it when
+        * starting up on an AP from real-mode. In the non-PAE
+        * case we already have these mappings through head.S.
+        * All user-space mappings are explicitly cleared after
+        * SMP startup.
+        */
+       set_pgd(&base[0], base[USER_PTRS_PER_PGD]);
+#endif
+}
+
+/*
+ * Build a proper pagetable for the kernel mappings.  Up until this
+ * point, we've been running on some set of pagetables constructed by
+ * the boot process.
+ *
+ * If we're booting on native hardware, this will be a pagetable
+ * constructed in arch/i386/kernel/head.S, and not running in PAE mode
+ * (even if we'll end up running in PAE).  The root of the pagetable
+ * will be swapper_pg_dir.
+ *
+ * If we're booting paravirtualized under a hypervisor, then there are
+ * more options: we may already be running PAE, and the pagetable may
+ * or may not be based in swapper_pg_dir.  In any case,
+ * paravirt_pagetable_setup_start() will set up swapper_pg_dir
+ * appropriately for the rest of the initialization to work.
+ *
+ * In general, pagetable_init() assumes that the pagetable may already
+ * be partially populated, and so it avoids stomping on any existing
+ * mappings.
+ */
+static void __init pagetable_init (void)
+{
+       unsigned long vaddr, end;
+       pgd_t *pgd_base = swapper_pg_dir;
+
+       paravirt_pagetable_setup_start(pgd_base);
 
        /* Enable PSE if available */
-       if (cpu_has_pse) {
+       if (cpu_has_pse)
                set_in_cr4(X86_CR4_PSE);
-       }
 
        /* Enable PGE if available */
        if (cpu_has_pge) {
@@ -371,20 +424,12 @@ static void __init pagetable_init (void)
         * created - mappings will be set by set_fixmap():
         */
        vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       page_table_range_init(vaddr, 0, pgd_base);
+       end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
+       page_table_range_init(vaddr, end, pgd_base);
 
        permanent_kmaps_init(pgd_base);
 
-#ifdef CONFIG_X86_PAE
-       /*
-        * Add low memory identity-mappings - SMP needs it when
-        * starting up on an AP from real-mode. In the non-PAE
-        * case we already have these mappings through head.S.
-        * All user-space mappings are explicitly cleared after
-        * SMP startup.
-        */
-       set_pgd(&pgd_base[0], pgd_base[USER_PTRS_PER_PGD]);
-#endif
+       paravirt_pagetable_setup_done(pgd_base);
 }
 
 #if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
@@ -700,6 +745,8 @@ struct kmem_cache *pmd_cache;
 
 void __init pgtable_cache_init(void)
 {
+       size_t pgd_size = PTRS_PER_PGD*sizeof(pgd_t);
+
        if (PTRS_PER_PMD > 1) {
                pmd_cache = kmem_cache_create("pmd",
                                        PTRS_PER_PMD*sizeof(pmd_t),
@@ -709,13 +756,23 @@ void __init pgtable_cache_init(void)
                                        NULL);
                if (!pmd_cache)
                        panic("pgtable_cache_init(): cannot create pmd cache");
+
+               if (!SHARED_KERNEL_PMD) {
+                       /* If we're in PAE mode and have a non-shared
+                          kernel pmd, then the pgd size must be a
+                          page size.  This is because the pgd_list
+                          links through the page structure, so there
+                          can only be one pgd per page for this to
+                          work. */
+                       pgd_size = PAGE_SIZE;
+               }
        }
        pgd_cache = kmem_cache_create("pgd",
-                               PTRS_PER_PGD*sizeof(pgd_t),
-                               PTRS_PER_PGD*sizeof(pgd_t),
+                               pgd_size,
+                               pgd_size,
                                0,
                                pgd_ctor,
-                               PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
+                               (!SHARED_KERNEL_PMD) ? pgd_dtor : NULL);
        if (!pgd_cache)
                panic("pgtable_cache_init(): Cannot create pgd cache");
 }
@@ -751,13 +808,25 @@ static int noinline do_test_wp_bit(void)
 
 void mark_rodata_ro(void)
 {
-       unsigned long addr = (unsigned long)__start_rodata;
+       unsigned long start = PFN_ALIGN(_text);
+       unsigned long size = PFN_ALIGN(_etext) - start;
 
-       for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
-               change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO);
+#ifdef CONFIG_HOTPLUG_CPU
+       /* It must still be possible to apply SMP alternatives. */
+       if (num_possible_cpus() <= 1)
+#endif
+       {
+               change_page_attr(virt_to_page(start),
+                                size >> PAGE_SHIFT, PAGE_KERNEL_RX);
+               printk("Write protecting the kernel text: %luk\n", size >> 10);
+       }
 
-       printk("Write protecting the kernel read-only data: %uk\n",
-                       (__end_rodata - __start_rodata) >> 10);
+       start += size;
+       size = (unsigned long)__end_rodata - start;
+       change_page_attr(virt_to_page(start),
+                        size >> PAGE_SHIFT, PAGE_KERNEL_RO);
+       printk("Write protecting the kernel read-only data: %luk\n",
+              size >> 10);
 
        /*
         * change_page_attr() requires a global_flush_tlb() call after it.
@@ -774,26 +843,27 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
        unsigned long addr;
 
        for (addr = begin; addr < end; addr += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(addr));
-               init_page_count(virt_to_page(addr));
-               memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-               free_page(addr);
+               struct page *page = pfn_to_page(addr >> PAGE_SHIFT);
+               ClearPageReserved(page);
+               init_page_count(page);
+               memset(page_address(page), POISON_FREE_INITMEM, PAGE_SIZE);
+               __free_page(page);
                totalram_pages++;
        }
-       printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+       printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
 }
 
 void free_initmem(void)
 {
        free_init_pages("unused kernel memory",
-                       (unsigned long)(&__init_begin),
-                       (unsigned long)(&__init_end));
+                       __pa_symbol(&__init_begin),
+                       __pa_symbol(&__init_end));
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-       free_init_pages("initrd memory", start, end);
+       free_init_pages("initrd memory", __pa(start), __pa(end));
 }
 #endif
 
index 412ebbd..47bd477 100644 (file)
@@ -91,7 +91,7 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
        unsigned long flags;
 
        set_pte_atomic(kpte, pte);      /* change init_mm */
-       if (PTRS_PER_PMD > 1)
+       if (SHARED_KERNEL_PMD)
                return;
 
        spin_lock_irqsave(&pgd_lock, flags);
@@ -142,7 +142,7 @@ __change_page_attr(struct page *page, pgprot_t prot)
                return -EINVAL;
        kpte_page = virt_to_page(kpte);
        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { 
-               if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
+               if (!pte_huge(*kpte)) {
                        set_pte_atomic(kpte, mk_pte(page, prot)); 
                } else {
                        pgprot_t ref_prot;
@@ -158,7 +158,7 @@ __change_page_attr(struct page *page, pgprot_t prot)
                        kpte_page = split;
                }
                page_private(kpte_page)++;
-       } else if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
+       } else if (!pte_huge(*kpte)) {
                set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL));
                BUG_ON(page_private(kpte_page) == 0);
                page_private(kpte_page)--;
index fa0cfbd..9a96c16 100644 (file)
@@ -144,10 +144,8 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
 }
 
 static int fixmaps;
-#ifndef CONFIG_COMPAT_VDSO
 unsigned long __FIXADDR_TOP = 0xfffff000;
 EXPORT_SYMBOL(__FIXADDR_TOP);
-#endif
 
 void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
 {
@@ -173,12 +171,8 @@ void reserve_top_address(unsigned long reserve)
        BUG_ON(fixmaps > 0);
        printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
               (int)-reserve);
-#ifdef CONFIG_COMPAT_VDSO
-       BUG_ON(reserve != 0);
-#else
        __FIXADDR_TOP = -reserve - PAGE_SIZE;
        __VMALLOC_RESERVE += reserve;
-#endif
 }
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
@@ -238,42 +232,92 @@ static inline void pgd_list_del(pgd_t *pgd)
                set_page_private(next, (unsigned long)pprev);
 }
 
+#if (PTRS_PER_PMD == 1)
+/* Non-PAE pgd constructor */
 void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags;
 
-       if (PTRS_PER_PMD == 1) {
-               memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
-               spin_lock_irqsave(&pgd_lock, flags);
-       }
+       /* !PAE, no pagetable sharing */
+       memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+
+       spin_lock_irqsave(&pgd_lock, flags);
 
+       /* must happen under lock */
        clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
                        swapper_pg_dir + USER_PTRS_PER_PGD,
                        KERNEL_PGD_PTRS);
-
-       if (PTRS_PER_PMD > 1)
-               return;
-
-       /* must happen under lock */
        paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
-                       __pa(swapper_pg_dir) >> PAGE_SHIFT,
-                       USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
-
+                               __pa(swapper_pg_dir) >> PAGE_SHIFT,
+                               USER_PTRS_PER_PGD,
+                               KERNEL_PGD_PTRS);
        pgd_list_add(pgd);
        spin_unlock_irqrestore(&pgd_lock, flags);
 }
+#else  /* PTRS_PER_PMD > 1 */
+/* PAE pgd constructor */
+void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+{
+       /* PAE, kernel PMD may be shared */
+
+       if (SHARED_KERNEL_PMD) {
+               clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+                               swapper_pg_dir + USER_PTRS_PER_PGD,
+                               KERNEL_PGD_PTRS);
+       } else {
+               unsigned long flags;
+
+               memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+               spin_lock_irqsave(&pgd_lock, flags);
+               pgd_list_add(pgd);
+               spin_unlock_irqrestore(&pgd_lock, flags);
+       }
+}
+#endif /* PTRS_PER_PMD */
 
-/* never called when PTRS_PER_PMD > 1 */
 void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags; /* can be called from interrupt context */
 
+       BUG_ON(SHARED_KERNEL_PMD);
+
        paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
        spin_lock_irqsave(&pgd_lock, flags);
        pgd_list_del(pgd);
        spin_unlock_irqrestore(&pgd_lock, flags);
 }
 
+#define UNSHARED_PTRS_PER_PGD                          \
+       (SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+
+/* If we allocate a pmd for part of the kernel address space, then
+   make sure its initialized with the appropriate kernel mappings.
+   Otherwise use a cached zeroed pmd.  */
+static pmd_t *pmd_cache_alloc(int idx)
+{
+       pmd_t *pmd;
+
+       if (idx >= USER_PTRS_PER_PGD) {
+               pmd = (pmd_t *)__get_free_page(GFP_KERNEL);
+
+               if (pmd)
+                       memcpy(pmd,
+                              (void *)pgd_page_vaddr(swapper_pg_dir[idx]),
+                              sizeof(pmd_t) * PTRS_PER_PMD);
+       } else
+               pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+
+       return pmd;
+}
+
+static void pmd_cache_free(pmd_t *pmd, int idx)
+{
+       if (idx >= USER_PTRS_PER_PGD)
+               free_page((unsigned long)pmd);
+       else
+               kmem_cache_free(pmd_cache, pmd);
+}
+
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        int i;
@@ -282,10 +326,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
        if (PTRS_PER_PMD == 1 || !pgd)
                return pgd;
 
-       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
-               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+       for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) {
+               pmd_t *pmd = pmd_cache_alloc(i);
+
                if (!pmd)
                        goto out_oom;
+
                paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
                set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
        }
@@ -296,7 +342,7 @@ out_oom:
                pgd_t pgdent = pgd[i];
                void* pmd = (void *)__va(pgd_val(pgdent)-1);
                paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
-               kmem_cache_free(pmd_cache, pmd);
+               pmd_cache_free(pmd, i);
        }
        kmem_cache_free(pgd_cache, pgd);
        return NULL;
@@ -308,11 +354,11 @@ void pgd_free(pgd_t *pgd)
 
        /* in the PAE case user pgd entries are overwritten before usage */
        if (PTRS_PER_PMD > 1)
-               for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+               for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) {
                        pgd_t pgdent = pgd[i];
                        void* pmd = (void *)__va(pgd_val(pgdent)-1);
                        paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
-                       kmem_cache_free(pmd_cache, pmd);
+                       pmd_cache_free(pmd, i);
                }
        /* in the non-PAE case, free_pgtables() clears user pgd entries */
        kmem_cache_free(pgd_cache, pgd);
index 8fda7be..695f737 100644 (file)
@@ -414,6 +414,10 @@ int __init op_nmi_init(struct oprofile_operations *ops)
                                   user space an consistent name. */
                                cpu_type = "x86-64/hammer";
                                break;
+                       case 0x10:
+                               model = &op_athlon_spec;
+                               cpu_type = "x86-64/family10";
+                               break;
                        }
                        break;
  
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 b21b6da..1cf11af 100644 (file)
@@ -6,7 +6,7 @@
    in the right sequence from here. */
 static __init int pci_access_init(void)
 {
-       int type = 0;
+       int type __attribute__((unused)) = 0;
 
 #ifdef CONFIG_PCI_DIRECT
        type = pci_direct_probe();
index 747d8c6..c7cabee 100644 (file)
@@ -60,14 +60,19 @@ static const char __init *pci_mmcfg_e7520(void)
        u32 win;
        pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
 
-       pci_mmcfg_config_num = 1;
-       pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
-       if (!pci_mmcfg_config)
-               return NULL;
-       pci_mmcfg_config[0].address = (win & 0xf000) << 16;
-       pci_mmcfg_config[0].pci_segment = 0;
-       pci_mmcfg_config[0].start_bus_number = 0;
-       pci_mmcfg_config[0].end_bus_number = 255;
+       win = win & 0xf000;
+       if(win == 0x0000 || win == 0xf000)
+               pci_mmcfg_config_num = 0;
+       else {
+               pci_mmcfg_config_num = 1;
+               pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+               if (!pci_mmcfg_config)
+                       return NULL;
+               pci_mmcfg_config[0].address = win << 16;
+               pci_mmcfg_config[0].pci_segment = 0;
+               pci_mmcfg_config[0].start_bus_number = 0;
+               pci_mmcfg_config[0].end_bus_number = 255;
+       }
 
        return "Intel Corporation E7520 Memory Controller Hub";
 }
@@ -108,6 +113,10 @@ static const char __init *pci_mmcfg_intel_945(void)
        if ((pciexbar & mask) & 0x0fffffffU)
                pci_mmcfg_config_num = 0;
 
+       /* Don't hit the APIC registers and their friends */
+       if ((pciexbar & mask) >= 0xf0000000U)
+               pci_mmcfg_config_num = 0;
+
        if (pci_mmcfg_config_num) {
                pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
                if (!pci_mmcfg_config)
index 2c15500..998fd3e 100644 (file)
@@ -21,6 +21,7 @@ unsigned long saved_context_eflags;
 
 void __save_processor_state(struct saved_context *ctxt)
 {
+       mtrr_save_fixed_ranges(NULL);
        kernel_fpu_begin();
 
        /*
index db5e98d..a0020b9 100644 (file)
@@ -16,6 +16,9 @@
 /* Defined in arch/i386/power/swsusp.S */
 extern int restore_image(void);
 
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
 /* Pointer to the temporary resume page tables */
 pgd_t *resume_pg_dir;
 
@@ -156,3 +159,14 @@ int swsusp_arch_resume(void)
        restore_image();
        return 0;
 }
+
+/*
+ *     pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+       unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
+       unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
+       return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
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 439cc25..6c73bca 100644 (file)
@@ -110,7 +110,7 @@ SECTIONS
   __initramfs_end = .;
 #endif
 
-  . = ALIGN(32);
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
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 c76b793..043f637 100644 (file)
@@ -119,7 +119,7 @@ SECTIONS
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
 #endif
-  . = ALIGN(32);
+  . = ALIGN(_PAGE_SIZE);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
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 2a82533..c745859 100644 (file)
@@ -181,7 +181,7 @@ SECTIONS
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
 #endif
-  . = ALIGN(32);
+  . = ALIGN(ASM_PAGE_SIZE);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
index e0fa80e..aa693d0 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_CRASH_DUMP)      += crash_dump.o
 obj-$(CONFIG_6xx)              += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)              += tau_6xx.o
 obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
 obj32-$(CONFIG_MODULES)                += module_32.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
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 22083ce..6018178 100644 (file)
@@ -582,14 +582,14 @@ void __init setup_per_cpu_areas(void)
        char *ptr;
 
        /* Copy section for each CPU (we discard the original) */
-       size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
+       size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE);
 #ifdef CONFIG_MODULES
        if (size < PERCPU_ENOUGH_ROOM)
                size = PERCPU_ENOUGH_ROOM;
 #endif
 
        for_each_possible_cpu(i) {
-               ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
+               ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size);
                if (!ptr)
                        panic("Cannot allocate cpu data for CPU %d\n", i);
 
diff --git a/arch/powerpc/kernel/suspend.c b/arch/powerpc/kernel/suspend.c
new file mode 100644 (file)
index 0000000..8cee571
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Suspend support specific for power.
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ */
+
+#include <asm/page.h>
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+/*
+ *     pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+       unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+       unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
+       return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
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 7eefeb4..1320673 100644 (file)
@@ -139,11 +139,7 @@ SECTIONS
                __initramfs_end = .;
        }
 #endif
-#ifdef CONFIG_PPC32
-       . = ALIGN(32);
-#else
-       . = ALIGN(128);
-#endif
+       . = ALIGN(PAGE_SIZE);
        .data.percpu : {
                __per_cpu_start = .;
                *(.data.percpu)
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 a062556..44cd128 100644 (file)
@@ -130,7 +130,7 @@ SECTIONS
   __ftr_fixup : { *(__ftr_fixup) }
   __stop___ftr_fixup = .;
 
-  . = ALIGN(32);
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
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.
@@ -804,6 +898,11 @@ setup_arch(char **cmdline_p)
         __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
        smp_setup_cpu_possible_map();
 
+       /*
+        * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+        */
+       setup_hwcaps();
+
        /*
         * Create kernel page tables and switch to virtual addressing.
         */
@@ -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 418f642..e9d3432 100644 (file)
@@ -107,7 +107,7 @@ SECTIONS
   . = ALIGN(2);
   __initramfs_end = .;
 #endif
-  . = ALIGN(256);
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
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 78a6c09..2f606d0 100644 (file)
@@ -54,7 +54,7 @@ SECTIONS
   . = ALIGN(PAGE_SIZE);
   .data.page_aligned : { *(.data.page_aligned) }
 
-  . = ALIGN(L1_CACHE_BYTES);
+  . = ALIGN(PAGE_SIZE);
   __per_cpu_start = .;
   .data.percpu : { *(.data.percpu) }
   __per_cpu_end = .;
index a59c5e9..4f9616f 100644 (file)
@@ -85,7 +85,7 @@ SECTIONS
   . = ALIGN(PAGE_SIZE);
   .data.page_aligned : C_PHYS(.data.page_aligned) { *(.data.page_aligned) }
 
-  . = ALIGN(L1_CACHE_BYTES);
+  . = ALIGN(PAGE_SIZE);
   __per_cpu_start = .;
   .data.percpu : C_PHYS(.data.percpu) { *(.data.percpu) }
   __per_cpu_end = . ;
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 e5c24e0..f0bb6e6 100644 (file)
@@ -65,7 +65,7 @@ SECTIONS
   __initramfs_end = .;
 #endif
 
-  . = ALIGN(32);
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
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 d4f0a70..1fac215 100644 (file)
@@ -1343,11 +1343,11 @@ void __init setup_per_cpu_areas(void)
        /* Copy section for each CPU (we discard the original) */
        goal = PERCPU_ENOUGH_ROOM;
 
-       __per_cpu_shift = 0;
-       for (size = 1UL; size < goal; size <<= 1UL)
+       __per_cpu_shift = PAGE_SHIFT;
+       for (size = PAGE_SIZE; size < goal; size <<= 1UL)
                __per_cpu_shift++;
 
-       ptr = alloc_bootmem(size * NR_CPUS);
+       ptr = alloc_bootmem_pages(size * NR_CPUS);
 
        __per_cpu_base = ptr - __per_cpu_start;
 
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 780cc0a..f938fa8 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_M686=y
 # CONFIG_MGEODE_LX is not set
 # CONFIG_MCYRIXIII is not set
 # CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
 # CONFIG_X86_GENERIC is not set
 CONFIG_X86_CMPXCHG=y
 CONFIG_X86_XADD=y
index 56eb14c..145bb82 100644 (file)
@@ -415,13 +415,13 @@ config OUT_OF_LINE_PFN_TO_PAGE
        depends on DISCONTIGMEM
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-256)"
+       int "Maximum number of CPUs (2-255)"
        range 2 255
        depends on SMP
        default "8"
        help
          This allows you to specify the maximum number of CPUs which this
-         kernel will support. Current maximum is 256 CPUs due to
+         kernel will support. Current maximum is 255 CPUs due to
          APIC addressing limits. Less depending on the hardware.
 
          This is purely to save memory - each supported CPU requires
@@ -565,23 +565,56 @@ config CRASH_DUMP
          PHYSICAL_START.
           For more details see Documentation/kdump/kdump.txt
 
+config RELOCATABLE
+       bool "Build a relocatable kernel(EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         Builds a relocatable kernel. This enables loading and running
+         a kernel binary from a different physical address than it has
+         been compiled for.
+
+         One use is for the kexec on panic case where the recovery kernel
+         must live at a different physical address than the primary
+         kernel.
+
+         Note: If CONFIG_RELOCATABLE=y, then kernel run from the address
+         it has been loaded at and compile time physical address
+         (CONFIG_PHYSICAL_START) is ignored.
+
 config PHYSICAL_START
        hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
-       default "0x1000000" if CRASH_DUMP
        default "0x200000"
        help
-         This gives the physical address where the kernel is loaded. Normally
-         for regular kernels this value is 0x200000 (2MB). But in the case
-         of kexec on panic the fail safe kernel needs to run at a different
-         address than the panic-ed kernel. This option is used to set the load
-         address for kernels used to capture crash dump on being kexec'ed
-         after panic. The default value for crash dump kernels is
-         0x1000000 (16MB). This can also be set based on the "X" value as
+         This gives the physical address where the kernel is loaded. It
+         should be aligned to 2MB boundary.
+
+         If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then
+         bzImage will decompress itself to above physical address and
+         run from there. Otherwise, bzImage will run from the address where
+         it has been loaded by the boot loader and will ignore above physical
+         address.
+
+         In normal kdump cases one does not have to set/change this option
+         as now bzImage can be compiled as a completely relocatable image
+         (CONFIG_RELOCATABLE=y) and be used to load and run from a different
+         address. This option is mainly useful for the folks who don't want
+         to use a bzImage for capturing the crash dump and want to use a
+         vmlinux instead.
+
+         So if you are using bzImage for capturing the crash dump, leave
+         the value here unchanged to 0x200000 and set CONFIG_RELOCATABLE=y.
+         Otherwise if you plan to use vmlinux for capturing the crash dump
+         change this value to start of the reserved region (Typically 16MB
+         0x1000000). In other words, it can be set based on the "X" value as
          specified in the "crashkernel=YM@XM" command line boot parameter
          passed to the panic-ed kernel. Typically this parameter is set as
          crashkernel=64M@16M. Please take a look at
          Documentation/kdump/kdump.txt for more details about crash dumps.
 
+         Usage of bzImage for capturing the crash dump is advantageous as
+         one does not have to build two kernels. Same kernel can be used
+         as production kernel and capture kernel.
+
          Don't change this unless you know what you are doing.
 
 config SECCOMP
@@ -627,14 +660,6 @@ config CC_STACKPROTECTOR_ALL
 
 source kernel/Kconfig.hz
 
-config REORDER
-       bool "Function reordering"
-       default n
-       help
-         This option enables the toolchain to reorder functions for a more 
-         optimal TLB usage. If you have pretty much any version of binutils, 
-        this can increase your kernel build time by roughly one minute.
-
 config K8_NB
        def_bool y
        depends on AGP_AMD64 || IOMMU || (PCI && NUMA)
@@ -676,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 2941a91..29617ae 100644 (file)
@@ -40,10 +40,6 @@ cflags-y += -m64
 cflags-y += -mno-red-zone
 cflags-y += -mcmodel=kernel
 cflags-y += -pipe
-cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections
-# this makes reading assembly source easier, but produces worse code
-# actually it makes the kernel smaller too.
-cflags-y += -fno-reorder-blocks
 cflags-y += -Wno-sign-compare
 cflags-y += -fno-asynchronous-unwind-tables
 ifneq ($(CONFIG_DEBUG_INFO),y)
index deb063e..ee6f650 100644 (file)
@@ -36,7 +36,7 @@ subdir-               := compressed/  #Let make clean descend in compressed/
 # ---------------------------------------------------------------------------
 
 $(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
+$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
 $(obj)/bzImage: BUILDFLAGS   := -b
 
 quiet_cmd_image = BUILD   $@
index e70fa6e..705a3e3 100644 (file)
@@ -8,16 +8,14 @@
 
 targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
 EXTRA_AFLAGS   := -traditional
-AFLAGS         := $(subst -m64,-m32,$(AFLAGS))
 
 # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
 # -m32
-CFLAGS := -m32 -D__KERNEL__ -Iinclude -O2  -fno-strict-aliasing
-LDFLAGS := -m elf_i386
+CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2  -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin
+LDFLAGS := -m elf_x86_64
 
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 -m elf_i386
-
-$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
+LDFLAGS_vmlinux := -T
+$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
        $(call if_changed,ld)
        @:
 
@@ -27,7 +25,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
 
-LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
+LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
 
 $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
        $(call if_changed,ld)
index 6f55565..f9d5692 100644 (file)
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/msr.h>
 
+.section ".text.head"
        .code32
        .globl startup_32
-       
+
 startup_32:
        cld
        cli
-       movl $(__KERNEL_DS),%eax
-       movl %eax,%ds
-       movl %eax,%es
-       movl %eax,%fs
-       movl %eax,%gs
-
-       lss stack_start,%esp
-       xorl %eax,%eax
-1:     incl %eax               # check that A20 really IS enabled
-       movl %eax,0x000000      # loop forever if it isn't
-       cmpl %eax,0x100000
-       je 1b
+       movl    $(__KERNEL_DS), %eax
+       movl    %eax, %ds
+       movl    %eax, %es
+       movl    %eax, %ss
+
+/* Calculate the delta between where we were compiled to run
+ * at and where we were actually loaded at.  This can only be done
+ * with a short local call on x86.  Nothing  else will tell us what
+ * address we are running at.  The reserved chunk of the real-mode
+ * data at 0x34-0x3f are used as the stack for this calculation.
+ * Only 4 bytes are needed.
+ */
+       leal    0x40(%esi), %esp
+       call    1f
+1:     popl    %ebp
+       subl    $1b, %ebp
+
+/* setup a stack and make sure cpu supports long mode. */
+       movl    $user_stack_end, %eax
+       addl    %ebp, %eax
+       movl    %eax, %esp
+
+       call    verify_cpu
+       testl   %eax, %eax
+       jnz     no_longmode
+
+/* Compute the delta between where we were compiled to run at
+ * and where the code will actually run at.
+ */
+/* %ebp contains the address we are loaded at by the boot loader and %ebx
+ * contains the address where we should move the kernel image temporarily
+ * for safe in-place decompression.
+ */
+
+#ifdef CONFIG_RELOCATABLE
+       movl    %ebp, %ebx
+       addl    $(LARGE_PAGE_SIZE -1), %ebx
+       andl    $LARGE_PAGE_MASK, %ebx
+#else
+       movl    $CONFIG_PHYSICAL_START, %ebx
+#endif
+
+       /* Replace the compressed data size with the uncompressed size */
+       subl    input_len(%ebp), %ebx
+       movl    output_len(%ebp), %eax
+       addl    %eax, %ebx
+       /* Add 8 bytes for every 32K input block */
+       shrl    $12, %eax
+       addl    %eax, %ebx
+       /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */
+       addl    $(32768 + 18 + 4095), %ebx
+       andl    $~4095, %ebx
 
 /*
- * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
- * confuse the debugger if this code is traced.
- * XXX - best to initialize before switching to protected mode.
+ * Prepare for entering 64 bit mode
  */
-       pushl $0
-       popfl
+
+       /* Load new GDT with the 64bit segments using 32bit descriptor */
+       leal    gdt(%ebp), %eax
+       movl    %eax, gdt+2(%ebp)
+       lgdt    gdt(%ebp)
+
+       /* Enable PAE mode */
+       xorl    %eax, %eax
+       orl     $(1 << 5), %eax
+       movl    %eax, %cr4
+
+ /*
+  * Build early 4G boot pagetable
+  */
+       /* Initialize Page tables to 0*/
+       leal    pgtable(%ebx), %edi
+       xorl    %eax, %eax
+       movl    $((4096*6)/4), %ecx
+       rep     stosl
+
+       /* Build Level 4 */
+       leal    pgtable + 0(%ebx), %edi
+       leal    0x1007 (%edi), %eax
+       movl    %eax, 0(%edi)
+
+       /* Build Level 3 */
+       leal    pgtable + 0x1000(%ebx), %edi
+       leal    0x1007(%edi), %eax
+       movl    $4, %ecx
+1:     movl    %eax, 0x00(%edi)
+       addl    $0x00001000, %eax
+       addl    $8, %edi
+       decl    %ecx
+       jnz     1b
+
+       /* Build Level 2 */
+       leal    pgtable + 0x2000(%ebx), %edi
+       movl    $0x00000183, %eax
+       movl    $2048, %ecx
+1:     movl    %eax, 0(%edi)
+       addl    $0x00200000, %eax
+       addl    $8, %edi
+       decl    %ecx
+       jnz     1b
+
+       /* Enable the boot page tables */
+       leal    pgtable(%ebx), %eax
+       movl    %eax, %cr3
+
+       /* Enable Long mode in EFER (Extended Feature Enable Register) */
+       movl    $MSR_EFER, %ecx
+       rdmsr
+       btsl    $_EFER_LME, %eax
+       wrmsr
+
+       /* Setup for the jump to 64bit mode
+        *
+        * When the jump is performend we will be in long mode but
+        * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
+        * (and in turn EFER.LMA = 1).  To jump into 64bit mode we use
+        * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+        * We place all of the values on our mini stack so lret can
+        * used to perform that far jump.
+        */
+       pushl   $__KERNEL_CS
+       leal    startup_64(%ebp), %eax
+       pushl   %eax
+
+       /* Enter paged protected Mode, activating Long Mode */
+       movl    $0x80000001, %eax /* Enable Paging and Protected mode */
+       movl    %eax, %cr0
+
+       /* Jump from 32bit compatibility mode into 64bit mode. */
+       lret
+
+no_longmode:
+       /* This isn't an x86-64 CPU so hang */
+1:
+       hlt
+       jmp     1b
+
+#include "../../kernel/verify_cpu.S"
+
+       /* Be careful here startup_64 needs to be at a predictable
+        * address so I can export it in an ELF header.  Bootloaders
+        * should look at the ELF header to find this address, as
+        * it may change in the future.
+        */
+       .code64
+       .org 0x200
+ENTRY(startup_64)
+       /* We come here either from startup_32 or directly from a
+        * 64bit bootloader.  If we come here from a bootloader we depend on
+        * an identity mapped page table being provied that maps our
+        * entire text+data+bss and hopefully all of memory.
+        */
+
+       /* Setup data segments. */
+       xorl    %eax, %eax
+       movl    %eax, %ds
+       movl    %eax, %es
+       movl    %eax, %ss
+
+       /* Compute the decompressed kernel start address.  It is where
+        * we were loaded at aligned to a 2M boundary. %rbp contains the
+        * decompressed kernel start address.
+        *
+        * If it is a relocatable kernel then decompress and run the kernel
+        * from load address aligned to 2MB addr, otherwise decompress and
+        * run the kernel from CONFIG_PHYSICAL_START
+        */
+
+       /* Start with the delta to where the kernel will run at. */
+#ifdef CONFIG_RELOCATABLE
+       leaq    startup_32(%rip) /* - $startup_32 */, %rbp
+       addq    $(LARGE_PAGE_SIZE - 1), %rbp
+       andq    $LARGE_PAGE_MASK, %rbp
+       movq    %rbp, %rbx
+#else
+       movq    $CONFIG_PHYSICAL_START, %rbp
+       movq    %rbp, %rbx
+#endif
+
+       /* Replace the compressed data size with the uncompressed size */
+       movl    input_len(%rip), %eax
+       subq    %rax, %rbx
+       movl    output_len(%rip), %eax
+       addq    %rax, %rbx
+       /* Add 8 bytes for every 32K input block */
+       shrq    $12, %rax
+       addq    %rax, %rbx
+       /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */
+       addq    $(32768 + 18 + 4095), %rbx
+       andq    $~4095, %rbx
+
+/* Copy the compressed kernel to the end of our buffer
+ * where decompression in place becomes safe.
+ */
+       leaq    _end(%rip), %r8
+       leaq    _end(%rbx), %r9
+       movq    $_end /* - $startup_32 */, %rcx
+1:     subq    $8, %r8
+       subq    $8, %r9
+       movq    0(%r8), %rax
+       movq    %rax, 0(%r9)
+       subq    $8, %rcx
+       jnz     1b
+
+/*
+ * Jump to the relocated address.
+ */
+       leaq    relocated(%rbx), %rax
+       jmp     *%rax
+
+.section ".text"
+relocated:
+
 /*
  * Clear BSS
  */
-       xorl %eax,%eax
-       movl $_edata,%edi
-       movl $_end,%ecx
-       subl %edi,%ecx
+       xorq    %rax, %rax
+       leaq    _edata(%rbx), %rdi
+       leaq    _end(%rbx), %rcx
+       subq    %rdi, %rcx
        cld
        rep
        stosb
+
+       /* Setup the stack */
+       leaq    user_stack_end(%rip), %rsp
+
+       /* zero EFLAGS after setting rsp */
+       pushq   $0
+       popfq
+
 /*
  * Do the decompression, and jump to the new kernel..
  */
-       subl $16,%esp   # place for structure on the stack
-       movl %esp,%eax
-       pushl %esi      # real mode pointer as second arg
-       pushl %eax      # address of structure as first arg
-       call decompress_kernel
-       orl  %eax,%eax 
-       jnz  3f
-       addl $8,%esp
-       xorl %ebx,%ebx
-       ljmp $(__KERNEL_CS), $__PHYSICAL_START
+       pushq   %rsi                    # Save the real mode argument
+       movq    %rsi, %rdi              # real mode address
+       leaq    _heap(%rip), %rsi       # _heap
+       leaq    input_data(%rip), %rdx  # input_data
+       movl    input_len(%rip), %eax
+       movq    %rax, %rcx              # input_len
+       movq    %rbp, %r8               # output
+       call    decompress_kernel
+       popq    %rsi
 
-/*
- * We come here, if we were loaded high.
- * We need to move the move-in-place routine down to 0x1000
- * and then start it with the buffer addresses in registers,
- * which we got from the stack.
- */
-3:
-       movl %esi,%ebx  
-       movl $move_routine_start,%esi
-       movl $0x1000,%edi
-       movl $move_routine_end,%ecx
-       subl %esi,%ecx
-       addl $3,%ecx
-       shrl $2,%ecx
-       cld
-       rep
-       movsl
-
-       popl %esi       # discard the address
-       addl $4,%esp    # real mode pointer
-       popl %esi       # low_buffer_start
-       popl %ecx       # lcount
-       popl %edx       # high_buffer_start
-       popl %eax       # hcount
-       movl $__PHYSICAL_START,%edi
-       cli             # make sure we don't get interrupted
-       ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
 
 /*
- * Routine (template) for moving the decompressed kernel in place,
- * if we were high loaded. This _must_ PIC-code !
+ * Jump to the decompressed kernel.
  */
-move_routine_start:
-       movl %ecx,%ebp
-       shrl $2,%ecx
-       rep
-       movsl
-       movl %ebp,%ecx
-       andl $3,%ecx
-       rep
-       movsb
-       movl %edx,%esi
-       movl %eax,%ecx  # NOTE: rep movsb won't move if %ecx == 0
-       addl $3,%ecx
-       shrl $2,%ecx
-       rep
-       movsl
-       movl %ebx,%esi  # Restore setup pointer
-       xorl %ebx,%ebx
-       ljmp $(__KERNEL_CS), $__PHYSICAL_START
-move_routine_end:
+       jmp     *%rbp
 
-
-/* Stack for uncompression */  
-       .align 32
-user_stack:            
+       .data
+gdt:
+       .word   gdt_end - gdt
+       .long   gdt
+       .word   0
+       .quad   0x0000000000000000      /* NULL descriptor */
+       .quad   0x00af9a000000ffff      /* __KERNEL_CS */
+       .quad   0x00cf92000000ffff      /* __KERNEL_DS */
+gdt_end:
+       .bss
+/* Stack for uncompression */
+       .balign 4
+user_stack:
        .fill 4096,4,0
-stack_start:   
-       .long user_stack+4096
-       .word __KERNEL_DS
-
+user_stack_end:
index 3755b2e..f932b0e 100644 (file)
@@ -9,10 +9,95 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
+#define _LINUX_STRING_H_ 1
+#define __LINUX_BITMAP_H 1
+
+#include <linux/linkage.h>
 #include <linux/screen_info.h>
 #include <asm/io.h>
 #include <asm/page.h>
 
+/* WARNING!!
+ * This code is compiled with -fPIC and it is relocated dynamically
+ * at run time, but no relocation processing is performed.
+ * This means that it is not safe to place pointers in static structures.
+ */
+
+/*
+ * Getting to provable safe in place decompression is hard.
+ * Worst case behaviours need to be analized.
+ * Background information:
+ *
+ * The file layout is:
+ *    magic[2]
+ *    method[1]
+ *    flags[1]
+ *    timestamp[4]
+ *    extraflags[1]
+ *    os[1]
+ *    compressed data blocks[N]
+ *    crc[4] orig_len[4]
+ *
+ * resulting in 18 bytes of non compressed data overhead.
+ *
+ * Files divided into blocks
+ * 1 bit (last block flag)
+ * 2 bits (block type)
+ *
+ * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+ * The smallest block type encoding is always used.
+ *
+ * stored:
+ *    32 bits length in bytes.
+ *
+ * fixed:
+ *    magic fixed tree.
+ *    symbols.
+ *
+ * dynamic:
+ *    dynamic tree encoding.
+ *    symbols.
+ *
+ *
+ * The buffer for decompression in place is the length of the
+ * uncompressed data, plus a small amount extra to keep the algorithm safe.
+ * The compressed data is placed at the end of the buffer.  The output
+ * pointer is placed at the start of the buffer and the input pointer
+ * is placed where the compressed data starts.  Problems will occur
+ * when the output pointer overruns the input pointer.
+ *
+ * The output pointer can only overrun the input pointer if the input
+ * pointer is moving faster than the output pointer.  A condition only
+ * triggered by data whose compressed form is larger than the uncompressed
+ * form.
+ *
+ * The worst case at the block level is a growth of the compressed data
+ * of 5 bytes per 32767 bytes.
+ *
+ * The worst case internal to a compressed block is very hard to figure.
+ * The worst case can at least be boundined by having one bit that represents
+ * 32764 bytes and then all of the rest of the bytes representing the very
+ * very last byte.
+ *
+ * All of which is enough to compute an amount of extra data that is required
+ * to be safe.  To avoid problems at the block level allocating 5 extra bytes
+ * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
+ * adding an extra 32767 bytes (the worst case uncompressed block size) is
+ * sufficient, to ensure that in the worst case the decompressed data for
+ * block will stop the byte before the compressed data for a block begins.
+ * To avoid problems with the compressed data's meta information an extra 18
+ * bytes are needed.  Leading to the formula:
+ *
+ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
+ *
+ * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
+ * Adding 32768 instead of 32767 just makes for round numbers.
+ * Adding the decompressor_size is necessary as it musht live after all
+ * of the data as well.  Last I measured the decompressor is about 14K.
+ * 10K of actuall data and 4K of bss.
+ *
+ */
+
 /*
  * gzip declarations
  */
@@ -28,15 +113,20 @@ typedef unsigned char  uch;
 typedef unsigned short ush;
 typedef unsigned long  ulg;
 
-#define WSIZE 0x8000           /* Window size must be at least 32k, */
-                               /* and a power of two */
+#define WSIZE 0x80000000       /* Window size must be at least 32k,
+                                * and a power of two
+                                * We don't actually have a window just
+                                * a huge output buffer so I report
+                                * a 2G windows size, as that should
+                                * always be larger than our output buffer.
+                                */
 
-static uch *inbuf;          /* input buffer */
-static uch window[WSIZE];    /* Sliding window buffer */
+static uch *inbuf;     /* input buffer */
+static uch *window;    /* Sliding window buffer, (and final output buffer) */
 
-static unsigned insize = 0;  /* valid bytes in inbuf */
-static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;  /* bytes in output buffer */
+static unsigned insize;  /* valid bytes in inbuf */
+static unsigned inptr;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt;  /* bytes in output buffer */
 
 /* gzip flag byte */
 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
@@ -87,8 +177,6 @@ extern unsigned char input_data[];
 extern int input_len;
 
 static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
 
 static void *malloc(int size);
 static void free(void *where);
@@ -98,17 +186,10 @@ static void *memcpy(void *dest, const void *src, unsigned n);
 
 static void putstr(const char *);
 
-extern int end;
-static long free_mem_ptr = (long)&end;
+static long free_mem_ptr;
 static long free_mem_end_ptr;
 
-#define INPLACE_MOVE_ROUTINE  0x1000
-#define LOW_BUFFER_START      0x2000
-#define LOW_BUFFER_MAX       0x90000
-#define HEAP_SIZE             0x3000
-static unsigned int low_buffer_end, low_buffer_size;
-static int high_loaded =0;
-static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
+#define HEAP_SIZE             0x7000
 
 static char *vidmem = (char *)0xb8000;
 static int vidport;
@@ -218,58 +299,31 @@ static void* memcpy(void* dest, const void* src, unsigned n)
  */
 static int fill_inbuf(void)
 {
-       if (insize != 0) {
-               error("ran out of input data");
-       }
-
-       inbuf = input_data;
-       insize = input_len;
-       inptr = 1;
-       return inbuf[0];
+       error("ran out of input data");
+       return 0;
 }
 
 /* ===========================================================================
  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  * (Used for the decompressed data only.)
  */
-static void flush_window_low(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in, *out, ch;
-    
-    in = window;
-    out = &output_data[output_ptr]; 
-    for (n = 0; n < outcnt; n++) {
-           ch = *out++ = *in++;
-           c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    output_ptr += (ulg)outcnt;
-    outcnt = 0;
-}
-
-static void flush_window_high(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in,  ch;
-    in = window;
-    for (n = 0; n < outcnt; n++) {
-       ch = *output_data++ = *in++;
-       if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start;
-       c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    outcnt = 0;
-}
-
 static void flush_window(void)
 {
-       if (high_loaded) flush_window_high();
-       else flush_window_low();
+       /* With my window equal to my output buffer
+        * I only need to compute the crc here.
+        */
+       ulg c = crc;         /* temporary variable */
+       unsigned n;
+       uch *in, ch;
+
+       in = window;
+       for (n = 0; n < outcnt; n++) {
+               ch = *in++;
+               c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+       }
+       crc = c;
+       bytes_out += (ulg)outcnt;
+       outcnt = 0;
 }
 
 static void error(char *x)
@@ -281,57 +335,8 @@ static void error(char *x)
        while(1);       /* Halt */
 }
 
-static void setup_normal_output_buffer(void)
-{
-#ifdef STANDARD_MEMORY_BIOS_CALL
-       if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory");
-#else
-       if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
-#endif
-       output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
-       free_mem_end_ptr = (long)real_mode;
-}
-
-struct moveparams {
-       uch *low_buffer_start;  int lcount;
-       uch *high_buffer_start; int hcount;
-};
-
-static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
-{
-       high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
-#ifdef STANDARD_MEMORY_BIOS_CALL
-       if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
-#else
-       if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
-#endif 
-       mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
-       low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
-         ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
-       low_buffer_size = low_buffer_end - LOW_BUFFER_START;
-       high_loaded = 1;
-       free_mem_end_ptr = (long)high_buffer_start;
-       if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) {
-               high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size);
-               mv->hcount = 0; /* say: we need not to move high_buffer */
-       }
-       else mv->hcount = -1;
-       mv->high_buffer_start = high_buffer_start;
-}
-
-static void close_output_buffer_if_we_run_high(struct moveparams *mv)
-{
-       if (bytes_out > low_buffer_size) {
-               mv->lcount = low_buffer_size;
-               if (mv->hcount)
-                       mv->hcount = bytes_out - low_buffer_size;
-       } else {
-               mv->lcount = bytes_out;
-               mv->hcount = 0;
-       }
-}
-
-int decompress_kernel(struct moveparams *mv, void *rmode)
+asmlinkage void decompress_kernel(void *rmode, unsigned long heap,
+       uch *input_data, unsigned long input_len, uch *output)
 {
        real_mode = rmode;
 
@@ -346,13 +351,21 @@ int decompress_kernel(struct moveparams *mv, void *rmode)
        lines = RM_SCREEN_INFO.orig_video_lines;
        cols = RM_SCREEN_INFO.orig_video_cols;
 
-       if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
-       else setup_output_buffer_if_we_run_high(mv);
+       window = output;                /* Output buffer (Normally at 1M) */
+       free_mem_ptr     = heap;        /* Heap  */
+       free_mem_end_ptr = heap + HEAP_SIZE;
+       inbuf  = input_data;            /* Input buffer */
+       insize = input_len;
+       inptr  = 0;
+
+       if ((ulg)output & (__KERNEL_ALIGN - 1))
+               error("Destination address not 2M aligned");
+       if ((ulg)output >= 0xffffffffffUL)
+               error("Destination address too large");
 
        makecrc();
        putstr(".\nDecompressing Linux...");
        gunzip();
        putstr("done.\nBooting the kernel.\n");
-       if (high_loaded) close_output_buffer_if_we_run_high(mv);
-       return high_loaded;
+       return;
 }
diff --git a/arch/x86_64/boot/compressed/vmlinux.lds b/arch/x86_64/boot/compressed/vmlinux.lds
new file mode 100644 (file)
index 0000000..94c13e5
--- /dev/null
@@ -0,0 +1,44 @@
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(startup_64)
+SECTIONS
+{
+       /* Be careful parts of head.S assume startup_32 is at
+        * address 0.
+        */
+       . = 0;
+       .text : {
+               _head = . ;
+               *(.text.head)
+               _ehead = . ;
+               *(.text.compressed)
+               _text = .;      /* Text */
+               *(.text)
+               *(.text.*)
+               _etext = . ;
+       }
+       .rodata : {
+               _rodata = . ;
+               *(.rodata)       /* read-only data */
+               *(.rodata.*)
+               _erodata = . ;
+       }
+       .data : {
+               _data = . ;
+               *(.data)
+               *(.data.*)
+               _edata = . ;
+       }
+       .bss : {
+               _bss = . ;
+               *(.bss)
+               *(.bss.*)
+               *(COMMON)
+               . = ALIGN(8);
+               _end = . ;
+               . = ALIGN(4096);
+               pgtable = . ;
+               . = . + 4096 * 6;
+               _heap = .;
+       }
+}
index 1ed9d79..bd1429c 100644 (file)
@@ -1,9 +1,10 @@
 SECTIONS
 {
-  .data : { 
+  .text.compressed : {
        input_len = .;
-       LONG(input_data_end - input_data) input_data = .; 
-       *(.data) 
-       input_data_end = .; 
+       LONG(input_data_end - input_data) input_data = .;
+       *(.data)
+       output_len = . - 4;
+       input_data_end = .;
        }
 }
index 770940c..e9e33f9 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page.h>
+#include <asm/setup.h>
 
 /* Signature words to ensure LILO loaded us right */
 #define SIG1   0xAA55
@@ -80,7 +81,7 @@ start:
 # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
 
                .ascii  "HdrS"          # header signature
-               .word   0x0204          # header version number (>= 0x0105)
+               .word   0x0206          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
 start_sys_seg: .word   SYSSEG
@@ -155,7 +156,20 @@ cmd_line_ptr:      .long 0                 # (Header version 0x0202 or later)
                                        # low memory 0x10000 or higher.
 
 ramdisk_max:   .long 0xffffffff
-       
+kernel_alignment:  .long 0x200000       # physical addr alignment required for
+                                       # protected mode relocatable kernel
+#ifdef CONFIG_RELOCATABLE
+relocatable_kernel:    .byte 1
+#else
+relocatable_kernel:    .byte 0
+#endif
+pad2:                  .byte 0
+pad3:                  .word 0
+
+cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
+                                                #added with boot protocol
+                                                #version 2.06
+
 trampoline:    call    start_of_setup
                .align 16
                                        # The offset at this point is 0x240
@@ -290,64 +304,10 @@ loader_ok:
        movw    %cs,%ax
        movw    %ax,%ds
        
-       /* minimum CPUID flags for x86-64 */
-       /* see http://www.x86-64.org/lists/discuss/msg02971.html */             
-#define SSE_MASK ((1<<25)|(1<<26))
-#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
-                                          (1<<13)|(1<<15)|(1<<24))
-#define REQUIRED_MASK2 (1<<29)
-
-       pushfl                          /* standard way to check for cpuid */
-       popl    %eax
-       movl    %eax,%ebx
-       xorl    $0x200000,%eax
-       pushl   %eax
-       popfl
-       pushfl
-       popl    %eax
-       cmpl    %eax,%ebx
-       jz      no_longmode             /* cpu has no cpuid */
-       movl    $0x0,%eax
-       cpuid
-       cmpl    $0x1,%eax
-       jb      no_longmode             /* no cpuid 1 */
-       xor     %di,%di
-       cmpl    $0x68747541,%ebx        /* AuthenticAMD */
-       jnz     noamd
-       cmpl    $0x69746e65,%edx
-       jnz     noamd
-       cmpl    $0x444d4163,%ecx
-       jnz     noamd
-       mov     $1,%di                  /* cpu is from AMD */
-noamd:         
-       movl    $0x1,%eax
-       cpuid
-       andl    $REQUIRED_MASK1,%edx
-       xorl    $REQUIRED_MASK1,%edx
-       jnz     no_longmode
-       movl    $0x80000000,%eax
-       cpuid
-       cmpl    $0x80000001,%eax
-       jb      no_longmode             /* no extended cpuid */
-       movl    $0x80000001,%eax
-       cpuid
-       andl    $REQUIRED_MASK2,%edx
-       xorl    $REQUIRED_MASK2,%edx
-       jnz     no_longmode
-sse_test:              
-       movl    $1,%eax
-       cpuid
-       andl    $SSE_MASK,%edx
-       cmpl    $SSE_MASK,%edx
-       je      sse_ok
-       test    %di,%di
-       jz      no_longmode     /* only try to force SSE on AMD */ 
-       movl    $0xc0010015,%ecx        /* HWCR */
-       rdmsr
-       btr     $15,%eax        /* enable SSE */
-       wrmsr
-       xor     %di,%di         /* don't loop */
-       jmp     sse_test        /* try again */ 
+       call verify_cpu
+       testl %eax,%eax
+       jz sse_ok
+
 no_longmode:
        call    beep
        lea     long_mode_panic,%si
@@ -357,7 +317,8 @@ no_longmode_loop:
 long_mode_panic:
        .string "Your CPU does not support long mode. Use a 32bit distribution."
        .byte 0
-       
+
+#include "../kernel/verify_cpu.S"
 sse_ok:
        popw    %ds
        
@@ -846,7 +807,7 @@ gdt_48:
 
 # Include video setup & detection code
 
-#include "video.S"
+#include "../../i386/boot/video.S"
 
 # Setup signature -- must be last
 setup_sig1:    .word   SIG1
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
deleted file mode 100644 (file)
index 6090516..0000000
+++ /dev/null
@@ -1,2043 +0,0 @@
-/*     video.S
- *
- *     Display adapter & video mode setup, version 2.13 (14-May-99)
- *
- *     Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
- *     Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
- *
- *     Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
- *
- *     For further information, look at Documentation/svga.txt.
- *
- */
-
-/* Enable autodetection of SVGA adapters and modes. */
-#undef CONFIG_VIDEO_SVGA
-
-/* Enable autodetection of VESA modes */
-#define CONFIG_VIDEO_VESA
-
-/* Enable compacting of mode table */
-#define CONFIG_VIDEO_COMPACT
-
-/* Retain screen contents when switching modes */
-#define CONFIG_VIDEO_RETAIN
-
-/* Enable local mode list */
-#undef CONFIG_VIDEO_LOCAL
-
-/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
-#undef CONFIG_VIDEO_400_HACK
-
-/* Hack that lets you force specific BIOS mode ID and specific dimensions */
-#undef CONFIG_VIDEO_GFX_HACK
-#define VIDEO_GFX_BIOS_AX 0x4f02       /* 800x600 on ThinkPad */
-#define VIDEO_GFX_BIOS_BX 0x0102
-#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425      /* 100x37 */
-
-/* This code uses an extended set of video mode numbers. These include:
- * Aliases for standard modes
- *     NORMAL_VGA (-1)
- *     EXTENDED_VGA (-2)
- *     ASK_VGA (-3)
- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
- * of compatibility when extending the table. These are between 0x00 and 0xff.
- */
-#define VIDEO_FIRST_MENU 0x0000
-
-/* Standard BIOS video modes (BIOS number + 0x0100) */
-#define VIDEO_FIRST_BIOS 0x0100
-
-/* VESA BIOS video modes (VESA number + 0x0200) */
-#define VIDEO_FIRST_VESA 0x0200
-
-/* Video7 special modes (BIOS number + 0x0900) */
-#define VIDEO_FIRST_V7 0x0900
-
-/* Special video modes */
-#define VIDEO_FIRST_SPECIAL 0x0f00
-#define VIDEO_80x25 0x0f00
-#define VIDEO_8POINT 0x0f01
-#define VIDEO_80x43 0x0f02
-#define VIDEO_80x28 0x0f03
-#define VIDEO_CURRENT_MODE 0x0f04
-#define VIDEO_80x30 0x0f05
-#define VIDEO_80x34 0x0f06
-#define VIDEO_80x60 0x0f07
-#define VIDEO_GFX_HACK 0x0f08
-#define VIDEO_LAST_SPECIAL 0x0f09
-
-/* Video modes given by resolution */
-#define VIDEO_FIRST_RESOLUTION 0x1000
-
-/* The "recalculate timings" flag */
-#define VIDEO_RECALC 0x8000
-
-/* Positions of various video parameters passed to the kernel */
-/* (see also include/linux/tty.h) */
-#define PARAM_CURSOR_POS       0x00
-#define PARAM_VIDEO_PAGE       0x04
-#define PARAM_VIDEO_MODE       0x06
-#define PARAM_VIDEO_COLS       0x07
-#define PARAM_VIDEO_EGA_BX     0x0a
-#define PARAM_VIDEO_LINES      0x0e
-#define PARAM_HAVE_VGA         0x0f
-#define PARAM_FONT_POINTS      0x10
-
-#define PARAM_LFB_WIDTH                0x12
-#define PARAM_LFB_HEIGHT       0x14
-#define PARAM_LFB_DEPTH                0x16
-#define PARAM_LFB_BASE         0x18
-#define PARAM_LFB_SIZE         0x1c
-#define PARAM_LFB_LINELENGTH   0x24
-#define PARAM_LFB_COLORS       0x26
-#define PARAM_VESAPM_SEG       0x2e
-#define PARAM_VESAPM_OFF       0x30
-#define PARAM_LFB_PAGES                0x32
-#define PARAM_VESA_ATTRIB      0x34
-#define PARAM_CAPABILITIES     0x36
-
-/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
-#ifdef CONFIG_VIDEO_RETAIN
-#define DO_STORE call store_screen
-#else
-#define DO_STORE
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# This is the main entry point called by setup.S
-# %ds *must* be pointing to the bootsector
-video: pushw   %ds             # We use different segments
-       pushw   %ds             # FS contains original DS
-       popw    %fs
-       pushw   %cs             # DS is equal to CS
-       popw    %ds
-       pushw   %cs             # ES is equal to CS
-       popw    %es
-       xorw    %ax, %ax
-       movw    %ax, %gs        # GS is zero
-       cld
-       call    basic_detect    # Basic adapter type testing (EGA/VGA/MDA/CGA)
-#ifdef CONFIG_VIDEO_SELECT
-       movw    %fs:(0x01fa), %ax               # User selected video mode
-       cmpw    $ASK_VGA, %ax                   # Bring up the menu
-       jz      vid2
-
-       call    mode_set                        # Set the mode
-       jc      vid1
-
-       leaw    badmdt, %si                     # Invalid mode ID
-       call    prtstr
-vid2:  call    mode_menu
-vid1:
-#ifdef CONFIG_VIDEO_RETAIN
-       call    restore_screen                  # Restore screen contents
-#endif /* CONFIG_VIDEO_RETAIN */
-       call    store_edid
-#endif /* CONFIG_VIDEO_SELECT */
-       call    mode_params                     # Store mode parameters
-       popw    %ds                             # Restore original DS
-       ret
-
-# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
-basic_detect:
-       movb    $0, %fs:(PARAM_HAVE_VGA)
-       movb    $0x12, %ah      # Check EGA/VGA
-       movb    $0x10, %bl
-       int     $0x10
-       movw    %bx, %fs:(PARAM_VIDEO_EGA_BX)   # Identifies EGA to the kernel
-       cmpb    $0x10, %bl                      # No, it's a CGA/MDA/HGA card.
-       je      basret
-
-       incb    adapter
-       movw    $0x1a00, %ax                    # Check EGA or VGA?
-       int     $0x10
-       cmpb    $0x1a, %al                      # 1a means VGA...
-       jne     basret                          # anything else is EGA.
-       
-       incb    %fs:(PARAM_HAVE_VGA)            # We've detected a VGA
-       incb    adapter
-basret:        ret
-
-# Store the video mode parameters for later usage by the kernel.
-# This is done by asking the BIOS except for the rows/columns
-# parameters in the default 80x25 mode -- these are set directly,
-# because some very obscure BIOSes supply insane values.
-mode_params:
-#ifdef CONFIG_VIDEO_SELECT
-       cmpb    $0, graphic_mode
-       jnz     mopar_gr
-#endif
-       movb    $0x03, %ah                      # Read cursor position
-       xorb    %bh, %bh
-       int     $0x10
-       movw    %dx, %fs:(PARAM_CURSOR_POS)
-       movb    $0x0f, %ah                      # Read page/mode/width
-       int     $0x10
-       movw    %bx, %fs:(PARAM_VIDEO_PAGE)
-       movw    %ax, %fs:(PARAM_VIDEO_MODE)     # Video mode and screen width
-       cmpb    $0x7, %al                       # MDA/HGA => segment differs
-       jnz     mopar0
-
-       movw    $0xb000, video_segment
-mopar0: movw   %gs:(0x485), %ax                # Font size
-       movw    %ax, %fs:(PARAM_FONT_POINTS)    # (valid only on EGA/VGA)
-       movw    force_size, %ax                 # Forced size?
-       orw     %ax, %ax
-       jz      mopar1
-
-       movb    %ah, %fs:(PARAM_VIDEO_COLS)
-       movb    %al, %fs:(PARAM_VIDEO_LINES)
-       ret
-
-mopar1:        movb    $25, %al
-       cmpb    $0, adapter                     # If we are on CGA/MDA/HGA, the
-       jz      mopar2                          # screen must have 25 lines.
-
-       movb    %gs:(0x484), %al                # On EGA/VGA, use the EGA+ BIOS
-       incb    %al                             # location of max lines.
-mopar2: movb   %al, %fs:(PARAM_VIDEO_LINES)
-       ret
-
-#ifdef CONFIG_VIDEO_SELECT
-# Fetching of VESA frame buffer parameters
-mopar_gr:
-       leaw    modelist+1024, %di
-       movb    $0x23, %fs:(PARAM_HAVE_VGA)
-       movw    16(%di), %ax
-       movw    %ax, %fs:(PARAM_LFB_LINELENGTH)
-       movw    18(%di), %ax
-       movw    %ax, %fs:(PARAM_LFB_WIDTH)
-       movw    20(%di), %ax
-       movw    %ax, %fs:(PARAM_LFB_HEIGHT)
-       movb    25(%di), %al
-       movb    $0, %ah
-       movw    %ax, %fs:(PARAM_LFB_DEPTH)
-       movb    29(%di), %al    
-       movb    $0, %ah
-       movw    %ax, %fs:(PARAM_LFB_PAGES)
-       movl    40(%di), %eax
-       movl    %eax, %fs:(PARAM_LFB_BASE)
-       movl    31(%di), %eax
-       movl    %eax, %fs:(PARAM_LFB_COLORS)
-       movl    35(%di), %eax
-       movl    %eax, %fs:(PARAM_LFB_COLORS+4)
-       movw    0(%di), %ax
-       movw    %ax, %fs:(PARAM_VESA_ATTRIB)
-
-# get video mem size
-       leaw    modelist+1024, %di
-       movw    $0x4f00, %ax
-       int     $0x10
-       xorl    %eax, %eax
-       movw    18(%di), %ax
-       movl    %eax, %fs:(PARAM_LFB_SIZE)
-
-# store mode capabilities
-       movl 10(%di), %eax
-       movl %eax, %fs:(PARAM_CAPABILITIES)
-
-# switching the DAC to 8-bit is for <= 8 bpp only
-       movw    %fs:(PARAM_LFB_DEPTH), %ax
-       cmpw    $8, %ax
-       jg      dac_done
-
-# get DAC switching capability
-       xorl    %eax, %eax
-       movb    10(%di), %al
-       testb   $1, %al
-       jz      dac_set
-
-# attempt to switch DAC to 8-bit
-       movw    $0x4f08, %ax
-       movw    $0x0800, %bx
-       int     $0x10
-       cmpw    $0x004f, %ax
-       jne     dac_set
-       movb    %bh, dac_size           # store actual DAC size
-
-dac_set:
-# set color size to DAC size
-       movb    dac_size, %al
-       movb    %al, %fs:(PARAM_LFB_COLORS+0)
-       movb    %al, %fs:(PARAM_LFB_COLORS+2)
-       movb    %al, %fs:(PARAM_LFB_COLORS+4)
-       movb    %al, %fs:(PARAM_LFB_COLORS+6)
-
-# set color offsets to 0
-       movb    $0, %fs:(PARAM_LFB_COLORS+1)
-       movb    $0, %fs:(PARAM_LFB_COLORS+3)
-       movb    $0, %fs:(PARAM_LFB_COLORS+5)
-       movb    $0, %fs:(PARAM_LFB_COLORS+7)
-
-dac_done:
-# get protected mode interface informations
-       movw    $0x4f0a, %ax
-       xorw    %bx, %bx
-       xorw    %di, %di
-       int     $0x10
-       cmp     $0x004f, %ax
-       jnz     no_pm
-
-       movw    %es, %fs:(PARAM_VESAPM_SEG)
-       movw    %di, %fs:(PARAM_VESAPM_OFF)
-no_pm: ret
-
-# The video mode menu
-mode_menu:
-       leaw    keymsg, %si                     # "Return/Space/Timeout" message
-       call    prtstr
-       call    flush
-nokey: call    getkt
-
-       cmpb    $0x0d, %al                      # ENTER ?
-       je      listm                           # yes - manual mode selection
-
-       cmpb    $0x20, %al                      # SPACE ?
-       je      defmd1                          # no - repeat
-
-       call    beep
-       jmp     nokey
-
-defmd1:        ret                                     # No mode chosen? Default 80x25
-
-listm: call    mode_table                      # List mode table
-listm0:        leaw    name_bann, %si                  # Print adapter name
-       call    prtstr
-       movw    card_name, %si
-       orw     %si, %si
-       jnz     an2
-
-       movb    adapter, %al
-       leaw    old_name, %si
-       orb     %al, %al
-       jz      an1
-
-       leaw    ega_name, %si
-       decb    %al
-       jz      an1
-
-       leaw    vga_name, %si
-       jmp     an1
-
-an2:   call    prtstr
-       leaw    svga_name, %si
-an1:   call    prtstr
-       leaw    listhdr, %si                    # Table header
-       call    prtstr
-       movb    $0x30, %dl                      # DL holds mode number
-       leaw    modelist, %si
-lm1:   cmpw    $ASK_VGA, (%si)                 # End?
-       jz      lm2
-
-       movb    %dl, %al                        # Menu selection number
-       call    prtchr
-       call    prtsp2
-       lodsw
-       call    prthw                           # Mode ID
-       call    prtsp2
-       movb    0x1(%si), %al
-       call    prtdec                          # Rows
-       movb    $0x78, %al                      # the letter 'x'
-       call    prtchr
-       lodsw
-       call    prtdec                          # Columns
-       movb    $0x0d, %al                      # New line
-       call    prtchr
-       movb    $0x0a, %al
-       call    prtchr
-       incb    %dl                             # Next character
-       cmpb    $0x3a, %dl
-       jnz     lm1
-
-       movb    $0x61, %dl
-       jmp     lm1
-
-lm2:   leaw    prompt, %si                     # Mode prompt
-       call    prtstr
-       leaw    edit_buf, %di                   # Editor buffer
-lm3:   call    getkey
-       cmpb    $0x0d, %al                      # Enter?
-       jz      lment
-
-       cmpb    $0x08, %al                      # Backspace?
-       jz      lmbs
-
-       cmpb    $0x20, %al                      # Printable?
-       jc      lm3
-
-       cmpw    $edit_buf+4, %di                # Enough space?
-       jz      lm3
-
-       stosb
-       call    prtchr
-       jmp     lm3
-
-lmbs:  cmpw    $edit_buf, %di                  # Backspace
-       jz      lm3
-
-       decw    %di
-       movb    $0x08, %al
-       call    prtchr
-       call    prtspc
-       movb    $0x08, %al
-       call    prtchr
-       jmp     lm3
-       
-lment: movb    $0, (%di)
-       leaw    crlft, %si
-       call    prtstr
-       leaw    edit_buf, %si
-       cmpb    $0, (%si)                       # Empty string = default mode
-       jz      lmdef
-
-       cmpb    $0, 1(%si)                      # One character = menu selection
-       jz      mnusel
-
-       cmpw    $0x6373, (%si)                  # "scan" => mode scanning
-       jnz     lmhx
-
-       cmpw    $0x6e61, 2(%si)
-       jz      lmscan
-
-lmhx:  xorw    %bx, %bx                        # Else => mode ID in hex
-lmhex: lodsb
-       orb     %al, %al
-       jz      lmuse1
-
-       subb    $0x30, %al
-       jc      lmbad
-
-       cmpb    $10, %al
-       jc      lmhx1
-
-       subb    $7, %al
-       andb    $0xdf, %al
-       cmpb    $10, %al
-       jc      lmbad
-
-       cmpb    $16, %al
-       jnc     lmbad
-
-lmhx1: shlw    $4, %bx
-       orb     %al, %bl
-       jmp     lmhex
-
-lmuse1:        movw    %bx, %ax
-       jmp     lmuse
-
-mnusel:        lodsb                                   # Menu selection
-       xorb    %ah, %ah
-       subb    $0x30, %al
-       jc      lmbad
-
-       cmpb    $10, %al
-       jc      lmuse
-       
-       cmpb    $0x61-0x30, %al
-       jc      lmbad
-       
-       subb    $0x61-0x30-10, %al
-       cmpb    $36, %al
-       jnc     lmbad
-
-lmuse: call    mode_set
-       jc      lmdef
-
-lmbad: leaw    unknt, %si
-       call    prtstr
-       jmp     lm2
-lmscan:        cmpb    $0, adapter                     # Scanning only on EGA/VGA
-       jz      lmbad
-
-       movw    $0, mt_end                      # Scanning of modes is
-       movb    $1, scanning                    # done as new autodetection.
-       call    mode_table
-       jmp     listm0
-lmdef: ret
-
-# Additional parts of mode_set... (relative jumps, you know)
-setv7:                                         # Video7 extended modes
-       DO_STORE
-       subb    $VIDEO_FIRST_V7>>8, %bh
-       movw    $0x6f05, %ax
-       int     $0x10
-       stc
-       ret
-
-_setrec:       jmp     setrec                  # Ugly...
-_set_80x25:    jmp     set_80x25
-
-# Aliases for backward compatibility.
-setalias:
-       movw    $VIDEO_80x25, %ax
-       incw    %bx
-       jz      mode_set
-
-       movb    $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
-       incw    %bx
-       jnz     setbad                          # Fall-through!
-
-# Setting of user mode (AX=mode ID) => CF=success
-mode_set:
-       movw    %ax, %fs:(0x01fa)               # Store mode for use in acpi_wakeup.S
-       movw    %ax, %bx
-       cmpb    $0xff, %ah
-       jz      setalias
-
-       testb   $VIDEO_RECALC>>8, %ah
-       jnz     _setrec
-
-       cmpb    $VIDEO_FIRST_RESOLUTION>>8, %ah
-       jnc     setres
-       
-       cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
-       jz      setspc
-       
-       cmpb    $VIDEO_FIRST_V7>>8, %ah
-       jz      setv7
-       
-       cmpb    $VIDEO_FIRST_VESA>>8, %ah
-       jnc     check_vesa
-       
-       orb     %ah, %ah
-       jz      setmenu
-       
-       decb    %ah
-       jz      setbios
-
-setbad:        clc
-       movb    $0, do_restore                  # The screen needn't be restored
-       ret
-
-setvesa:
-       DO_STORE
-       subb    $VIDEO_FIRST_VESA>>8, %bh
-       movw    $0x4f02, %ax                    # VESA BIOS mode set call
-       int     $0x10
-       cmpw    $0x004f, %ax                    # AL=4f if implemented
-       jnz     setbad                          # AH=0 if OK
-
-       stc
-       ret
-
-setbios:
-       DO_STORE
-       int     $0x10                           # Standard BIOS mode set call
-       pushw   %bx
-       movb    $0x0f, %ah                      # Check if really set
-       int     $0x10
-       popw    %bx
-       cmpb    %bl, %al
-       jnz     setbad
-       
-       stc
-       ret
-
-setspc:        xorb    %bh, %bh                        # Set special mode
-       cmpb    $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
-       jnc     setbad
-       
-       addw    %bx, %bx
-       jmp     *spec_inits(%bx)
-
-setmenu:
-       orb     %al, %al                        # 80x25 is an exception
-       jz      _set_80x25
-       
-       pushw   %bx                             # Set mode chosen from menu
-       call    mode_table                      # Build the mode table
-       popw    %ax
-       shlw    $2, %ax
-       addw    %ax, %si
-       cmpw    %di, %si
-       jnc     setbad
-       
-       movw    (%si), %ax                      # Fetch mode ID
-_m_s:  jmp     mode_set
-
-setres:        pushw   %bx                             # Set mode chosen by resolution
-       call    mode_table
-       popw    %bx
-       xchgb   %bl, %bh
-setr1: lodsw
-       cmpw    $ASK_VGA, %ax                   # End of the list?
-       jz      setbad
-       
-       lodsw
-       cmpw    %bx, %ax
-       jnz     setr1
-       
-       movw    -4(%si), %ax                    # Fetch mode ID
-       jmp     _m_s
-
-check_vesa:
-#ifdef CONFIG_FIRMWARE_EDID
-       leaw    modelist+1024, %di
-       movw    $0x4f00, %ax
-       int     $0x10
-       cmpw    $0x004f, %ax
-       jnz     setbad
-
-       movw    4(%di), %ax
-       movw    %ax, vbe_version
-#endif
-       leaw    modelist+1024, %di
-       subb    $VIDEO_FIRST_VESA>>8, %bh
-       movw    %bx, %cx                        # Get mode information structure
-       movw    $0x4f01, %ax
-       int     $0x10
-       addb    $VIDEO_FIRST_VESA>>8, %bh
-       cmpw    $0x004f, %ax
-       jnz     setbad
-
-       movb    (%di), %al                      # Check capabilities.
-       andb    $0x19, %al
-       cmpb    $0x09, %al
-       jz      setvesa                         # This is a text mode
-
-       movb    (%di), %al                      # Check capabilities.
-       andb    $0x99, %al
-       cmpb    $0x99, %al
-       jnz     _setbad                         # Doh! No linear frame buffer.
-
-       subb    $VIDEO_FIRST_VESA>>8, %bh
-       orw     $0x4000, %bx                    # Use linear frame buffer
-       movw    $0x4f02, %ax                    # VESA BIOS mode set call
-       int     $0x10
-       cmpw    $0x004f, %ax                    # AL=4f if implemented
-       jnz     _setbad                         # AH=0 if OK
-
-       movb    $1, graphic_mode                # flag graphic mode
-       movb    $0, do_restore                  # no screen restore
-       stc
-       ret
-
-_setbad:       jmp     setbad                  # Ugly...
-
-# Recalculate vertical display end registers -- this fixes various
-# inconsistencies of extended modes on many adapters. Called when
-# the VIDEO_RECALC flag is set in the mode ID.
-
-setrec:        subb    $VIDEO_RECALC>>8, %ah           # Set the base mode
-       call    mode_set
-       jnc     rct3
-
-       movw    %gs:(0x485), %ax                # Font size in pixels
-       movb    %gs:(0x484), %bl                # Number of rows
-       incb    %bl
-       mulb    %bl                             # Number of visible
-       decw    %ax                             # scan lines - 1
-       movw    $0x3d4, %dx
-       movw    %ax, %bx
-       movb    $0x12, %al                      # Lower 8 bits
-       movb    %bl, %ah
-       outw    %ax, %dx
-       movb    $0x07, %al              # Bits 8 and 9 in the overflow register
-       call    inidx
-       xchgb   %al, %ah
-       andb    $0xbd, %ah
-       shrb    %bh
-       jnc     rct1
-       orb     $0x02, %ah
-rct1:  shrb    %bh
-       jnc     rct2
-       orb     $0x40, %ah
-rct2:  movb    $0x07, %al
-       outw    %ax, %dx
-       stc
-rct3:  ret
-
-# Table of routines for setting of the special modes.
-spec_inits:
-       .word   set_80x25
-       .word   set_8pixel
-       .word   set_80x43
-       .word   set_80x28
-       .word   set_current
-       .word   set_80x30
-       .word   set_80x34
-       .word   set_80x60
-       .word   set_gfx
-
-# Set the 80x25 mode. If already set, do nothing.
-set_80x25:
-       movw    $0x5019, force_size             # Override possibly broken BIOS
-use_80x25:
-#ifdef CONFIG_VIDEO_400_HACK
-       movw    $0x1202, %ax                    # Force 400 scan lines
-       movb    $0x30, %bl
-       int     $0x10
-#else
-       movb    $0x0f, %ah                      # Get current mode ID
-       int     $0x10
-       cmpw    $0x5007, %ax    # Mode 7 (80x25 mono) is the only one available
-       jz      st80            # on CGA/MDA/HGA and is also available on EGAM
-
-       cmpw    $0x5003, %ax    # Unknown mode, force 80x25 color
-       jnz     force3
-
-st80:  cmpb    $0, adapter     # CGA/MDA/HGA => mode 3/7 is always 80x25
-       jz      set80
-
-       movb    %gs:(0x0484), %al       # This is EGA+ -- beware of 80x50 etc.
-       orb     %al, %al                # Some buggy BIOS'es set 0 rows
-       jz      set80
-       
-       cmpb    $24, %al                # It's hopefully correct
-       jz      set80
-#endif /* CONFIG_VIDEO_400_HACK */
-force3:        DO_STORE
-       movw    $0x0003, %ax                    # Forced set
-       int     $0x10
-set80: stc
-       ret
-
-# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
-set_8pixel:
-       DO_STORE
-       call    use_80x25                       # The base is 80x25
-set_8pt:
-       movw    $0x1112, %ax                    # Use 8x8 font
-       xorb    %bl, %bl
-       int     $0x10
-       movw    $0x1200, %ax                    # Use alternate print screen
-       movb    $0x20, %bl
-       int     $0x10
-       movw    $0x1201, %ax                    # Turn off cursor emulation
-       movb    $0x34, %bl
-       int     $0x10
-       movb    $0x01, %ah                      # Define cursor scan lines 6-7
-       movw    $0x0607, %cx
-       int     $0x10
-set_current:
-       stc
-       ret
-
-# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
-# 80x25 mode with 14-point fonts instead of 16-point.
-set_80x28:
-       DO_STORE
-       call    use_80x25                       # The base is 80x25
-set14: movw    $0x1111, %ax                    # Use 9x14 font
-       xorb    %bl, %bl
-       int     $0x10
-       movb    $0x01, %ah                      # Define cursor scan lines 11-12
-       movw    $0x0b0c, %cx
-       int     $0x10
-       stc
-       ret
-
-# Set the 80x43 mode. This mode is works on all VGA's.
-# It's a 350-scanline mode with 8-pixel font.
-set_80x43:
-       DO_STORE
-       movw    $0x1201, %ax                    # Set 350 scans
-       movb    $0x30, %bl
-       int     $0x10
-       movw    $0x0003, %ax                    # Reset video mode
-       int     $0x10
-       jmp     set_8pt                         # Use 8-pixel font
-
-# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
-set_80x30:
-       call    use_80x25                       # Start with real 80x25
-       DO_STORE
-       movw    $0x3cc, %dx                     # Get CRTC port
-       inb     %dx, %al
-       movb    $0xd4, %dl
-       rorb    %al                             # Mono or color?
-       jc      set48a
-
-       movb    $0xb4, %dl
-set48a:        movw    $0x0c11, %ax            # Vertical sync end (also unlocks CR0-7)
-       call    outidx
-       movw    $0x0b06, %ax                    # Vertical total
-       call    outidx
-       movw    $0x3e07, %ax                    # (Vertical) overflow
-       call    outidx
-       movw    $0xea10, %ax                    # Vertical sync start
-       call    outidx
-       movw    $0xdf12, %ax                    # Vertical display end
-       call    outidx
-       movw    $0xe715, %ax                    # Vertical blank start
-       call    outidx
-       movw    $0x0416, %ax                    # Vertical blank end
-       call    outidx
-       pushw   %dx
-       movb    $0xcc, %dl                      # Misc output register (read)
-       inb     %dx, %al
-       movb    $0xc2, %dl                      # (write)
-       andb    $0x0d, %al      # Preserve clock select bits and color bit
-       orb     $0xe2, %al                      # Set correct sync polarity
-       outb    %al, %dx
-       popw    %dx
-       movw    $0x501e, force_size
-       stc                                     # That's all.
-       ret
-
-# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
-set_80x34:
-       call    set_80x30                       # Set 480 scans
-       call    set14                           # And 14-pt font
-       movw    $0xdb12, %ax                    # VGA vertical display end
-       movw    $0x5022, force_size
-setvde:        call    outidx
-       stc
-       ret
-
-# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
-set_80x60:
-       call    set_80x30                       # Set 480 scans
-       call    set_8pt                         # And 8-pt font
-       movw    $0xdf12, %ax                    # VGA vertical display end
-       movw    $0x503c, force_size
-       jmp     setvde
-
-# Special hack for ThinkPad graphics
-set_gfx:
-#ifdef CONFIG_VIDEO_GFX_HACK
-       movw    $VIDEO_GFX_BIOS_AX, %ax
-       movw    $VIDEO_GFX_BIOS_BX, %bx
-       int     $0x10
-       movw    $VIDEO_GFX_DUMMY_RESOLUTION, force_size
-       stc
-#endif
-       ret
-
-#ifdef CONFIG_VIDEO_RETAIN
-
-# Store screen contents to temporary buffer.
-store_screen:
-       cmpb    $0, do_restore                  # Already stored?
-       jnz     stsr
-
-       testb   $CAN_USE_HEAP, loadflags        # Have we space for storing?
-       jz      stsr
-       
-       pushw   %ax
-       pushw   %bx
-       pushw   force_size                      # Don't force specific size
-       movw    $0, force_size
-       call    mode_params                     # Obtain params of current mode
-       popw    force_size
-       movb    %fs:(PARAM_VIDEO_LINES), %ah
-       movb    %fs:(PARAM_VIDEO_COLS), %al
-       movw    %ax, %bx                        # BX=dimensions
-       mulb    %ah
-       movw    %ax, %cx                        # CX=number of characters
-       addw    %ax, %ax                        # Calculate image size
-       addw    $modelist+1024+4, %ax
-       cmpw    heap_end_ptr, %ax
-       jnc     sts1                            # Unfortunately, out of memory
-
-       movw    %fs:(PARAM_CURSOR_POS), %ax     # Store mode params
-       leaw    modelist+1024, %di
-       stosw
-       movw    %bx, %ax
-       stosw
-       pushw   %ds                             # Store the screen
-       movw    video_segment, %ds
-       xorw    %si, %si
-       rep
-       movsw
-       popw    %ds
-       incb    do_restore                      # Screen will be restored later
-sts1:  popw    %bx
-       popw    %ax
-stsr:  ret
-
-# Restore screen contents from temporary buffer.
-restore_screen:
-       cmpb    $0, do_restore                  # Has the screen been stored?
-       jz      res1
-
-       call    mode_params                     # Get parameters of current mode
-       movb    %fs:(PARAM_VIDEO_LINES), %cl
-       movb    %fs:(PARAM_VIDEO_COLS), %ch
-       leaw    modelist+1024, %si              # Screen buffer
-       lodsw                                   # Set cursor position
-       movw    %ax, %dx
-       cmpb    %cl, %dh
-       jc      res2
-       
-       movb    %cl, %dh
-       decb    %dh
-res2:  cmpb    %ch, %dl
-       jc      res3
-       
-       movb    %ch, %dl
-       decb    %dl
-res3:  movb    $0x02, %ah
-       movb    $0x00, %bh
-       int     $0x10
-       lodsw                                   # Display size
-       movb    %ah, %dl                        # DL=number of lines
-       movb    $0, %ah                         # BX=phys. length of orig. line
-       movw    %ax, %bx
-       cmpb    %cl, %dl                        # Too many?
-       jc      res4
-
-       pushw   %ax
-       movb    %dl, %al
-       subb    %cl, %al
-       mulb    %bl
-       addw    %ax, %si
-       addw    %ax, %si
-       popw    %ax
-       movb    %cl, %dl
-res4:  cmpb    %ch, %al                        # Too wide?
-       jc      res5
-       
-       movb    %ch, %al                        # AX=width of src. line
-res5:  movb    $0, %cl
-       xchgb   %ch, %cl
-       movw    %cx, %bp                        # BP=width of dest. line
-       pushw   %es
-       movw    video_segment, %es
-       xorw    %di, %di                        # Move the data
-       addw    %bx, %bx                        # Convert BX and BP to _bytes_
-       addw    %bp, %bp
-res6:  pushw   %si
-       pushw   %di
-       movw    %ax, %cx
-       rep
-       movsw
-       popw    %di
-       popw    %si
-       addw    %bp, %di
-       addw    %bx, %si
-       decb    %dl
-       jnz     res6
-       
-       popw    %es                             # Done
-res1:  ret
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
-outidx:        outb    %al, %dx
-       pushw   %ax
-       movb    %ah, %al
-       incw    %dx
-       outb    %al, %dx
-       decw    %dx
-       popw    %ax
-       ret
-
-# Build the table of video modes (stored after the setup.S code at the
-# `modelist' label. Each video mode record looks like:
-#      .word   MODE-ID         (our special mode ID (see above))
-#      .byte   rows            (number of rows)
-#      .byte   columns         (number of columns)
-# Returns address of the end of the table in DI, the end is marked
-# with a ASK_VGA ID.
-mode_table:
-       movw    mt_end, %di                     # Already filled?
-       orw     %di, %di
-       jnz     mtab1x
-       
-       leaw    modelist, %di                   # Store standard modes:
-       movl    $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
-       stosl
-       movb    adapter, %al                    # CGA/MDA/HGA -- no more modes
-       orb     %al, %al
-       jz      mtabe
-       
-       decb    %al
-       jnz     mtabv
-       
-       movl    $VIDEO_8POINT + 0x502b0000, %eax        # The 80x43 EGA mode
-       stosl
-       jmp     mtabe
-
-mtab1x:        jmp     mtab1
-
-mtabv: leaw    vga_modes, %si                  # All modes for std VGA
-       movw    $vga_modes_end-vga_modes, %cx
-       rep     # I'm unable to use movsw as I don't know how to store a half
-       movsb   # of the expression above to cx without using explicit shr.
-
-       cmpb    $0, scanning                    # Mode scan requested?
-       jz      mscan1
-       
-       call    mode_scan
-mscan1:
-
-#ifdef CONFIG_VIDEO_LOCAL
-       call    local_modes
-#endif /* CONFIG_VIDEO_LOCAL */
-
-#ifdef CONFIG_VIDEO_VESA
-       call    vesa_modes                      # Detect VESA VGA modes
-#endif /* CONFIG_VIDEO_VESA */
-
-#ifdef CONFIG_VIDEO_SVGA
-       cmpb    $0, scanning                    # Bypass when scanning
-       jnz     mscan2
-       
-       call    svga_modes                      # Detect SVGA cards & modes
-mscan2:
-#endif /* CONFIG_VIDEO_SVGA */
-
-mtabe:
-
-#ifdef CONFIG_VIDEO_COMPACT
-       leaw    modelist, %si
-       movw    %di, %dx
-       movw    %si, %di
-cmt1:  cmpw    %dx, %si                        # Scan all modes
-       jz      cmt2
-
-       leaw    modelist, %bx                   # Find in previous entries
-       movw    2(%si), %cx
-cmt3:  cmpw    %bx, %si
-       jz      cmt4
-
-       cmpw    2(%bx), %cx                     # Found => don't copy this entry
-       jz      cmt5
-
-       addw    $4, %bx
-       jmp     cmt3
-
-cmt4:  movsl                                   # Copy entry
-       jmp     cmt1
-
-cmt5:  addw    $4, %si                         # Skip entry
-       jmp     cmt1
-
-cmt2:
-#endif /* CONFIG_VIDEO_COMPACT */
-
-       movw    $ASK_VGA, (%di)                 # End marker
-       movw    %di, mt_end
-mtab1: leaw    modelist, %si                   # SI=mode list, DI=list end
-ret0:  ret
-
-# Modes usable on all standard VGAs
-vga_modes:
-       .word   VIDEO_8POINT
-       .word   0x5032                          # 80x50
-       .word   VIDEO_80x43
-       .word   0x502b                          # 80x43
-       .word   VIDEO_80x28
-       .word   0x501c                          # 80x28
-       .word   VIDEO_80x30
-       .word   0x501e                          # 80x30
-       .word   VIDEO_80x34
-       .word   0x5022                          # 80x34
-       .word   VIDEO_80x60
-       .word   0x503c                          # 80x60
-#ifdef CONFIG_VIDEO_GFX_HACK
-       .word   VIDEO_GFX_HACK
-       .word   VIDEO_GFX_DUMMY_RESOLUTION
-#endif
-
-vga_modes_end:
-# Detect VESA modes.
-
-#ifdef CONFIG_VIDEO_VESA
-vesa_modes:
-       cmpb    $2, adapter                     # VGA only
-       jnz     ret0
-
-       movw    %di, %bp                        # BP=original mode table end
-       addw    $0x200, %di                     # Buffer space
-       movw    $0x4f00, %ax                    # VESA Get card info call
-       int     $0x10
-       movw    %bp, %di
-       cmpw    $0x004f, %ax                    # Successful?
-       jnz     ret0
-       
-       cmpw    $0x4556, 0x200(%di)
-       jnz     ret0
-       
-       cmpw    $0x4153, 0x202(%di)
-       jnz     ret0
-       
-       movw    $vesa_name, card_name           # Set name to "VESA VGA"
-       pushw   %gs
-       lgsw    0x20e(%di), %si                 # GS:SI=mode list
-       movw    $128, %cx                       # Iteration limit
-vesa1:
-# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
-# XXX: lodsw   %gs:(%si), %ax                  # Get next mode in the list
-       gs; lodsw
-       cmpw    $0xffff, %ax                    # End of the table?
-       jz      vesar
-       
-       cmpw    $0x0080, %ax                    # Check validity of mode ID
-       jc      vesa2
-       
-       orb     %ah, %ah                # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
-       jz      vesan                   # Certain BIOSes report 0x80-0xff!
-
-       cmpw    $0x0800, %ax
-       jnc     vesae
-
-vesa2: pushw   %cx
-       movw    %ax, %cx                        # Get mode information structure
-       movw    $0x4f01, %ax
-       int     $0x10
-       movw    %cx, %bx                        # BX=mode number
-       addb    $VIDEO_FIRST_VESA>>8, %bh
-       popw    %cx
-       cmpw    $0x004f, %ax
-       jnz     vesan                   # Don't report errors (buggy BIOSES)
-
-       movb    (%di), %al                      # Check capabilities. We require
-       andb    $0x19, %al                      # a color text mode.
-       cmpb    $0x09, %al
-       jnz     vesan
-       
-       cmpw    $0xb800, 8(%di)         # Standard video memory address required
-       jnz     vesan
-
-       testb   $2, (%di)                       # Mode characteristics supplied?
-       movw    %bx, (%di)                      # Store mode number
-       jz      vesa3
-       
-       xorw    %dx, %dx
-       movw    0x12(%di), %bx                  # Width
-       orb     %bh, %bh
-       jnz     vesan
-       
-       movb    %bl, 0x3(%di)
-       movw    0x14(%di), %ax                  # Height
-       orb     %ah, %ah
-       jnz     vesan
-       
-       movb    %al, 2(%di)
-       mulb    %bl
-       cmpw    $8193, %ax              # Small enough for Linux console driver?
-       jnc     vesan
-
-       jmp     vesaok
-
-vesa3: subw    $0x8108, %bx    # This mode has no detailed info specified,
-       jc      vesan           # so it must be a standard VESA mode.
-
-       cmpw    $5, %bx
-       jnc     vesan
-
-       movw    vesa_text_mode_table(%bx), %ax
-       movw    %ax, 2(%di)
-vesaok:        addw    $4, %di                         # The mode is valid. Store it.
-vesan: loop    vesa1                   # Next mode. Limit exceeded => error
-vesae: leaw    vesaer, %si
-       call    prtstr
-       movw    %bp, %di                        # Discard already found modes.
-vesar: popw    %gs
-       ret
-
-# Dimensions of standard VESA text modes
-vesa_text_mode_table:
-       .byte   60, 80                          # 0108
-       .byte   25, 132                         # 0109
-       .byte   43, 132                         # 010A
-       .byte   50, 132                         # 010B
-       .byte   60, 132                         # 010C
-#endif /* CONFIG_VIDEO_VESA */
-
-# Scan for video modes. A bit dirty, but should work.
-mode_scan:
-       movw    $0x0100, %cx                    # Start with mode 0
-scm1:  movb    $0, %ah                         # Test the mode
-       movb    %cl, %al
-       int     $0x10
-       movb    $0x0f, %ah
-       int     $0x10
-       cmpb    %cl, %al
-       jnz     scm2                            # Mode not set
-
-       movw    $0x3c0, %dx                     # Test if it's a text mode
-       movb    $0x10, %al                      # Mode bits
-       call    inidx
-       andb    $0x03, %al
-       jnz     scm2
-       
-       movb    $0xce, %dl                      # Another set of mode bits
-       movb    $0x06, %al
-       call    inidx
-       shrb    %al
-       jc      scm2
-       
-       movb    $0xd4, %dl                      # Cursor location
-       movb    $0x0f, %al
-       call    inidx
-       orb     %al, %al
-       jnz     scm2
-       
-       movw    %cx, %ax                        # Ok, store the mode
-       stosw
-       movb    %gs:(0x484), %al                # Number of rows
-       incb    %al
-       stosb
-       movw    %gs:(0x44a), %ax                # Number of columns
-       stosb
-scm2:  incb    %cl
-       jns     scm1
-       
-       movw    $0x0003, %ax                    # Return back to mode 3
-       int     $0x10
-       ret
-
-tstidx:        outw    %ax, %dx                        # OUT DX,AX and inidx
-inidx: outb    %al, %dx                        # Read from indexed VGA register
-       incw    %dx                     # AL=index, DX=index reg port -> AL=data
-       inb     %dx, %al
-       decw    %dx
-       ret
-
-# Try to detect type of SVGA card and supply (usually approximate) video
-# mode table for it.
-
-#ifdef CONFIG_VIDEO_SVGA
-svga_modes:
-       leaw    svga_table, %si                 # Test all known SVGA adapters
-dosvga:        lodsw
-       movw    %ax, %bp                        # Default mode table
-       orw     %ax, %ax
-       jz      didsv1
-
-       lodsw                                   # Pointer to test routine
-       pushw   %si
-       pushw   %di
-       pushw   %es
-       movw    $0xc000, %bx
-       movw    %bx, %es
-       call    *%ax                            # Call test routine
-       popw    %es
-       popw    %di
-       popw    %si
-       orw     %bp, %bp
-       jz      dosvga
-       
-       movw    %bp, %si                        # Found, copy the modes
-       movb    svga_prefix, %ah
-cpsvga:        lodsb
-       orb     %al, %al
-       jz      didsv
-       
-       stosw
-       movsw
-       jmp     cpsvga
-
-didsv: movw    %si, card_name                  # Store pointer to card name
-didsv1:        ret
-
-# Table of all known SVGA cards. For each card, we store a pointer to
-# a table of video modes supported by the card and a pointer to a routine
-# used for testing of presence of the card. The video mode table is always
-# followed by the name of the card or the chipset.
-svga_table:
-       .word   ati_md, ati_test
-       .word   oak_md, oak_test
-       .word   paradise_md, paradise_test
-       .word   realtek_md, realtek_test
-       .word   s3_md, s3_test
-       .word   chips_md, chips_test
-       .word   video7_md, video7_test
-       .word   cirrus5_md, cirrus5_test
-       .word   cirrus6_md, cirrus6_test
-       .word   cirrus1_md, cirrus1_test
-       .word   ahead_md, ahead_test
-       .word   everex_md, everex_test
-       .word   genoa_md, genoa_test
-       .word   trident_md, trident_test
-       .word   tseng_md, tseng_test
-       .word   0
-
-# Test routines and mode tables:
-
-# S3 - The test algorithm was taken from the SuperProbe package
-# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
-s3_test:
-       movw    $0x0f35, %cx    # we store some constants in cl/ch
-       movw    $0x03d4, %dx
-       movb    $0x38, %al
-       call    inidx
-       movb    %al, %bh        # store current CRT-register 0x38
-       movw    $0x0038, %ax
-       call    outidx          # disable writing to special regs
-       movb    %cl, %al        # check whether we can write special reg 0x35
-       call    inidx
-       movb    %al, %bl        # save the current value of CRT reg 0x35
-       andb    $0xf0, %al      # clear bits 0-3
-       movb    %al, %ah
-       movb    %cl, %al        # and write it to CRT reg 0x35
-       call    outidx
-       call    inidx           # now read it back
-       andb    %ch, %al        # clear the upper 4 bits
-       jz      s3_2            # the first test failed. But we have a
-
-       movb    %bl, %ah        # second chance
-       movb    %cl, %al
-       call    outidx
-       jmp     s3_1            # do the other tests
-
-s3_2:  movw    %cx, %ax        # load ah with 0xf and al with 0x35
-       orb     %bl, %ah        # set the upper 4 bits of ah with the orig value
-       call    outidx          # write ...
-       call    inidx           # ... and reread 
-       andb    %cl, %al        # turn off the upper 4 bits
-       pushw   %ax
-       movb    %bl, %ah        # restore old value in register 0x35
-       movb    %cl, %al
-       call    outidx
-       popw    %ax
-       cmpb    %ch, %al        # setting lower 4 bits was successful => bad
-       je      no_s3           # writing is allowed => this is not an S3
-
-s3_1:  movw    $0x4838, %ax    # allow writing to special regs by putting
-       call    outidx          # magic number into CRT-register 0x38
-       movb    %cl, %al        # check whether we can write special reg 0x35
-       call    inidx
-       movb    %al, %bl
-       andb    $0xf0, %al
-       movb    %al, %ah
-       movb    %cl, %al
-       call    outidx
-       call    inidx
-       andb    %ch, %al
-       jnz     no_s3           # no, we can't write => no S3
-
-       movw    %cx, %ax
-       orb     %bl, %ah
-       call    outidx
-       call    inidx
-       andb    %ch, %al
-       pushw   %ax
-       movb    %bl, %ah        # restore old value in register 0x35
-       movb    %cl, %al
-       call    outidx
-       popw    %ax
-       cmpb    %ch, %al
-       jne     no_s31          # writing not possible => no S3
-       movb    $0x30, %al
-       call    inidx           # now get the S3 id ...
-       leaw    idS3, %di
-       movw    $0x10, %cx
-       repne
-       scasb
-       je      no_s31
-
-       movb    %bh, %ah
-       movb    $0x38, %al
-       jmp     s3rest
-
-no_s3: movb    $0x35, %al      # restore CRT register 0x35
-       movb    %bl, %ah
-       call    outidx
-no_s31:        xorw    %bp, %bp        # Detection failed
-s3rest:        movb    %bh, %ah
-       movb    $0x38, %al      # restore old value of CRT register 0x38
-       jmp     outidx
-
-idS3:  .byte   0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
-       .byte   0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
-
-s3_md: .byte   0x54, 0x2b, 0x84
-       .byte   0x55, 0x19, 0x84
-       .byte   0
-       .ascii  "S3"
-       .byte   0
-
-# ATI cards.
-ati_test:
-       leaw    idati, %si
-       movw    $0x31, %di
-       movw    $0x09, %cx
-       repe
-       cmpsb
-       je      atiok
-
-       xorw    %bp, %bp
-atiok: ret
-
-idati: .ascii  "761295520"
-
-ati_md:        .byte   0x23, 0x19, 0x84
-       .byte   0x33, 0x2c, 0x84
-       .byte   0x22, 0x1e, 0x64
-       .byte   0x21, 0x19, 0x64
-       .byte   0x58, 0x21, 0x50
-       .byte   0x5b, 0x1e, 0x50
-       .byte   0
-       .ascii  "ATI"
-       .byte   0
-
-# AHEAD
-ahead_test:
-       movw    $0x200f, %ax
-       movw    $0x3ce, %dx
-       outw    %ax, %dx
-       incw    %dx
-       inb     %dx, %al
-       cmpb    $0x20, %al
-       je      isahed
-
-       cmpb    $0x21, %al
-       je      isahed
-       
-       xorw    %bp, %bp
-isahed:        ret
-
-ahead_md:
-       .byte   0x22, 0x2c, 0x84
-       .byte   0x23, 0x19, 0x84
-       .byte   0x24, 0x1c, 0x84
-       .byte   0x2f, 0x32, 0xa0
-       .byte   0x32, 0x22, 0x50
-       .byte   0x34, 0x42, 0x50
-       .byte   0
-       .ascii  "Ahead"
-       .byte   0
-
-# Chips & Tech.
-chips_test:
-       movw    $0x3c3, %dx
-       inb     %dx, %al
-       orb     $0x10, %al
-       outb    %al, %dx
-       movw    $0x104, %dx
-       inb     %dx, %al
-       movb    %al, %bl
-       movw    $0x3c3, %dx
-       inb     %dx, %al
-       andb    $0xef, %al
-       outb    %al, %dx
-       cmpb    $0xa5, %bl
-       je      cantok
-       
-       xorw    %bp, %bp
-cantok:        ret
-
-chips_md:
-       .byte   0x60, 0x19, 0x84
-       .byte   0x61, 0x32, 0x84
-       .byte   0
-       .ascii  "Chips & Technologies"
-       .byte   0
-
-# Cirrus Logic 5X0
-cirrus1_test:
-       movw    $0x3d4, %dx
-       movb    $0x0c, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bl
-       xorb    %al, %al
-       outb    %al, %dx
-       decw    %dx
-       movb    $0x1f, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bh
-       xorb    %ah, %ah
-       shlb    $4, %al
-       movw    %ax, %cx
-       movb    %bh, %al
-       shrb    $4, %al
-       addw    %ax, %cx
-       shlw    $8, %cx
-       addw    $6, %cx
-       movw    %cx, %ax
-       movw    $0x3c4, %dx
-       outw    %ax, %dx
-       incw    %dx
-       inb     %dx, %al
-       andb    %al, %al
-       jnz     nocirr
-       
-       movb    %bh, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       cmpb    $0x01, %al
-       je      iscirr
-
-nocirr:        xorw    %bp, %bp
-iscirr: movw   $0x3d4, %dx
-       movb    %bl, %al
-       xorb    %ah, %ah
-       shlw    $8, %ax
-       addw    $0x0c, %ax
-       outw    %ax, %dx
-       ret
-
-cirrus1_md:
-       .byte   0x1f, 0x19, 0x84
-       .byte   0x20, 0x2c, 0x84
-       .byte   0x22, 0x1e, 0x84
-       .byte   0x31, 0x25, 0x64
-       .byte   0
-       .ascii  "Cirrus Logic 5X0"
-       .byte   0
-
-# Cirrus Logic 54XX
-cirrus5_test:
-       movw    $0x3c4, %dx
-       movb    $6, %al
-       call    inidx
-       movb    %al, %bl                        # BL=backup
-       movw    $6, %ax
-       call    tstidx
-       cmpb    $0x0f, %al
-       jne     c5fail
-       
-       movw    $0x1206, %ax
-       call    tstidx
-       cmpb    $0x12, %al
-       jne     c5fail
-       
-       movb    $0x1e, %al
-       call    inidx
-       movb    %al, %bh
-       movb    %bh, %ah
-       andb    $0xc0, %ah
-       movb    $0x1e, %al
-       call    tstidx
-       andb    $0x3f, %al
-       jne     c5xx
-       
-       movb    $0x1e, %al
-       movb    %bh, %ah
-       orb     $0x3f, %ah
-       call    tstidx
-       xorb    $0x3f, %al
-       andb    $0x3f, %al
-c5xx:  pushf
-       movb    $0x1e, %al
-       movb    %bh, %ah
-       outw    %ax, %dx
-       popf
-       je      c5done
-
-c5fail:        xorw    %bp, %bp
-c5done:        movb    $6, %al
-       movb    %bl, %ah
-       outw    %ax, %dx
-       ret
-
-cirrus5_md:
-       .byte   0x14, 0x19, 0x84
-       .byte   0x54, 0x2b, 0x84
-       .byte   0
-       .ascii  "Cirrus Logic 54XX"
-       .byte   0
-
-# Cirrus Logic 64XX -- no known extra modes, but must be identified, because
-# it's misidentified by the Ahead test.
-cirrus6_test:
-       movw    $0x3ce, %dx
-       movb    $0x0a, %al
-       call    inidx
-       movb    %al, %bl        # BL=backup
-       movw    $0xce0a, %ax
-       call    tstidx
-       orb     %al, %al
-       jne     c2fail
-       
-       movw    $0xec0a, %ax
-       call    tstidx
-       cmpb    $0x01, %al
-       jne     c2fail
-       
-       movb    $0xaa, %al
-       call    inidx           # 4X, 5X, 7X and 8X are valid 64XX chip ID's. 
-       shrb    $4, %al
-       subb    $4, %al
-       jz      c6done
-       
-       decb    %al
-       jz      c6done
-       
-       subb    $2, %al
-       jz      c6done
-       
-       decb    %al
-       jz      c6done
-       
-c2fail:        xorw    %bp, %bp
-c6done:        movb    $0x0a, %al
-       movb    %bl, %ah
-       outw    %ax, %dx
-       ret
-
-cirrus6_md:
-       .byte   0
-       .ascii  "Cirrus Logic 64XX"
-       .byte   0
-
-# Everex / Trident
-everex_test:
-       movw    $0x7000, %ax
-       xorw    %bx, %bx
-       int     $0x10
-       cmpb    $0x70, %al
-       jne     noevrx
-       
-       shrw    $4, %dx
-       cmpw    $0x678, %dx
-       je      evtrid
-       
-       cmpw    $0x236, %dx
-       jne     evrxok
-
-evtrid:        leaw    trident_md, %bp
-evrxok:        ret
-
-noevrx:        xorw    %bp, %bp
-       ret
-
-everex_md:
-       .byte   0x03, 0x22, 0x50
-       .byte   0x04, 0x3c, 0x50
-       .byte   0x07, 0x2b, 0x64
-       .byte   0x08, 0x4b, 0x64
-       .byte   0x0a, 0x19, 0x84
-       .byte   0x0b, 0x2c, 0x84
-       .byte   0x16, 0x1e, 0x50
-       .byte   0x18, 0x1b, 0x64
-       .byte   0x21, 0x40, 0xa0
-       .byte   0x40, 0x1e, 0x84
-       .byte   0
-       .ascii  "Everex/Trident"
-       .byte   0
-
-# Genoa.
-genoa_test:
-       leaw    idgenoa, %si                    # Check Genoa 'clues'
-       xorw    %ax, %ax
-       movb    %es:(0x37), %al
-       movw    %ax, %di
-       movw    $0x04, %cx
-       decw    %si
-       decw    %di
-l1:    incw    %si
-       incw    %di
-       movb    (%si), %al
-       testb   %al, %al
-       jz      l2
-
-       cmpb    %es:(%di), %al
-l2:    loope   l1
-       orw     %cx, %cx
-       je      isgen
-       
-       xorw    %bp, %bp
-isgen: ret
-
-idgenoa: .byte 0x77, 0x00, 0x99, 0x66
-
-genoa_md:
-       .byte   0x58, 0x20, 0x50
-       .byte   0x5a, 0x2a, 0x64
-       .byte   0x60, 0x19, 0x84
-       .byte   0x61, 0x1d, 0x84
-       .byte   0x62, 0x20, 0x84
-       .byte   0x63, 0x2c, 0x84
-       .byte   0x64, 0x3c, 0x84
-       .byte   0x6b, 0x4f, 0x64
-       .byte   0x72, 0x3c, 0x50
-       .byte   0x74, 0x42, 0x50
-       .byte   0x78, 0x4b, 0x64
-       .byte   0
-       .ascii  "Genoa"
-       .byte   0
-
-# OAK
-oak_test:
-       leaw    idoakvga, %si
-       movw    $0x08, %di
-       movw    $0x08, %cx
-       repe
-       cmpsb
-       je      isoak
-       
-       xorw    %bp, %bp
-isoak: ret
-
-idoakvga: .ascii  "OAK VGA "
-
-oak_md: .byte  0x4e, 0x3c, 0x50
-       .byte   0x4f, 0x3c, 0x84
-       .byte   0x50, 0x19, 0x84
-       .byte   0x51, 0x2b, 0x84
-       .byte   0
-       .ascii  "OAK"
-       .byte   0
-
-# WD Paradise.
-paradise_test:
-       leaw    idparadise, %si
-       movw    $0x7d, %di
-       movw    $0x04, %cx
-       repe
-       cmpsb
-       je      ispara
-       
-       xorw    %bp, %bp
-ispara:        ret
-
-idparadise:    .ascii  "VGA="
-
-paradise_md:
-       .byte   0x41, 0x22, 0x50
-       .byte   0x47, 0x1c, 0x84
-       .byte   0x55, 0x19, 0x84
-       .byte   0x54, 0x2c, 0x84
-       .byte   0
-       .ascii  "Paradise"
-       .byte   0
-
-# Trident.
-trident_test:
-       movw    $0x3c4, %dx
-       movb    $0x0e, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       xchgb   %al, %ah
-       xorb    %al, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       xchgb   %ah, %al
-       movb    %al, %bl        # Strange thing ... in the book this wasn't
-       andb    $0x02, %bl      # necessary but it worked on my card which
-       jz      setb2           # is a trident. Without it the screen goes
-                               # blurred ...
-       andb    $0xfd, %al
-       jmp     clrb2           
-
-setb2: orb     $0x02, %al      
-clrb2: outb    %al, %dx
-       andb    $0x0f, %ah
-       cmpb    $0x02, %ah
-       je      istrid
-
-       xorw    %bp, %bp
-istrid:        ret
-
-trident_md:
-       .byte   0x50, 0x1e, 0x50
-       .byte   0x51, 0x2b, 0x50
-       .byte   0x52, 0x3c, 0x50
-       .byte   0x57, 0x19, 0x84
-       .byte   0x58, 0x1e, 0x84
-       .byte   0x59, 0x2b, 0x84
-       .byte   0x5a, 0x3c, 0x84
-       .byte   0
-       .ascii  "Trident"
-       .byte   0
-
-# Tseng.
-tseng_test:
-       movw    $0x3cd, %dx
-       inb     %dx, %al        # Could things be this simple ! :-)
-       movb    %al, %bl
-       movb    $0x55, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       movb    %al, %ah
-       movb    %bl, %al
-       outb    %al, %dx
-       cmpb    $0x55, %ah
-       je      istsen
-
-isnot: xorw    %bp, %bp
-istsen:        ret
-
-tseng_md:
-       .byte   0x26, 0x3c, 0x50
-       .byte   0x2a, 0x28, 0x64
-       .byte   0x23, 0x19, 0x84
-       .byte   0x24, 0x1c, 0x84
-       .byte   0x22, 0x2c, 0x84
-       .byte   0x21, 0x3c, 0x84
-       .byte   0
-       .ascii  "Tseng"
-       .byte   0
-
-# Video7.
-video7_test:
-       movw    $0x3cc, %dx
-       inb     %dx, %al
-       movw    $0x3b4, %dx
-       andb    $0x01, %al
-       jz      even7
-
-       movw    $0x3d4, %dx
-even7: movb    $0x0c, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bl
-       movb    $0x55, %al
-       outb    %al, %dx
-       inb     %dx, %al
-       decw    %dx
-       movb    $0x1f, %al
-       outb    %al, %dx
-       incw    %dx
-       inb     %dx, %al
-       movb    %al, %bh
-       decw    %dx
-       movb    $0x0c, %al
-       outb    %al, %dx
-       incw    %dx
-       movb    %bl, %al
-       outb    %al, %dx
-       movb    $0x55, %al
-       xorb    $0xea, %al
-       cmpb    %bh, %al
-       jne     isnot
-       
-       movb    $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
-       ret
-
-video7_md:
-       .byte   0x40, 0x2b, 0x50
-       .byte   0x43, 0x3c, 0x50
-       .byte   0x44, 0x3c, 0x64
-       .byte   0x41, 0x19, 0x84
-       .byte   0x42, 0x2c, 0x84
-       .byte   0x45, 0x1c, 0x84
-       .byte   0
-       .ascii  "Video 7"
-       .byte   0
-
-# Realtek VGA
-realtek_test:
-       leaw    idrtvga, %si
-       movw    $0x45, %di
-       movw    $0x0b, %cx
-       repe
-       cmpsb
-       je      isrt
-       
-       xorw    %bp, %bp
-isrt:  ret
-
-idrtvga:       .ascii  "REALTEK VGA"
-
-realtek_md:
-       .byte   0x1a, 0x3c, 0x50
-       .byte   0x1b, 0x19, 0x84
-       .byte   0x1c, 0x1e, 0x84
-       .byte   0x1d, 0x2b, 0x84
-       .byte   0x1e, 0x3c, 0x84
-       .byte   0
-       .ascii  "REALTEK"
-       .byte   0
-
-#endif /* CONFIG_VIDEO_SVGA */
-
-# User-defined local mode table (VGA only)
-#ifdef CONFIG_VIDEO_LOCAL
-local_modes:
-       leaw    local_mode_table, %si
-locm1: lodsw
-       orw     %ax, %ax
-       jz      locm2
-       
-       stosw
-       movsw
-       jmp     locm1
-
-locm2: ret
-
-# This is the table of local video modes which can be supplied manually
-# by the user. Each entry consists of mode ID (word) and dimensions
-# (byte for column count and another byte for row count). These modes
-# are placed before all SVGA and VESA modes and override them if table
-# compacting is enabled. The table must end with a zero word followed
-# by NUL-terminated video adapter name.
-local_mode_table:
-       .word   0x0100                          # Example: 40x25
-       .byte   25,40
-       .word   0
-       .ascii  "Local"
-       .byte   0
-#endif /* CONFIG_VIDEO_LOCAL */
-
-# Read a key and return the ASCII code in al, scan code in ah
-getkey:        xorb    %ah, %ah
-       int     $0x16
-       ret
-
-# Read a key with a timeout of 30 seconds.
-# The hardware clock is used to get the time.
-getkt: call    gettime
-       addb    $30, %al                        # Wait 30 seconds
-       cmpb    $60, %al
-       jl      lminute
-
-       subb    $60, %al
-lminute:
-       movb    %al, %cl
-again: movb    $0x01, %ah
-       int     $0x16
-       jnz     getkey                          # key pressed, so get it
-
-       call    gettime
-       cmpb    %cl, %al
-       jne     again
-
-       movb    $0x20, %al                      # timeout, return `space'
-       ret
-
-# Flush the keyboard buffer
-flush: movb    $0x01, %ah
-       int     $0x16
-       jz      empty
-       
-       xorb    %ah, %ah
-       int     $0x16
-       jmp     flush
-
-empty: ret
-
-# Print hexadecimal number.
-prthw: pushw   %ax
-       movb    %ah, %al
-       call    prthb
-       popw    %ax
-prthb: pushw   %ax
-       shrb    $4, %al
-       call    prthn
-       popw    %ax
-       andb    $0x0f, %al
-prthn: cmpb    $0x0a, %al
-       jc      prth1
-
-       addb    $0x07, %al
-prth1: addb    $0x30, %al
-       jmp     prtchr
-
-# Print decimal number in al
-prtdec:        pushw   %ax
-       pushw   %cx
-       xorb    %ah, %ah
-       movb    $0x0a, %cl
-       idivb   %cl
-       cmpb    $0x09, %al
-       jbe     lt100
-
-       call    prtdec
-       jmp     skip10
-
-lt100: addb    $0x30, %al
-       call    prtchr
-skip10:        movb    %ah, %al
-       addb    $0x30, %al
-       call    prtchr  
-       popw    %cx
-       popw    %ax
-       ret
-
-store_edid:
-#ifdef CONFIG_FIRMWARE_EDID
-       pushw   %es                             # just save all registers
-       pushw   %ax
-       pushw   %bx
-       pushw   %cx
-       pushw   %dx
-       pushw   %di
-
-       pushw   %fs
-       popw    %es
-
-       movl    $0x13131313, %eax               # memset block with 0x13
-       movw    $32, %cx
-       movw    $0x140, %di
-       cld
-       rep
-       stosl
-
-       cmpw    $0x0200, vbe_version            # only do EDID on >= VBE2.0
-       jl      no_edid
-
-       pushw   %es                             # save ES
-       xorw    %di, %di                        # Report Capability
-       pushw   %di
-       popw    %es                             # ES:DI must be 0:0
-       movw    $0x4f15, %ax
-       xorw    %bx, %bx
-       xorw    %cx, %cx
-       int     $0x10
-       popw    %es                             # restore ES
-
-       cmpb    $0x00, %ah                      # call successful
-       jne     no_edid
-
-       cmpb    $0x4f, %al                      # function supported
-       jne     no_edid
-
-       movw    $0x4f15, %ax                    # do VBE/DDC
-       movw    $0x01, %bx
-       movw    $0x00, %cx
-       movw    $0x01, %dx
-       movw    $0x140, %di
-       int     $0x10
-
-no_edid:
-       popw    %di                             # restore all registers
-       popw    %dx
-       popw    %cx
-       popw    %bx
-       popw    %ax
-       popw    %es
-#endif
-       ret
-
-# VIDEO_SELECT-only variables
-mt_end:                .word   0       # End of video mode table if built
-edit_buf:      .space  6       # Line editor buffer
-card_name:     .word   0       # Pointer to adapter name
-scanning:      .byte   0       # Performing mode scan
-do_restore:    .byte   0       # Screen contents altered during mode change
-svga_prefix:   .byte   VIDEO_FIRST_BIOS>>8     # Default prefix for BIOS modes
-graphic_mode:  .byte   0       # Graphic mode with a linear frame buffer
-dac_size:      .byte   6       # DAC bit depth
-vbe_version:   .word   0       # VBE bios version
-
-# Status messages
-keymsg:                .ascii  "Press <RETURN> to see video modes available, "
-               .ascii  "<SPACE> to continue or wait 30 secs"
-               .byte   0x0d, 0x0a, 0
-
-listhdr:       .byte   0x0d, 0x0a
-               .ascii  "Mode:    COLSxROWS:"
-
-crlft:         .byte   0x0d, 0x0a, 0
-
-prompt:                .byte   0x0d, 0x0a
-               .asciz  "Enter mode number or `scan': "
-
-unknt:         .asciz  "Unknown mode ID. Try again."
-
-badmdt:                .ascii  "You passed an undefined mode number."
-               .byte   0x0d, 0x0a, 0
-
-vesaer:                .ascii  "Error: Scanning of VESA modes failed. Please "
-               .ascii  "report to <mj@ucw.cz>."
-               .byte   0x0d, 0x0a, 0
-
-old_name:      .asciz  "CGA/MDA/HGA"
-
-ega_name:      .asciz  "EGA"
-
-svga_name:     .ascii  " "
-
-vga_name:      .asciz  "VGA"
-
-vesa_name:     .asciz  "VESA"
-
-name_bann:     .asciz  "Video adapter: "
-#endif /* CONFIG_VIDEO_SELECT */
-
-# Other variables:
-adapter:       .byte   0       # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
-video_segment: .word   0xb800  # Video memory segment
-force_size:    .word   0       # Use this size instead of the one in BIOS vars
index b263788..941a7e3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Wed Mar  7 15:29:47 2007
+# Linux kernel version: 2.6.21-git3
+# Tue May  1 07:30:48 2007
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -118,11 +118,11 @@ CONFIG_X86_PC=y
 # CONFIG_X86_VSMP is not set
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
-# CONFIG_MCORE2 is not set
-CONFIG_GENERIC_CPU=y
-CONFIG_X86_L1_CACHE_BYTES=128
-CONFIG_X86_L1_CACHE_SHIFT=7
-CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_MCORE2=y
+# CONFIG_GENERIC_CPU is not set
+CONFIG_X86_L1_CACHE_BYTES=64
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_INTERNODE_CACHE_BYTES=64
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
 # CONFIG_MICROCODE is not set
@@ -174,6 +174,7 @@ CONFIG_X86_MCE_INTEL=y
 CONFIG_X86_MCE_AMD=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+# CONFIG_RELOCATABLE is not set
 CONFIG_PHYSICAL_START=0x200000
 CONFIG_SECCOMP=y
 # CONFIG_CC_STACKPROTECTOR is not set
@@ -182,7 +183,6 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
-# CONFIG_REORDER is not set
 CONFIG_K8_NB=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -218,7 +218,6 @@ CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=y
 CONFIG_ACPI_NUMA=y
 # CONFIG_ACPI_ASUS is not set
-# CONFIG_ACPI_IBM is not set
 # CONFIG_ACPI_TOSHIBA is not set
 CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
@@ -243,7 +242,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 
 #
 # CPUFreq processor drivers
@@ -299,7 +298,6 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -334,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
@@ -389,6 +388,13 @@ CONFIG_IPV6_SIT=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
 # CONFIG_IEEE80211 is not set
 
 #
@@ -409,10 +415,6 @@ CONFIG_FW_LOADER=y
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -459,6 +461,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_SONY_LAPTOP is not set
+# CONFIG_THINKPAD_ACPI is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -494,7 +497,6 @@ CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -525,7 +527,6 @@ CONFIG_BLK_DEV_PDC202XX_NEW=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -584,11 +585,9 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_ARCMSR is not set
-CONFIG_MEGARAID_NEWGEN=y
-CONFIG_MEGARAID_MM=y
-CONFIG_MEGARAID_MAILBOX=y
+# CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
-CONFIG_MEGARAID_SAS=y
+# CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -608,6 +607,7 @@ CONFIG_MEGARAID_SAS=y
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
 
 #
@@ -636,6 +636,7 @@ CONFIG_SATA_ACPI=y
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -687,7 +688,7 @@ CONFIG_BLK_DEV_DM=y
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=y
 # CONFIG_FUSION_FC is not set
-CONFIG_FUSION_SAS=y
+# CONFIG_FUSION_SAS is not set
 CONFIG_FUSION_MAX_SGE=128
 # CONFIG_FUSION_CTL is not set
 
@@ -700,19 +701,22 @@ CONFIG_IEEE1394=y
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
 
 #
-# Device Drivers
+# Controllers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
 #
-# CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=y
 
 #
-# Protocol Drivers
+# Protocols
 #
 # CONFIG_IEEE1394_VIDEO1394 is not set
 # CONFIG_IEEE1394_SBP2 is not set
+# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
 # CONFIG_IEEE1394_ETH1394 is not set
 # CONFIG_IEEE1394_DV1394 is not set
 CONFIG_IEEE1394_RAWIO=y
@@ -775,7 +779,8 @@ CONFIG_TULIP=y
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
+CONFIG_AMD8111_ETH=y
+# CONFIG_AMD8111E_NAPI is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 CONFIG_B44=y
 CONFIG_FORCEDETH=y
@@ -837,9 +842,10 @@ CONFIG_S2IO=m
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
 # Wan interfaces
@@ -853,7 +859,6 @@ CONFIG_S2IO=m
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
 # CONFIG_NETPOLL_TRAP is not set
 CONFIG_NET_POLL_CONTROLLER=y
 
@@ -987,57 +992,7 @@ CONFIG_HPET_MMAP=y
 #
 # I2C support
 #
-CONFIG_I2C=m
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_ISA=m
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C is not set
 
 #
 # SPI support
@@ -1053,54 +1008,8 @@ CONFIG_I2C_ISA=m
 #
 # Hardware Monitoring support
 #
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_K8TEMP is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-CONFIG_SENSORS_SMSC47B397=m
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_SENSORS_HDAPS is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multifunction device drivers
@@ -1147,8 +1056,9 @@ CONFIG_SOUND=y
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-# CONFIG_OBSOLETE_OSS is not set
+CONFIG_OBSOLETE_OSS=y
 # CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -1162,6 +1072,14 @@ CONFIG_SOUND_ICH=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
 
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
 #
 # USB support
 #
@@ -1175,6 +1093,7 @@ CONFIG_USB=y
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
@@ -1225,10 +1144,6 @@ CONFIG_USB_STORAGE=y
 #
 # USB Input Devices
 #
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_ACECAD is not set
@@ -1556,7 +1471,7 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
+CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
index 071100e..185399b 100644 (file)
@@ -5,6 +5,11 @@
  * This tricks binfmt_elf.c into loading 32bit binaries using lots 
  * of ugly preprocessor tricks. Talk about very very poor man's inheritance.
  */ 
+#define __ASM_X86_64_ELF_H 1
+
+#undef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/rwsem.h>
@@ -50,9 +55,6 @@ struct elf_phdr;
 #undef ELF_ARCH
 #define ELF_ARCH EM_386
 
-#undef ELF_CLASS
-#define ELF_CLASS ELFCLASS32
-
 #define ELF_DATA       ELFDATA2LSB
 
 #define USE_ELF_CORE_DUMP 1
@@ -136,7 +138,7 @@ struct elf_prpsinfo
 
 #define user user32
 
-#define __ASM_X86_64_ELF_H 1
+#undef elf_read_implies_exec
 #define elf_read_implies_exec(ex, executable_stack)     (executable_stack != EXSTACK_DISABLE_X)
 //#include <asm/ia32.h>
 #include <linux/elf.h>
index 796df69..c48087d 100644 (file)
@@ -481,11 +481,7 @@ ia32_sys_call_table:
        .quad sys_symlink
        .quad sys_lstat
        .quad sys_readlink              /* 85 */
-#ifdef CONFIG_IA32_AOUT
        .quad sys_uselib
-#else
-       .quad quiet_ni_syscall
-#endif
        .quad sys_swapon
        .quad sys_reboot
        .quad compat_sys_old_readdir
index 568ff0d..fc4419f 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/proto.h>
 #include <asm/tlbflush.h>
 #include <asm/ia32_unistd.h>
+#include <asm/vsyscall32.h>
 
 extern unsigned char syscall32_syscall[], syscall32_syscall_end[];
 extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[];
index bb47e86..4d94c51 100644 (file)
@@ -8,7 +8,8 @@ obj-y   := process.o signal.o entry.o traps.o irq.o \
                ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
                x8664_ksyms.o i387.o syscall.o vsyscall.o \
                setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
-               pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o
+               pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o bugs.o \
+               perfctr-watchdog.o
 
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_X86_MCE)          += mce.o therm_throt.o
@@ -21,8 +22,7 @@ obj-$(CONFIG_MICROCODE)               += microcode.o
 obj-$(CONFIG_X86_CPUID)                += cpuid.o
 obj-$(CONFIG_SMP)              += smp.o smpboot.o trampoline.o tsc_sync.o
 obj-y                          += apic.o  nmi.o
-obj-y                          += io_apic.o mpparse.o \
-               genapic.o genapic_cluster.o genapic_flat.o
+obj-y                          += io_apic.o mpparse.o genapic.o genapic_flat.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_PM)               += suspend.o
@@ -58,3 +58,4 @@ i8237-y                               += ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
 alternative-y                  += ../../i386/kernel/alternative.o
 pcspeaker-y                    += ../../i386/kernel/pcspeaker.o
+perfctr-watchdog-y             += ../../i386/kernel/cpu/perfctr-watchdog.o
index e1548fb..195b703 100644 (file)
@@ -60,19 +60,6 @@ extern char wakeup_start, wakeup_end;
 
 extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 
-static pgd_t low_ptr;
-
-static void init_low_mapping(void)
-{
-       pgd_t *slot0 = pgd_offset(current->mm, 0UL);
-       low_ptr = *slot0;
-       /* FIXME: We're playing with the current task's page tables here, which
-        * is potentially dangerous on SMP systems.
-        */
-       set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
-       local_flush_tlb();
-}
-
 /**
  * acpi_save_state_mem - save kernel state
  *
@@ -81,8 +68,6 @@ static void init_low_mapping(void)
  */
 int acpi_save_state_mem(void)
 {
-       init_low_mapping();
-
        memcpy((void *)acpi_wakeup_address, &wakeup_start,
               &wakeup_end - &wakeup_start);
        acpi_copy_wakeup_routine(acpi_wakeup_address);
@@ -95,8 +80,6 @@ int acpi_save_state_mem(void)
  */
 void acpi_restore_state_mem(void)
 {
-       set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
-       local_flush_tlb();
 }
 
 /**
@@ -109,10 +92,11 @@ void acpi_restore_state_mem(void)
  */
 void __init acpi_reserve_bootmem(void)
 {
-       acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
-       if ((&wakeup_end - &wakeup_start) > PAGE_SIZE)
+       acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
+       if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE*2))
                printk(KERN_CRIT
-                      "ACPI: Wakeup code way too big, will crash on attempt to suspend\n");
+                      "ACPI: Wakeup code way too big, will crash on attempt"
+                      " to suspend\n");
 }
 
 static int __init acpi_sleep_setup(char *str)
index 185faa9..8550a6f 100644 (file)
@@ -1,6 +1,7 @@
 .text
 #include <linux/linkage.h>
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/msr.h>
 
@@ -30,22 +31,28 @@ wakeup_code:
        cld
        # setup data segment
        movw    %cs, %ax
-       movw    %ax, %ds                                        # Make ds:0 point to wakeup_start
+       movw    %ax, %ds                # Make ds:0 point to wakeup_start
        movw    %ax, %ss
-       mov     $(wakeup_stack - wakeup_code), %sp              # Private stack is needed for ASUS board
+                                       # Private stack is needed for ASUS board
+       mov     $(wakeup_stack - wakeup_code), %sp
 
-       pushl   $0                                              # Kill any dangerous flags
+       pushl   $0                      # Kill any dangerous flags
        popfl
 
        movl    real_magic - wakeup_code, %eax
        cmpl    $0x12345678, %eax
        jne     bogus_real_magic
 
+       call    verify_cpu                      # Verify the cpu supports long
+                                               # mode
+       testl   %eax, %eax
+       jnz     no_longmode
+
        testl   $1, video_flags - wakeup_code
        jz      1f
        lcall   $0xc000,$3
        movw    %cs, %ax
-       movw    %ax, %ds                                        # Bios might have played with that
+       movw    %ax, %ds                # Bios might have played with that
        movw    %ax, %ss
 1:
 
@@ -61,12 +68,15 @@ wakeup_code:
 
        movb    $0xa2, %al      ;  outb %al, $0x80
        
-       lidt    %ds:idt_48a - wakeup_code
-       xorl    %eax, %eax
-       movw    %ds, %ax                        # (Convert %ds:gdt to a linear ptr)
-       shll    $4, %eax
-       addl    $(gdta - wakeup_code), %eax
-       movl    %eax, gdt_48a +2 - wakeup_code
+       mov     %ds, %ax                        # Find 32bit wakeup_code addr
+       movzx   %ax, %esi                       # (Convert %ds:gdt to a liner ptr)
+       shll    $4, %esi
+                                               # Fix up the vectors
+       addl    %esi, wakeup_32_vector - wakeup_code
+       addl    %esi, wakeup_long64_vector - wakeup_code
+       addl    %esi, gdt_48a + 2 - wakeup_code # Fixup the gdt pointer
+
+       lidtl   %ds:idt_48a - wakeup_code
        lgdtl   %ds:gdt_48a - wakeup_code       # load gdt with whatever is
                                                # appropriate
 
@@ -75,86 +85,63 @@ wakeup_code:
        jmp     1f
 1:
 
-       .byte 0x66, 0xea                        # prefix + jmpi-opcode
-       .long   wakeup_32 - __START_KERNEL_map
-       .word   __KERNEL_CS
+       ljmpl   *(wakeup_32_vector - wakeup_code)
+
+       .balign 4
+wakeup_32_vector:
+       .long   wakeup_32 - wakeup_code
+       .word   __KERNEL32_CS, 0
 
        .code32
 wakeup_32:
 # Running in this code, but at low address; paging is not yet turned on.
        movb    $0xa5, %al      ;  outb %al, $0x80
 
-       /* Check if extended functions are implemented */               
-       movl    $0x80000000, %eax
-       cpuid
-       cmpl    $0x80000000, %eax
-       jbe     bogus_cpu
-       wbinvd
-       mov     $0x80000001, %eax
-       cpuid
-       btl     $29, %edx
-       jnc     bogus_cpu
-       movl    %edx,%edi
-       
-       movw    $__KERNEL_DS, %ax
-       movw    %ax, %ds
-       movw    %ax, %es
-       movw    %ax, %fs
-       movw    %ax, %gs
-
-       movw    $__KERNEL_DS, %ax       
-       movw    %ax, %ss
+       movl    $__KERNEL_DS, %eax
+       movl    %eax, %ds
 
-       mov     $(wakeup_stack - __START_KERNEL_map), %esp
-       movl    saved_magic - __START_KERNEL_map, %eax
-       cmpl    $0x9abcdef0, %eax
-       jne     bogus_32_magic
+       movw    $0x0e00 + 'i', %ds:(0xb8012)
+       movb    $0xa8, %al      ;  outb %al, $0x80;
 
        /*
         * Prepare for entering 64bits mode
         */
 
-       /* Enable PAE mode and PGE */
+       /* Enable PAE */
        xorl    %eax, %eax
        btsl    $5, %eax
-       btsl    $7, %eax
        movl    %eax, %cr4
 
        /* Setup early boot stage 4 level pagetables */
-       movl    $(wakeup_level4_pgt - __START_KERNEL_map), %eax
+       leal    (wakeup_level4_pgt - wakeup_code)(%esi), %eax
        movl    %eax, %cr3
 
-       /* Setup EFER (Extended Feature Enable Register) */
-       movl    $MSR_EFER, %ecx
-       rdmsr
-       /* Fool rdmsr and reset %eax to avoid dependences */
-       xorl    %eax, %eax
+        /* Check if nx is implemented */
+        movl    $0x80000001, %eax
+        cpuid
+        movl    %edx,%edi
+
        /* Enable Long Mode */
+       xorl    %eax, %eax
        btsl    $_EFER_LME, %eax
-       /* Enable System Call */
-       btsl    $_EFER_SCE, %eax
 
-       /* No Execute supported? */     
+       /* No Execute supported? */
        btl     $20,%edi
        jnc     1f
        btsl    $_EFER_NX, %eax
-1:     
                                
        /* Make changes effective */
+1:     movl    $MSR_EFER, %ecx
+       xorl    %edx, %edx
        wrmsr
-       wbinvd
 
        xorl    %eax, %eax
        btsl    $31, %eax                       /* Enable paging and in turn activate Long Mode */
        btsl    $0, %eax                        /* Enable protected mode */
-       btsl    $1, %eax                        /* Enable MP */
-       btsl    $4, %eax                        /* Enable ET */
-       btsl    $5, %eax                        /* Enable NE */
-       btsl    $16, %eax                       /* Enable WP */
-       btsl    $18, %eax                       /* Enable AM */
 
        /* Make changes effective */
        movl    %eax, %cr0
+
        /* At this point:
                CR4.PAE must be 1
                CS.L must be 0
@@ -162,11 +149,6 @@ wakeup_32:
                Next instruction must be a branch
                This must be on identity-mapped page
        */
-       jmp     reach_compatibility_mode
-reach_compatibility_mode:
-       movw    $0x0e00 + 'i', %ds:(0xb8012)
-       movb    $0xa8, %al      ;  outb %al, $0x80;     
-               
        /*
         * At this point we're in long mode but in 32bit compatibility mode
         * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
@@ -174,24 +156,19 @@ reach_compatibility_mode:
         * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
         */
 
-       movw    $0x0e00 + 'n', %ds:(0xb8014)
-       movb    $0xa9, %al      ;  outb %al, $0x80
-       
-       /* Load new GDT with the 64bit segment using 32bit descriptor */
-       movl    $(pGDT32 - __START_KERNEL_map), %eax
-       lgdt    (%eax)
-
-       movl    $(wakeup_jumpvector - __START_KERNEL_map), %eax
        /* Finally jump in 64bit mode */
-       ljmp    *(%eax)
+        ljmp    *(wakeup_long64_vector - wakeup_code)(%esi)
 
-wakeup_jumpvector:
-       .long   wakeup_long64 - __START_KERNEL_map
-       .word   __KERNEL_CS
+       .balign 4
+wakeup_long64_vector:
+       .long   wakeup_long64 - wakeup_code
+       .word   __KERNEL_CS, 0
 
 .code64
 
-       /*      Hooray, we are in Long 64-bit mode (but still running in low memory) */
+       /* Hooray, we are in Long 64-bit mode (but still running in
+        * low memory)
+        */
 wakeup_long64:
        /*
         * We must switch to a new descriptor in kernel space for the GDT
@@ -199,7 +176,15 @@ wakeup_long64:
         * addresses where we're currently running on. We have to do that here
         * because in 32bit we couldn't load a 64bit linear address.
         */
-       lgdt    cpu_gdt_descr - __START_KERNEL_map
+       lgdt    cpu_gdt_descr
+
+       movw    $0x0e00 + 'n', %ds:(0xb8014)
+       movb    $0xa9, %al      ;  outb %al, $0x80
+
+       movq    saved_magic, %rax
+       movq    $0x123456789abcdef0, %rdx
+       cmpq    %rdx, %rax
+       jne     bogus_64_magic
 
        movw    $0x0e00 + 'u', %ds:(0xb8016)
        
@@ -211,75 +196,58 @@ wakeup_long64:
        movw    %ax, %es
        movw    %ax, %fs
        movw    %ax, %gs
-       movq    saved_esp, %rsp
+       movq    saved_rsp, %rsp
 
        movw    $0x0e00 + 'x', %ds:(0xb8018)
-       movq    saved_ebx, %rbx
-       movq    saved_edi, %rdi
-       movq    saved_esi, %rsi
-       movq    saved_ebp, %rbp
+       movq    saved_rbx, %rbx
+       movq    saved_rdi, %rdi
+       movq    saved_rsi, %rsi
+       movq    saved_rbp, %rbp
 
        movw    $0x0e00 + '!', %ds:(0xb801a)
-       movq    saved_eip, %rax
+       movq    saved_rip, %rax
        jmp     *%rax
 
 .code32
 
        .align  64      
 gdta:
+       /* Its good to keep gdt in sync with one in trampoline.S */
        .word   0, 0, 0, 0                      # dummy
-
-       .word   0, 0, 0, 0                      # unused
-
-       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
-       .word   0                               # base address = 0
-       .word   0x9B00                          # code read/exec. ??? Why I need 0x9B00 (as opposed to 0x9A00 in order for this to work?)
-       .word   0x00CF                          # granularity = 4096, 386
-                                               #  (+5th nibble of limit)
-
-       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
-       .word   0                               # base address = 0
-       .word   0x9200                          # data read/write
-       .word   0x00CF                          # granularity = 4096, 386
-                                               #  (+5th nibble of limit)
-# this is 64bit descriptor for code
-       .word   0xFFFF
-       .word   0
-       .word   0x9A00                          # code read/exec
-       .word   0x00AF                          # as above, but it is long mode and with D=0
+       /* ??? Why I need the accessed bit set in order for this to work? */
+       .quad   0x00cf9b000000ffff              # __KERNEL32_CS
+       .quad   0x00af9b000000ffff              # __KERNEL_CS
+       .quad   0x00cf93000000ffff              # __KERNEL_DS
 
 idt_48a:
        .word   0                               # idt limit = 0
        .word   0, 0                            # idt base = 0L
 
 gdt_48a:
-       .word   0x8000                          # gdt limit=2048,
+       .word   0x800                           # gdt limit=2048,
                                                #  256 GDT entries
-       .word   0, 0                            # gdt base (filled in later)
-       
+       .long   gdta - wakeup_code              # gdt base (relocated in later)
        
-real_save_gdt: .word 0
-               .quad 0
 real_magic:    .quad 0
 video_mode:    .quad 0
 video_flags:   .quad 0
 
+.code16
 bogus_real_magic:
-       movb    $0xba,%al       ;  outb %al,$0x80               
+       movb    $0xba,%al       ;  outb %al,$0x80
        jmp bogus_real_magic
 
-bogus_32_magic:
+.code64
+bogus_64_magic:
        movb    $0xb3,%al       ;  outb %al,$0x80
-       jmp bogus_32_magic
+       jmp bogus_64_magic
 
-bogus_31_magic:
-       movb    $0xb1,%al       ;  outb %al,$0x80
-       jmp bogus_31_magic
-
-bogus_cpu:
-       movb    $0xbc,%al       ;  outb %al,$0x80
-       jmp bogus_cpu
+.code16
+no_longmode:
+       movb    $0xbc,%al       ;  outb %al,$0x80
+       jmp no_longmode
 
+#include "../verify_cpu.S"
        
 /* This code uses an extended set of video mode numbers. These include:
  * Aliases for standard modes
@@ -301,6 +269,7 @@ bogus_cpu:
 #define VIDEO_FIRST_V7 0x0900
 
 # Setting of user mode (AX=mode ID) => CF=success
+.code16
 mode_seta:
        movw    %ax, %bx
 #if 0
@@ -346,21 +315,18 @@ check_vesaa:
 
 _setbada: jmp setbada
 
-       .code64
-bogus_magic:
-       movw    $0x0e00 + 'B', %ds:(0xb8018)
-       jmp bogus_magic
-
-bogus_magic2:
-       movw    $0x0e00 + '2', %ds:(0xb8018)
-       jmp bogus_magic2
-       
-
 wakeup_stack_begin:    # Stack grows down
 
 .org   0xff0
 wakeup_stack:          # Just below end of page
 
+.org   0x1000
+ENTRY(wakeup_level4_pgt)
+       .quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+       .fill   510,8,0
+       /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
+       .quad   level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
+
 ENTRY(wakeup_end)
        
 ##
@@ -373,28 +339,11 @@ ENTRY(wakeup_end)
 #
 # Returned address is location of code in low memory (past data and stack)
 #
+       .code64
 ENTRY(acpi_copy_wakeup_routine)
        pushq   %rax
-       pushq   %rcx
        pushq   %rdx
 
-       sgdt    saved_gdt
-       sidt    saved_idt
-       sldt    saved_ldt
-       str     saved_tss
-
-       movq    %cr3, %rdx
-       movq    %rdx, saved_cr3
-       movq    %cr4, %rdx
-       movq    %rdx, saved_cr4
-       movq    %cr0, %rdx
-       movq    %rdx, saved_cr0
-       sgdt    real_save_gdt - wakeup_start (,%rdi)
-       movl    $MSR_EFER, %ecx
-       rdmsr
-       movl    %eax, saved_efer
-       movl    %edx, saved_efer2
-
        movl    saved_video_mode, %edx
        movl    %edx, video_mode - wakeup_start (,%rdi)
        movl    acpi_video_flags, %edx
@@ -403,21 +352,13 @@ ENTRY(acpi_copy_wakeup_routine)
        movq    $0x123456789abcdef0, %rdx
        movq    %rdx, saved_magic
 
-       movl    saved_magic - __START_KERNEL_map, %eax
-       cmpl    $0x9abcdef0, %eax
-       jne     bogus_32_magic
-
-       # make sure %cr4 is set correctly (features, etc)
-       movl    saved_cr4 - __START_KERNEL_map, %eax
-       movq    %rax, %cr4
+       movq    saved_magic, %rax
+       movq    $0x123456789abcdef0, %rdx
+       cmpq    %rdx, %rax
+       jne     bogus_64_magic
 
-       movl    saved_cr0 - __START_KERNEL_map, %eax
-       movq    %rax, %cr0
-       jmp     1f              # Flush pipelines
-1:
        # restore the regs we used
        popq    %rdx
-       popq    %rcx
        popq    %rax
 ENTRY(do_suspend_lowlevel_s4bios)
        ret
@@ -450,13 +391,13 @@ do_suspend_lowlevel:
        movq %r15, saved_context_r15(%rip)
        pushfq ; popq saved_context_eflags(%rip)
 
-       movq    $.L97, saved_eip(%rip)
+       movq    $.L97, saved_rip(%rip)
 
-       movq %rsp,saved_esp
-       movq %rbp,saved_ebp
-       movq %rbx,saved_ebx
-       movq %rdi,saved_edi
-       movq %rsi,saved_esi
+       movq %rsp,saved_rsp
+       movq %rbp,saved_rbp
+       movq %rbx,saved_rbx
+       movq %rdi,saved_rdi
+       movq %rsi,saved_rsi
 
        addq    $8, %rsp
        movl    $3, %edi
@@ -503,25 +444,12 @@ do_suspend_lowlevel:
        
 .data
 ALIGN
-ENTRY(saved_ebp)       .quad   0
-ENTRY(saved_esi)       .quad   0
-ENTRY(saved_edi)       .quad   0
-ENTRY(saved_ebx)       .quad   0
+ENTRY(saved_rbp)       .quad   0
+ENTRY(saved_rsi)       .quad   0
+ENTRY(saved_rdi)       .quad   0
+ENTRY(saved_rbx)       .quad   0
 
-ENTRY(saved_eip)       .quad   0
-ENTRY(saved_esp)       .quad   0
+ENTRY(saved_rip)       .quad   0
+ENTRY(saved_rsp)       .quad   0
 
 ENTRY(saved_magic)     .quad   0
-
-ALIGN
-# saved registers
-saved_gdt:     .quad   0,0
-saved_idt:     .quad   0,0
-saved_ldt:     .quad   0
-saved_tss:     .quad   0
-
-saved_cr0:     .quad 0
-saved_cr3:     .quad 0
-saved_cr4:     .quad 0
-saved_efer:    .quad 0
-saved_efer2:   .quad 0
index b487396..a52af58 100644 (file)
@@ -51,7 +51,6 @@ static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
 
 static u32 __init allocate_aperture(void) 
 {
-       pg_data_t *nd0 = NODE_DATA(0);
        u32 aper_size;
        void *p; 
 
@@ -65,12 +64,12 @@ static u32 __init allocate_aperture(void)
         * Unfortunately we cannot move it up because that would make the
         * IOMMU useless.
         */
-       p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0); 
+       p = __alloc_bootmem_nopanic(aper_size, aper_size, 0);
        if (!p || __pa(p)+aper_size > 0xffffffff) {
                printk("Cannot allocate aperture memory hole (%p,%uK)\n",
                       p, aper_size>>10);
                if (p)
-                       free_bootmem_node(nd0, __pa(p), aper_size); 
+                       free_bootmem(__pa(p), aper_size);
                return 0;
        }
        printk("Mapping aperture over %d KB of RAM @ %lx\n",
index bd3e45d..d198f7d 100644 (file)
@@ -68,6 +68,28 @@ int using_apic_timer __read_mostly = 0;
 
 static void apic_pm_activate(void);
 
+void apic_wait_icr_idle(void)
+{
+       while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
+               cpu_relax();
+}
+
+unsigned int safe_apic_wait_icr_idle(void)
+{
+       unsigned int send_status;
+       int timeout;
+
+       timeout = 0;
+       do {
+               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
+               if (!send_status)
+                       break;
+               udelay(100);
+       } while (timeout++ < 1000);
+
+       return send_status;
+}
+
 void enable_NMI_through_LVT0 (void * dummy)
 {
        unsigned int v;
@@ -817,14 +839,15 @@ static void setup_APIC_timer(unsigned int clocks)
 
 static int __init calibrate_APIC_clock(void)
 {
-       int apic, apic_start, tsc, tsc_start;
+       unsigned apic, apic_start;
+       unsigned long tsc, tsc_start;
        int result;
        /*
         * Put whatever arbitrary (but long enough) timeout
         * value into the APIC clock, we just want to get the
         * counter running for calibration.
         */
-       __setup_APIC_LVTT(1000000000);
+       __setup_APIC_LVTT(4000000000);
 
        apic_start = apic_read(APIC_TMCCT);
 #ifdef CONFIG_X86_PM_TIMER
@@ -835,15 +858,15 @@ static int __init calibrate_APIC_clock(void)
        } else
 #endif
        {
-               rdtscl(tsc_start);
+               rdtscll(tsc_start);
 
                do {
                        apic = apic_read(APIC_TMCCT);
-                       rdtscl(tsc);
+                       rdtscll(tsc);
                } while ((tsc - tsc_start) < TICK_COUNT &&
-                               (apic - apic_start) < TICK_COUNT);
+                               (apic_start - apic) < TICK_COUNT);
 
-               result = (apic_start - apic) * 1000L * cpu_khz /
+               result = (apic_start - apic) * 1000L * tsc_khz /
                                        (tsc - tsc_start);
        }
        printk("result %d\n", result);
index 96687e2..778953b 100644 (file)
 
 #define BLANK() asm volatile("\n->" : : )
 
+#define __NO_STUBS 1
+#undef __SYSCALL
+#undef _ASM_X86_64_UNISTD_H_
+#define __SYSCALL(nr, sym) [nr] = 1,
+static char syscalls[] = {
+#include <asm/unistd.h>
+};
+
 int main(void)
 {
 #define ENTRY(entry) DEFINE(tsk_ ## entry, offsetof(struct task_struct, entry))
@@ -71,5 +79,7 @@ int main(void)
        DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
        BLANK();
        DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
+       BLANK();
+       DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
        return 0;
 }
diff --git a/arch/x86_64/kernel/bugs.c b/arch/x86_64/kernel/bugs.c
new file mode 100644 (file)
index 0000000..12b585b
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  arch/x86_64/kernel/bugs.c
+ *
+ *  Copyright (C) 1994  Linus Torvalds
+ *  Copyright (C) 2000  SuSE
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/alternative.h>
+#include <asm/processor.h>
+
+void __init check_bugs(void)
+{
+       identify_cpu(&boot_cpu_data);
+#if !defined(CONFIG_SMP)
+       printk("CPU: ");
+       print_cpu_info(&boot_cpu_data);
+#endif
+       alternative_instructions();
+}
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 a490fab..be89654 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/bootsetup.h>
 #include <asm/sections.h>
 
-struct e820map e820 __initdata;
+struct e820map e820;
 
 /* 
  * PFN of last memory page.
@@ -98,7 +98,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
  * This function checks if any part of the range <start,end> is mapped
  * with type.
  */
-int __meminit
+int
 e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
 { 
        int i;
@@ -112,6 +112,7 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
        } 
        return 0;
 }
+EXPORT_SYMBOL_GPL(e820_any_mapped);
 
 /*
  * This function checks if the entire range <start,end> is mapped with type.
index fede55a..990d9c2 100644 (file)
@@ -71,18 +71,6 @@ static void __init ati_bugs(void)
        }
 }
 
-static void intel_bugs(void)
-{
-       u16 device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
-
-#ifdef CONFIG_SMP
-       if (device == PCI_DEVICE_ID_INTEL_E7320_MCH ||
-           device == PCI_DEVICE_ID_INTEL_E7520_MCH ||
-           device == PCI_DEVICE_ID_INTEL_E7525_MCH)
-               quirk_intel_irqbalance();
-#endif
-}
-
 struct chipset {
        u16 vendor;
        void (*f)(void);
@@ -92,7 +80,6 @@ static struct chipset early_qrk[] __initdata = {
        { PCI_VENDOR_ID_NVIDIA, nvidia_bugs },
        { PCI_VENDOR_ID_VIA, via_bugs },
        { PCI_VENDOR_ID_ATI, ati_bugs },
-       { PCI_VENDOR_ID_INTEL, intel_bugs},
        {}
 };
 
index 47b6d90..92213d2 100644 (file)
 
 #ifdef __i386__
 #include <asm/setup.h>
-#define VGABASE                (__ISA_IO_base + 0xb8000)
 #else
 #include <asm/bootsetup.h>
-#define VGABASE                ((void __iomem *)0xffffffff800b8000UL)
 #endif
+#define VGABASE                (__ISA_IO_base + 0xb8000)
 
 static int max_ypos = 25, max_xpos = 80;
 static int current_ypos = 25, current_xpos = 0;
@@ -176,7 +175,7 @@ static noinline long simnow(long cmd, long a, long b, long c)
        return ret;
 }
 
-void __init simnow_init(char *str)
+static void __init simnow_init(char *str)
 {
        char *fn = "klog";
        if (*str == '=')
index ed4350c..fa984b5 100644 (file)
@@ -701,6 +701,7 @@ END(spurious_interrupt)
        CFI_ADJUST_CFA_OFFSET 8
        pushq %rax      /* push real oldrax to the rdi slot */ 
        CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rax,0
        leaq  \sym(%rip),%rax
        jmp error_entry
        CFI_ENDPROC
@@ -710,6 +711,7 @@ END(spurious_interrupt)
        XCPT_FRAME
        pushq %rax
        CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rax,0
        leaq  \sym(%rip),%rax
        jmp error_entry
        CFI_ENDPROC
@@ -817,6 +819,7 @@ paranoid_schedule\trace:
  */                                            
 KPROBE_ENTRY(error_entry)
        _frame RDI
+       CFI_REL_OFFSET rax,0
        /* rdi slot contains rax, oldrax contains error code */
        cld     
        subq  $14*8,%rsp
@@ -824,6 +827,7 @@ KPROBE_ENTRY(error_entry)
        movq %rsi,13*8(%rsp)
        CFI_REL_OFFSET  rsi,RSI
        movq 14*8(%rsp),%rsi    /* load rax from rdi slot */
+       CFI_REGISTER    rax,rsi
        movq %rdx,12*8(%rsp)
        CFI_REL_OFFSET  rdx,RDX
        movq %rcx,11*8(%rsp)
@@ -857,6 +861,7 @@ error_swapgs:
        swapgs
 error_sti:     
        movq %rdi,RDI(%rsp)     
+       CFI_REL_OFFSET  rdi,RDI
        movq %rsp,%rdi
        movq ORIG_RAX(%rsp),%rsi        /* get error code */ 
        movq $-1,ORIG_RAX(%rsp)
diff --git a/arch/x86_64/kernel/functionlist b/arch/x86_64/kernel/functionlist
deleted file mode 100644 (file)
index 7ae18ec..0000000
+++ /dev/null
@@ -1,1284 +0,0 @@
-*(.text.flush_thread)
-*(.text.check_poison_obj)
-*(.text.copy_page)
-*(.text.__set_personality)
-*(.text.gart_map_sg)
-*(.text.kmem_cache_free)
-*(.text.find_get_page)
-*(.text._raw_spin_lock)
-*(.text.ide_outb)
-*(.text.unmap_vmas)
-*(.text.copy_page_range)
-*(.text.kprobe_handler)
-*(.text.__handle_mm_fault)
-*(.text.__d_lookup)
-*(.text.copy_user_generic)
-*(.text.__link_path_walk)
-*(.text.get_page_from_freelist)
-*(.text.kmem_cache_alloc)
-*(.text.drive_cmd_intr)
-*(.text.ia32_setup_sigcontext)
-*(.text.huge_pte_offset)
-*(.text.do_page_fault)
-*(.text.page_remove_rmap)
-*(.text.release_pages)
-*(.text.ide_end_request)
-*(.text.__mutex_lock_slowpath)
-*(.text.__find_get_block)
-*(.text.kfree)
-*(.text.vfs_read)
-*(.text._raw_spin_unlock)
-*(.text.free_hot_cold_page)
-*(.text.fget_light)
-*(.text.schedule)
-*(.text.memcmp)
-*(.text.touch_atime)
-*(.text.__might_sleep)
-*(.text.__down_read_trylock)
-*(.text.arch_pick_mmap_layout)
-*(.text.find_vma)
-*(.text.__make_request)
-*(.text.do_generic_mapping_read)
-*(.text.mutex_lock_interruptible)
-*(.text.__generic_file_aio_read)
-*(.text._atomic_dec_and_lock)
-*(.text.__wake_up_bit)
-*(.text.add_to_page_cache)
-*(.text.cache_alloc_debugcheck_after)
-*(.text.vm_normal_page)
-*(.text.mutex_debug_check_no_locks_freed)
-*(.text.net_rx_action)
-*(.text.__find_first_zero_bit)
-*(.text.put_page)
-*(.text._raw_read_lock)
-*(.text.__delay)
-*(.text.dnotify_parent)
-*(.text.do_path_lookup)
-*(.text.do_sync_read)
-*(.text.do_lookup)
-*(.text.bit_waitqueue)
-*(.text.file_read_actor)
-*(.text.strncpy_from_user)
-*(.text.__pagevec_lru_add_active)
-*(.text.fget)
-*(.text.dput)
-*(.text.__strnlen_user)
-*(.text.inotify_inode_queue_event)
-*(.text.rw_verify_area)
-*(.text.ide_intr)
-*(.text.inotify_dentry_parent_queue_event)
-*(.text.permission)
-*(.text.memscan)
-*(.text.hpet_rtc_interrupt)
-*(.text.do_mmap_pgoff)
-*(.text.current_fs_time)
-*(.text.vfs_getattr)
-*(.text.kmem_flagcheck)
-*(.text.mark_page_accessed)
-*(.text.free_pages_and_swap_cache)
-*(.text.generic_fillattr)
-*(.text.__block_prepare_write)
-*(.text.__set_page_dirty_nobuffers)
-*(.text.link_path_walk)
-*(.text.find_get_pages_tag)
-*(.text.ide_do_request)
-*(.text.__alloc_pages)
-*(.text.generic_permission)
-*(.text.mod_page_state_offset)
-*(.text.free_pgd_range)
-*(.text.generic_file_buffered_write)
-*(.text.number)
-*(.text.ide_do_rw_disk)
-*(.text.__brelse)
-*(.text.__mod_page_state_offset)
-*(.text.rotate_reclaimable_page)
-*(.text.find_vma_prepare)
-*(.text.find_vma_prev)
-*(.text.lru_cache_add_active)
-*(.text.__kmalloc_track_caller)
-*(.text.smp_invalidate_interrupt)
-*(.text.handle_IRQ_event)
-*(.text.__find_get_block_slow)
-*(.text.do_wp_page)
-*(.text.do_select)
-*(.text.set_user_nice)
-*(.text.sys_read)
-*(.text.do_munmap)
-*(.text.csum_partial)
-*(.text.__do_softirq)
-*(.text.may_open)
-*(.text.getname)
-*(.text.get_empty_filp)
-*(.text.__fput)
-*(.text.remove_mapping)
-*(.text.filp_ctor)
-*(.text.poison_obj)
-*(.text.unmap_region)
-*(.text.test_set_page_writeback)
-*(.text.__do_page_cache_readahead)
-*(.text.sock_def_readable)
-*(.text.ide_outl)
-*(.text.shrink_zone)
-*(.text.rb_insert_color)
-*(.text.get_request)
-*(.text.sys_pread64)
-*(.text.spin_bug)
-*(.text.ide_outsl)
-*(.text.mask_and_ack_8259A)
-*(.text.filemap_nopage)
-*(.text.page_add_file_rmap)
-*(.text.find_lock_page)
-*(.text.tcp_poll)
-*(.text.__mark_inode_dirty)
-*(.text.file_ra_state_init)
-*(.text.generic_file_llseek)
-*(.text.__pagevec_lru_add)
-*(.text.page_cache_readahead)
-*(.text.n_tty_receive_buf)
-*(.text.zonelist_policy)
-*(.text.vma_adjust)
-*(.text.test_clear_page_dirty)
-*(.text.sync_buffer)
-*(.text.do_exit)
-*(.text.__bitmap_weight)
-*(.text.alloc_pages_current)
-*(.text.get_unused_fd)
-*(.text.zone_watermark_ok)
-*(.text.cpuset_update_task_memory_state)
-*(.text.__bitmap_empty)
-*(.text.sys_munmap)
-*(.text.__inode_dir_notify)
-*(.text.__generic_file_aio_write_nolock)
-*(.text.__pte_alloc)
-*(.text.sys_select)
-*(.text.vm_acct_memory)
-*(.text.vfs_write)
-*(.text.__lru_add_drain)
-*(.text.prio_tree_insert)
-*(.text.generic_file_aio_read)
-*(.text.vma_merge)
-*(.text.block_write_full_page)
-*(.text.__page_set_anon_rmap)
-*(.text.apic_timer_interrupt)
-*(.text.release_console_sem)
-*(.text.sys_write)
-*(.text.sys_brk)
-*(.text.dup_mm)
-*(.text.read_current_timer)
-*(.text.ll_rw_block)
-*(.text.blk_rq_map_sg)
-*(.text.dbg_userword)
-*(.text.__block_commit_write)
-*(.text.cache_grow)
-*(.text.copy_strings)
-*(.text.release_task)
-*(.text.do_sync_write)
-*(.text.unlock_page)
-*(.text.load_elf_binary)
-*(.text.__follow_mount)
-*(.text.__getblk)
-*(.text.do_sys_open)
-*(.text.current_kernel_time)
-*(.text.call_rcu)
-*(.text.write_chan)
-*(.text.vsnprintf)
-*(.text.dummy_inode_setsecurity)
-*(.text.submit_bh)
-*(.text.poll_freewait)
-*(.text.bio_alloc_bioset)
-*(.text.skb_clone)
-*(.text.page_waitqueue)
-*(.text.__mutex_lock_interruptible_slowpath)
-*(.text.get_index)
-*(.text.csum_partial_copy_generic)
-*(.text.bad_range)
-*(.text.remove_vma)
-*(.text.cp_new_stat)
-*(.text.alloc_arraycache)
-*(.text.test_clear_page_writeback)
-*(.text.strsep)
-*(.text.open_namei)
-*(.text._raw_read_unlock)
-*(.text.get_vma_policy)
-*(.text.__down_write_trylock)
-*(.text.find_get_pages)
-*(.text.tcp_rcv_established)
-*(.text.generic_make_request)
-*(.text.__block_write_full_page)
-*(.text.cfq_set_request)
-*(.text.sys_inotify_init)
-*(.text.split_vma)
-*(.text.__mod_timer)
-*(.text.get_options)
-*(.text.vma_link)
-*(.text.mpage_writepages)
-*(.text.truncate_complete_page)
-*(.text.tcp_recvmsg)
-*(.text.sigprocmask)
-*(.text.filemap_populate)
-*(.text.sys_close)
-*(.text.inotify_dev_queue_event)
-*(.text.do_task_stat)
-*(.text.__dentry_open)
-*(.text.unlink_file_vma)
-*(.text.__pollwait)
-*(.text.packet_rcv_spkt)
-*(.text.drop_buffers)
-*(.text.free_pgtables)
-*(.text.generic_file_direct_write)
-*(.text.copy_process)
-*(.text.netif_receive_skb)
-*(.text.dnotify_flush)
-*(.text.print_bad_pte)
-*(.text.anon_vma_unlink)
-*(.text.sys_mprotect)
-*(.text.sync_sb_inodes)
-*(.text.find_inode_fast)
-*(.text.dummy_inode_readlink)
-*(.text.putname)
-*(.text.init_smp_flush)
-*(.text.dbg_redzone2)
-*(.text.sk_run_filter)
-*(.text.may_expand_vm)
-*(.text.generic_file_aio_write)
-*(.text.find_next_zero_bit)
-*(.text.file_kill)
-*(.text.audit_getname)
-*(.text.arch_unmap_area_topdown)
-*(.text.alloc_page_vma)
-*(.text.tcp_transmit_skb)
-*(.text.rb_next)
-*(.text.dbg_redzone1)
-*(.text.generic_file_mmap)
-*(.text.vfs_fstat)
-*(.text.sys_time)
-*(.text.page_lock_anon_vma)
-*(.text.get_unmapped_area)
-*(.text.remote_llseek)
-*(.text.__up_read)
-*(.text.fd_install)
-*(.text.eventpoll_init_file)
-*(.text.dma_alloc_coherent)
-*(.text.create_empty_buffers)
-*(.text.__mutex_unlock_slowpath)
-*(.text.dup_fd)
-*(.text.d_alloc)
-*(.text.tty_ldisc_try)
-*(.text.sys_stime)
-*(.text.__rb_rotate_right)
-*(.text.d_validate)
-*(.text.rb_erase)
-*(.text.path_release)
-*(.text.memmove)
-*(.text.invalidate_complete_page)
-*(.text.clear_inode)
-*(.text.cache_estimate)
-*(.text.alloc_buffer_head)
-*(.text.smp_call_function_interrupt)
-*(.text.flush_tlb_others)
-*(.text.file_move)
-*(.text.balance_dirty_pages_ratelimited)
-*(.text.vma_prio_tree_add)
-*(.text.timespec_trunc)
-*(.text.mempool_alloc)
-*(.text.iget_locked)
-*(.text.d_alloc_root)
-*(.text.cpuset_populate_dir)
-*(.text.anon_vma_prepare)
-*(.text.sys_newstat)
-*(.text.alloc_page_interleave)
-*(.text.__path_lookup_intent_open)
-*(.text.__pagevec_free)
-*(.text.inode_init_once)
-*(.text.free_vfsmnt)
-*(.text.__user_walk_fd)
-*(.text.cfq_idle_slice_timer)
-*(.text.sys_mmap)
-*(.text.sys_llseek)
-*(.text.prio_tree_remove)
-*(.text.filp_close)
-*(.text.file_permission)
-*(.text.vma_prio_tree_remove)
-*(.text.tcp_ack)
-*(.text.nameidata_to_filp)
-*(.text.sys_lseek)
-*(.text.percpu_counter_mod)
-*(.text.igrab)
-*(.text.__bread)
-*(.text.alloc_inode)
-*(.text.filldir)
-*(.text.__rb_rotate_left)
-*(.text.irq_affinity_write_proc)
-*(.text.init_request_from_bio)
-*(.text.find_or_create_page)
-*(.text.tty_poll)
-*(.text.tcp_sendmsg)
-*(.text.ide_wait_stat)
-*(.text.free_buffer_head)
-*(.text.flush_signal_handlers)
-*(.text.tcp_v4_rcv)
-*(.text.nr_blockdev_pages)
-*(.text.locks_remove_flock)
-*(.text.__iowrite32_copy)
-*(.text.do_filp_open)
-*(.text.try_to_release_page)
-*(.text.page_add_new_anon_rmap)
-*(.text.kmem_cache_size)
-*(.text.eth_type_trans)
-*(.text.try_to_free_buffers)
-*(.text.schedule_tail)
-*(.text.proc_lookup)
-*(.text.no_llseek)
-*(.text.kfree_skbmem)
-*(.text.do_wait)
-*(.text.do_mpage_readpage)
-*(.text.vfs_stat_fd)
-*(.text.tty_write)
-*(.text.705)
-*(.text.sync_page)
-*(.text.__remove_shared_vm_struct)
-*(.text.__kfree_skb)
-*(.text.sock_poll)
-*(.text.get_request_wait)
-*(.text.do_sigaction)
-*(.text.do_brk)
-*(.text.tcp_event_data_recv)
-*(.text.read_chan)
-*(.text.pipe_writev)
-*(.text.__emul_lookup_dentry)
-*(.text.rtc_get_rtc_time)
-*(.text.print_objinfo)
-*(.text.file_update_time)
-*(.text.do_signal)
-*(.text.disable_8259A_irq)
-*(.text.blk_queue_bounce)
-*(.text.__anon_vma_link)
-*(.text.__vma_link)
-*(.text.vfs_rename)
-*(.text.sys_newlstat)
-*(.text.sys_newfstat)
-*(.text.sys_mknod)
-*(.text.__show_regs)
-*(.text.iput)
-*(.text.get_signal_to_deliver)
-*(.text.flush_tlb_page)
-*(.text.debug_mutex_wake_waiter)
-*(.text.copy_thread)
-*(.text.clear_page_dirty_for_io)
-*(.text.buffer_io_error)
-*(.text.vfs_permission)
-*(.text.truncate_inode_pages_range)
-*(.text.sys_recvfrom)
-*(.text.remove_suid)
-*(.text.mark_buffer_dirty)
-*(.text.local_bh_enable)
-*(.text.get_zeroed_page)
-*(.text.get_vmalloc_info)
-*(.text.flush_old_exec)
-*(.text.dummy_inode_permission)
-*(.text.__bio_add_page)
-*(.text.prio_tree_replace)
-*(.text.notify_change)
-*(.text.mntput_no_expire)
-*(.text.fput)
-*(.text.__end_that_request_first)
-*(.text.wake_up_bit)
-*(.text.unuse_mm)
-*(.text.shrink_icache_memory)
-*(.text.sched_balance_self)
-*(.text.__pmd_alloc)
-*(.text.pipe_poll)
-*(.text.normal_poll)
-*(.text.__free_pages)
-*(.text.follow_mount)
-*(.text.cdrom_start_packet_command)
-*(.text.blk_recount_segments)
-*(.text.bio_put)
-*(.text.__alloc_skb)
-*(.text.__wake_up)
-*(.text.vm_stat_account)
-*(.text.sys_fcntl)
-*(.text.sys_fadvise64)
-*(.text._raw_write_unlock)
-*(.text.__pud_alloc)
-*(.text.alloc_page_buffers)
-*(.text.vfs_llseek)
-*(.text.sockfd_lookup)
-*(.text._raw_write_lock)
-*(.text.put_compound_page)
-*(.text.prune_dcache)
-*(.text.pipe_readv)
-*(.text.mempool_free)
-*(.text.make_ahead_window)
-*(.text.lru_add_drain)
-*(.text.constant_test_bit)
-*(.text.__clear_user)
-*(.text.arch_unmap_area)
-*(.text.anon_vma_link)
-*(.text.sys_chroot)
-*(.text.setup_arg_pages)
-*(.text.radix_tree_preload)
-*(.text.init_rwsem)
-*(.text.generic_osync_inode)
-*(.text.generic_delete_inode)
-*(.text.do_sys_poll)
-*(.text.dev_queue_xmit)
-*(.text.default_llseek)
-*(.text.__writeback_single_inode)
-*(.text.vfs_ioctl)
-*(.text.__up_write)
-*(.text.unix_poll)
-*(.text.sys_rt_sigprocmask)
-*(.text.sock_recvmsg)
-*(.text.recalc_bh_state)
-*(.text.__put_unused_fd)
-*(.text.process_backlog)
-*(.text.locks_remove_posix)
-*(.text.lease_modify)
-*(.text.expand_files)
-*(.text.end_buffer_read_nobh)
-*(.text.d_splice_alias)
-*(.text.debug_mutex_init_waiter)
-*(.text.copy_from_user)
-*(.text.cap_vm_enough_memory)
-*(.text.show_vfsmnt)
-*(.text.release_sock)
-*(.text.pfifo_fast_enqueue)
-*(.text.half_md4_transform)
-*(.text.fs_may_remount_ro)
-*(.text.do_fork)
-*(.text.copy_hugetlb_page_range)
-*(.text.cache_free_debugcheck)
-*(.text.__tcp_select_window)
-*(.text.task_handoff_register)
-*(.text.sys_open)
-*(.text.strlcpy)
-*(.text.skb_copy_datagram_iovec)
-*(.text.set_up_list3s)
-*(.text.release_open_intent)
-*(.text.qdisc_restart)
-*(.text.n_tty_chars_in_buffer)
-*(.text.inode_change_ok)
-*(.text.__downgrade_write)
-*(.text.debug_mutex_unlock)
-*(.text.add_timer_randomness)
-*(.text.sock_common_recvmsg)
-*(.text.set_bh_page)
-*(.text.printk_lock)
-*(.text.path_release_on_umount)
-*(.text.ip_output)
-*(.text.ide_build_dmatable)
-*(.text.__get_user_8)
-*(.text.end_buffer_read_sync)
-*(.text.__d_path)
-*(.text.d_move)
-*(.text.del_timer)
-*(.text.constant_test_bit)
-*(.text.blockable_page_cache_readahead)
-*(.text.tty_read)
-*(.text.sys_readlink)
-*(.text.sys_faccessat)
-*(.text.read_swap_cache_async)
-*(.text.pty_write_room)
-*(.text.page_address_in_vma)
-*(.text.kthread)
-*(.text.cfq_exit_io_context)
-*(.text.__tcp_push_pending_frames)
-*(.text.sys_pipe)
-*(.text.submit_bio)
-*(.text.pid_revalidate)
-*(.text.page_referenced_file)
-*(.text.lock_sock)
-*(.text.get_page_state_node)
-*(.text.generic_block_bmap)
-*(.text.do_setitimer)
-*(.text.dev_queue_xmit_nit)
-*(.text.copy_from_read_buf)
-*(.text.__const_udelay)
-*(.text.console_conditional_schedule)
-*(.text.wake_up_new_task)
-*(.text.wait_for_completion_interruptible)
-*(.text.tcp_rcv_rtt_update)
-*(.text.sys_mlockall)
-*(.text.set_fs_altroot)
-*(.text.schedule_timeout)
-*(.text.nr_free_pagecache_pages)
-*(.text.nf_iterate)
-*(.text.mapping_tagged)
-*(.text.ip_queue_xmit)
-*(.text.ip_local_deliver)
-*(.text.follow_page)
-*(.text.elf_map)
-*(.text.dummy_file_permission)
-*(.text.dispose_list)
-*(.text.dentry_open)
-*(.text.dentry_iput)
-*(.text.bio_alloc)
-*(.text.wait_on_page_bit)
-*(.text.vfs_readdir)
-*(.text.vfs_lstat)
-*(.text.seq_escape)
-*(.text.__posix_lock_file)
-*(.text.mm_release)
-*(.text.kref_put)
-*(.text.ip_rcv)
-*(.text.__iget)
-*(.text.free_pages)
-*(.text.find_mergeable_anon_vma)
-*(.text.find_extend_vma)
-*(.text.dummy_inode_listsecurity)
-*(.text.bio_add_page)
-*(.text.__vm_enough_memory)
-*(.text.vfs_stat)
-*(.text.tty_paranoia_check)
-*(.text.tcp_read_sock)
-*(.text.tcp_data_queue)
-*(.text.sys_uname)
-*(.text.sys_renameat)
-*(.text.__strncpy_from_user)
-*(.text.__mutex_init)
-*(.text.__lookup_hash)
-*(.text.kref_get)
-*(.text.ip_route_input)
-*(.text.__insert_inode_hash)
-*(.text.do_sock_write)
-*(.text.blk_done_softirq)
-*(.text.__wake_up_sync)
-*(.text.__vma_link_rb)
-*(.text.tty_ioctl)
-*(.text.tracesys)
-*(.text.sys_getdents)
-*(.text.sys_dup)
-*(.text.stub_execve)
-*(.text.sha_transform)
-*(.text.radix_tree_tag_clear)
-*(.text.put_unused_fd)
-*(.text.put_files_struct)
-*(.text.mpage_readpages)
-*(.text.may_delete)
-*(.text.kmem_cache_create)
-*(.text.ip_mc_output)
-*(.text.interleave_nodes)
-*(.text.groups_search)
-*(.text.generic_drop_inode)
-*(.text.generic_commit_write)
-*(.text.fcntl_setlk)
-*(.text.exit_mmap)
-*(.text.end_page_writeback)
-*(.text.__d_rehash)
-*(.text.debug_mutex_free_waiter)
-*(.text.csum_ipv6_magic)
-*(.text.count)
-*(.text.cleanup_rbuf)
-*(.text.check_spinlock_acquired_node)
-*(.text.can_vma_merge_after)
-*(.text.bio_endio)
-*(.text.alloc_pidmap)
-*(.text.write_ldt)
-*(.text.vmtruncate_range)
-*(.text.vfs_create)
-*(.text.__user_walk)
-*(.text.update_send_head)
-*(.text.unmap_underlying_metadata)
-*(.text.tty_ldisc_deref)
-*(.text.tcp_setsockopt)
-*(.text.tcp_send_ack)
-*(.text.sys_pause)
-*(.text.sys_gettimeofday)
-*(.text.sync_dirty_buffer)
-*(.text.strncmp)
-*(.text.release_posix_timer)
-*(.text.proc_file_read)
-*(.text.prepare_to_wait)
-*(.text.locks_mandatory_locked)
-*(.text.interruptible_sleep_on_timeout)
-*(.text.inode_sub_bytes)
-*(.text.in_group_p)
-*(.text.hrtimer_try_to_cancel)
-*(.text.filldir64)
-*(.text.fasync_helper)
-*(.text.dummy_sb_pivotroot)
-*(.text.d_lookup)
-*(.text.d_instantiate)
-*(.text.__d_find_alias)
-*(.text.cpu_idle_wait)
-*(.text.cond_resched_lock)
-*(.text.chown_common)
-*(.text.blk_congestion_wait)
-*(.text.activate_page)
-*(.text.unlock_buffer)
-*(.text.tty_wakeup)
-*(.text.tcp_v4_do_rcv)
-*(.text.tcp_current_mss)
-*(.text.sys_openat)
-*(.text.sys_fchdir)
-*(.text.strnlen_user)
-*(.text.strnlen)
-*(.text.strchr)
-*(.text.sock_common_getsockopt)
-*(.text.skb_checksum)
-*(.text.remove_wait_queue)
-*(.text.rb_replace_node)
-*(.text.radix_tree_node_ctor)
-*(.text.pty_chars_in_buffer)
-*(.text.profile_hit)
-*(.text.prio_tree_left)
-*(.text.pgd_clear_bad)
-*(.text.pfifo_fast_dequeue)
-*(.text.page_referenced)
-*(.text.open_exec)
-*(.text.mmput)
-*(.text.mm_init)
-*(.text.__ide_dma_off_quietly)
-*(.text.ide_dma_intr)
-*(.text.hrtimer_start)
-*(.text.get_io_context)
-*(.text.__get_free_pages)
-*(.text.find_first_zero_bit)
-*(.text.file_free_rcu)
-*(.text.dummy_socket_sendmsg)
-*(.text.do_unlinkat)
-*(.text.do_arch_prctl)
-*(.text.destroy_inode)
-*(.text.can_vma_merge_before)
-*(.text.block_sync_page)
-*(.text.block_prepare_write)
-*(.text.bio_init)
-*(.text.arch_ptrace)
-*(.text.wake_up_inode)
-*(.text.wait_on_retry_sync_kiocb)
-*(.text.vma_prio_tree_next)
-*(.text.tcp_rcv_space_adjust)
-*(.text.__tcp_ack_snd_check)
-*(.text.sys_utime)
-*(.text.sys_recvmsg)
-*(.text.sys_mremap)
-*(.text.sys_bdflush)
-*(.text.sleep_on)
-*(.text.set_page_dirty_lock)
-*(.text.seq_path)
-*(.text.schedule_timeout_interruptible)
-*(.text.sched_fork)
-*(.text.rt_run_flush)
-*(.text.profile_munmap)
-*(.text.prepare_binprm)
-*(.text.__pagevec_release_nonlru)
-*(.text.m_show)
-*(.text.lookup_mnt)
-*(.text.__lookup_mnt)
-*(.text.lock_timer_base)
-*(.text.is_subdir)
-*(.text.invalidate_bh_lru)
-*(.text.init_buffer_head)
-*(.text.ifind_fast)
-*(.text.ide_dma_start)
-*(.text.__get_page_state)
-*(.text.flock_to_posix_lock)
-*(.text.__find_symbol)
-*(.text.do_futex)
-*(.text.do_execve)
-*(.text.dirty_writeback_centisecs_handler)
-*(.text.dev_watchdog)
-*(.text.can_share_swap_page)
-*(.text.blkdev_put)
-*(.text.bio_get_nr_vecs)
-*(.text.xfrm_compile_policy)
-*(.text.vma_prio_tree_insert)
-*(.text.vfs_lstat_fd)
-*(.text.__user_path_lookup_open)
-*(.text.thread_return)
-*(.text.tcp_send_delayed_ack)
-*(.text.sock_def_error_report)
-*(.text.shrink_slab)
-*(.text.serial_out)
-*(.text.seq_read)
-*(.text.secure_ip_id)
-*(.text.search_binary_handler)
-*(.text.proc_pid_unhash)
-*(.text.pagevec_lookup)
-*(.text.new_inode)
-*(.text.memcpy_toiovec)
-*(.text.locks_free_lock)
-*(.text.__lock_page)
-*(.text.__lock_buffer)
-*(.text.load_module)
-*(.text.is_bad_inode)
-*(.text.invalidate_inode_buffers)
-*(.text.insert_vm_struct)
-*(.text.inode_setattr)
-*(.text.inode_add_bytes)
-*(.text.ide_read_24)
-*(.text.ide_get_error_location)
-*(.text.ide_do_drive_cmd)
-*(.text.get_locked_pte)
-*(.text.get_filesystem_list)
-*(.text.generic_file_open)
-*(.text.follow_down)
-*(.text.find_next_bit)
-*(.text.__find_first_bit)
-*(.text.exit_mm)
-*(.text.exec_keys)
-*(.text.end_buffer_write_sync)
-*(.text.end_bio_bh_io_sync)
-*(.text.dummy_socket_shutdown)
-*(.text.d_rehash)
-*(.text.d_path)
-*(.text.do_ioctl)
-*(.text.dget_locked)
-*(.text.copy_thread_group_keys)
-*(.text.cdrom_end_request)
-*(.text.cap_bprm_apply_creds)
-*(.text.blk_rq_bio_prep)
-*(.text.__bitmap_intersects)
-*(.text.bio_phys_segments)
-*(.text.bio_free)
-*(.text.arch_get_unmapped_area_topdown)
-*(.text.writeback_in_progress)
-*(.text.vfs_follow_link)
-*(.text.tcp_rcv_state_process)
-*(.text.tcp_check_space)
-*(.text.sys_stat)
-*(.text.sys_rt_sigreturn)
-*(.text.sys_rt_sigaction)
-*(.text.sys_remap_file_pages)
-*(.text.sys_pwrite64)
-*(.text.sys_fchownat)
-*(.text.sys_fchmodat)
-*(.text.strncat)
-*(.text.strlcat)
-*(.text.strcmp)
-*(.text.steal_locks)
-*(.text.sock_create)
-*(.text.sk_stream_rfree)
-*(.text.sk_stream_mem_schedule)
-*(.text.skip_atoi)
-*(.text.sk_alloc)
-*(.text.show_stat)
-*(.text.set_fs_pwd)
-*(.text.set_binfmt)
-*(.text.pty_unthrottle)
-*(.text.proc_symlink)
-*(.text.pipe_release)
-*(.text.pageout)
-*(.text.n_tty_write_wakeup)
-*(.text.n_tty_ioctl)
-*(.text.nr_free_zone_pages)
-*(.text.migration_thread)
-*(.text.mempool_free_slab)
-*(.text.meminfo_read_proc)
-*(.text.max_sane_readahead)
-*(.text.lru_cache_add)
-*(.text.kill_fasync)
-*(.text.kernel_read)
-*(.text.invalidate_mapping_pages)
-*(.text.inode_has_buffers)
-*(.text.init_once)
-*(.text.inet_sendmsg)
-*(.text.idedisk_issue_flush)
-*(.text.generic_file_write)
-*(.text.free_more_memory)
-*(.text.__free_fdtable)
-*(.text.filp_dtor)
-*(.text.exit_sem)
-*(.text.exit_itimers)
-*(.text.error_interrupt)
-*(.text.end_buffer_async_write)
-*(.text.eligible_child)
-*(.text.elf_map)
-*(.text.dump_task_regs)
-*(.text.dummy_task_setscheduler)
-*(.text.dummy_socket_accept)
-*(.text.dummy_file_free_security)
-*(.text.__down_read)
-*(.text.do_sock_read)
-*(.text.do_sigaltstack)
-*(.text.do_mremap)
-*(.text.current_io_context)
-*(.text.cpu_swap_callback)
-*(.text.copy_vma)
-*(.text.cap_bprm_set_security)
-*(.text.blk_insert_request)
-*(.text.bio_map_kern_endio)
-*(.text.bio_hw_segments)
-*(.text.bictcp_cong_avoid)
-*(.text.add_interrupt_randomness)
-*(.text.wait_for_completion)
-*(.text.version_read_proc)
-*(.text.unix_write_space)
-*(.text.tty_ldisc_ref_wait)
-*(.text.tty_ldisc_put)
-*(.text.try_to_wake_up)
-*(.text.tcp_v4_tw_remember_stamp)
-*(.text.tcp_try_undo_dsack)
-*(.text.tcp_may_send_now)
-*(.text.sys_waitid)
-*(.text.sys_sched_getparam)
-*(.text.sys_getppid)
-*(.text.sys_getcwd)
-*(.text.sys_dup2)
-*(.text.sys_chmod)
-*(.text.sys_chdir)
-*(.text.sprintf)
-*(.text.sock_wfree)
-*(.text.sock_aio_write)
-*(.text.skb_drop_fraglist)
-*(.text.skb_dequeue)
-*(.text.set_close_on_exec)
-*(.text.set_brk)
-*(.text.seq_puts)
-*(.text.SELECT_DRIVE)
-*(.text.sched_exec)
-*(.text.return_EIO)
-*(.text.remove_from_page_cache)
-*(.text.rcu_start_batch)
-*(.text.__put_task_struct)
-*(.text.proc_pid_readdir)
-*(.text.proc_get_inode)
-*(.text.prepare_to_wait_exclusive)
-*(.text.pipe_wait)
-*(.text.pipe_new)
-*(.text.pdflush_operation)
-*(.text.__pagevec_release)
-*(.text.pagevec_lookup_tag)
-*(.text.packet_rcv)
-*(.text.n_tty_set_room)
-*(.text.nr_free_pages)
-*(.text.__net_timestamp)
-*(.text.mpage_end_io_read)
-*(.text.mod_timer)
-*(.text.__memcpy)
-*(.text.mb_cache_shrink_fn)
-*(.text.lock_rename)
-*(.text.kstrdup)
-*(.text.is_ignored)
-*(.text.int_very_careful)
-*(.text.inotify_inode_is_dead)
-*(.text.inotify_get_cookie)
-*(.text.inode_get_bytes)
-*(.text.init_timer)
-*(.text.init_dev)
-*(.text.inet_getname)
-*(.text.ide_map_sg)
-*(.text.__ide_dma_end)
-*(.text.hrtimer_get_remaining)
-*(.text.get_task_mm)
-*(.text.get_random_int)
-*(.text.free_pipe_info)
-*(.text.filemap_write_and_wait_range)
-*(.text.exit_thread)
-*(.text.enter_idle)
-*(.text.end_that_request_first)
-*(.text.end_8259A_irq)
-*(.text.dummy_file_alloc_security)
-*(.text.do_group_exit)
-*(.text.debug_mutex_init)
-*(.text.cpuset_exit)
-*(.text.cpu_idle)
-*(.text.copy_semundo)
-*(.text.copy_files)
-*(.text.chrdev_open)
-*(.text.cdrom_transfer_packet_command)
-*(.text.cdrom_mode_sense)
-*(.text.blk_phys_contig_segment)
-*(.text.blk_get_queue)
-*(.text.bio_split)
-*(.text.audit_alloc)
-*(.text.anon_pipe_buf_release)
-*(.text.add_wait_queue_exclusive)
-*(.text.add_wait_queue)
-*(.text.acct_process)
-*(.text.account)
-*(.text.zeromap_page_range)
-*(.text.yield)
-*(.text.writeback_acquire)
-*(.text.worker_thread)
-*(.text.wait_on_page_writeback_range)
-*(.text.__wait_on_buffer)
-*(.text.vscnprintf)
-*(.text.vmalloc_to_pfn)
-*(.text.vgacon_save_screen)
-*(.text.vfs_unlink)
-*(.text.vfs_rmdir)
-*(.text.unregister_md_personality)
-*(.text.unlock_new_inode)
-*(.text.unix_stream_sendmsg)
-*(.text.unix_stream_recvmsg)
-*(.text.unhash_process)
-*(.text.udp_v4_lookup_longway)
-*(.text.tty_ldisc_flush)
-*(.text.tty_ldisc_enable)
-*(.text.tty_hung_up_p)
-*(.text.tty_buffer_free_all)
-*(.text.tso_fragment)
-*(.text.try_to_del_timer_sync)
-*(.text.tcp_v4_err)
-*(.text.tcp_unhash)
-*(.text.tcp_seq_next)
-*(.text.tcp_select_initial_window)
-*(.text.tcp_sacktag_write_queue)
-*(.text.tcp_cwnd_validate)
-*(.text.sys_vhangup)
-*(.text.sys_uselib)
-*(.text.sys_symlink)
-*(.text.sys_signal)
-*(.text.sys_poll)
-*(.text.sys_mount)
-*(.text.sys_kill)
-*(.text.sys_ioctl)
-*(.text.sys_inotify_add_watch)
-*(.text.sys_getuid)
-*(.text.sys_getrlimit)
-*(.text.sys_getitimer)
-*(.text.sys_getgroups)
-*(.text.sys_ftruncate)
-*(.text.sysfs_lookup)
-*(.text.sys_exit_group)
-*(.text.stub_fork)
-*(.text.sscanf)
-*(.text.sock_map_fd)
-*(.text.sock_get_timestamp)
-*(.text.__sock_create)
-*(.text.smp_call_function_single)
-*(.text.sk_stop_timer)
-*(.text.skb_copy_and_csum_datagram)
-*(.text.__skb_checksum_complete)
-*(.text.single_next)
-*(.text.sigqueue_alloc)
-*(.text.shrink_dcache_parent)
-*(.text.select_idle_routine)
-*(.text.run_workqueue)
-*(.text.run_local_timers)
-*(.text.remove_inode_hash)
-*(.text.remove_dquot_ref)
-*(.text.register_binfmt)
-*(.text.read_cache_pages)
-*(.text.rb_last)
-*(.text.pty_open)
-*(.text.proc_root_readdir)
-*(.text.proc_pid_flush)
-*(.text.proc_pident_lookup)
-*(.text.proc_fill_super)
-*(.text.proc_exe_link)
-*(.text.posix_locks_deadlock)
-*(.text.pipe_iov_copy_from_user)
-*(.text.opost)
-*(.text.nf_register_hook)
-*(.text.netif_rx_ni)
-*(.text.m_start)
-*(.text.mpage_writepage)
-*(.text.mm_alloc)
-*(.text.memory_open)
-*(.text.mark_buffer_async_write)
-*(.text.lru_add_drain_all)
-*(.text.locks_init_lock)
-*(.text.locks_delete_lock)
-*(.text.lock_hrtimer_base)
-*(.text.load_script)
-*(.text.__kill_fasync)
-*(.text.ip_mc_sf_allow)
-*(.text.__ioremap)
-*(.text.int_with_check)
-*(.text.int_sqrt)
-*(.text.install_thread_keyring)
-*(.text.init_page_buffers)
-*(.text.inet_sock_destruct)
-*(.text.idle_notifier_register)
-*(.text.ide_execute_command)
-*(.text.ide_end_drive_cmd)
-*(.text.__ide_dma_host_on)
-*(.text.hrtimer_run_queues)
-*(.text.hpet_mask_rtc_irq_bit)
-*(.text.__get_zone_counts)
-*(.text.get_zone_counts)
-*(.text.get_write_access)
-*(.text.get_fs_struct)
-*(.text.get_dirty_limits)
-*(.text.generic_readlink)
-*(.text.free_hot_page)
-*(.text.finish_wait)
-*(.text.find_inode)
-*(.text.find_first_bit)
-*(.text.__filemap_fdatawrite_range)
-*(.text.__filemap_copy_from_user_iovec)
-*(.text.exit_aio)
-*(.text.elv_set_request)
-*(.text.elv_former_request)
-*(.text.dup_namespace)
-*(.text.dupfd)
-*(.text.dummy_socket_getsockopt)
-*(.text.dummy_sb_post_mountroot)
-*(.text.dummy_quotactl)
-*(.text.dummy_inode_rename)
-*(.text.__do_SAK)
-*(.text.do_pipe)
-*(.text.do_fsync)
-*(.text.d_instantiate_unique)
-*(.text.d_find_alias)
-*(.text.deny_write_access)
-*(.text.dentry_unhash)
-*(.text.d_delete)
-*(.text.datagram_poll)
-*(.text.cpuset_fork)
-*(.text.cpuid_read)
-*(.text.copy_namespace)
-*(.text.cond_resched)
-*(.text.check_version)
-*(.text.__change_page_attr)
-*(.text.cfq_slab_kill)
-*(.text.cfq_completed_request)
-*(.text.cdrom_pc_intr)
-*(.text.cdrom_decode_status)
-*(.text.cap_capset_check)
-*(.text.blk_put_request)
-*(.text.bio_fs_destructor)
-*(.text.bictcp_min_cwnd)
-*(.text.alloc_chrdev_region)
-*(.text.add_element)
-*(.text.acct_update_integrals)
-*(.text.write_boundary_block)
-*(.text.writeback_release)
-*(.text.writeback_inodes)
-*(.text.wake_up_state)
-*(.text.__wake_up_locked)
-*(.text.wake_futex)
-*(.text.wait_task_inactive)
-*(.text.__wait_on_freeing_inode)
-*(.text.wait_noreap_copyout)
-*(.text.vmstat_start)
-*(.text.vgacon_do_font_op)
-*(.text.vfs_readv)
-*(.text.vfs_quota_sync)
-*(.text.update_queue)
-*(.text.unshare_files)
-*(.text.unmap_vm_area)
-*(.text.unix_socketpair)
-*(.text.unix_release_sock)
-*(.text.unix_detach_fds)
-*(.text.unix_create1)
-*(.text.unix_bind)
-*(.text.udp_sendmsg)
-*(.text.udp_rcv)
-*(.text.udp_queue_rcv_skb)
-*(.text.uart_write)
-*(.text.uart_startup)
-*(.text.uart_open)
-*(.text.tty_vhangup)
-*(.text.tty_termios_baud_rate)
-*(.text.tty_release)
-*(.text.tty_ldisc_ref)
-*(.text.throttle_vm_writeout)
-*(.text.058)
-*(.text.tcp_xmit_probe_skb)
-*(.text.tcp_v4_send_check)
-*(.text.tcp_v4_destroy_sock)
-*(.text.tcp_sync_mss)
-*(.text.tcp_snd_test)
-*(.text.tcp_slow_start)
-*(.text.tcp_send_fin)
-*(.text.tcp_rtt_estimator)
-*(.text.tcp_parse_options)
-*(.text.tcp_ioctl)
-*(.text.tcp_init_tso_segs)
-*(.text.tcp_init_cwnd)
-*(.text.tcp_getsockopt)
-*(.text.tcp_fin)
-*(.text.tcp_connect)
-*(.text.tcp_cong_avoid)
-*(.text.__tcp_checksum_complete_user)
-*(.text.task_dumpable)
-*(.text.sys_wait4)
-*(.text.sys_utimes)
-*(.text.sys_symlinkat)
-*(.text.sys_socketpair)
-*(.text.sys_rmdir)
-*(.text.sys_readahead)
-*(.text.sys_nanosleep)
-*(.text.sys_linkat)
-*(.text.sys_fstat)
-*(.text.sysfs_readdir)
-*(.text.sys_execve)
-*(.text.sysenter_tracesys)
-*(.text.sys_chown)
-*(.text.stub_clone)
-*(.text.strrchr)
-*(.text.strncpy)
-*(.text.stopmachine_set_state)
-*(.text.sock_sendmsg)
-*(.text.sock_release)
-*(.text.sock_fasync)
-*(.text.sock_close)
-*(.text.sk_stream_write_space)
-*(.text.sk_reset_timer)
-*(.text.skb_split)
-*(.text.skb_recv_datagram)
-*(.text.skb_queue_tail)
-*(.text.sk_attach_filter)
-*(.text.si_swapinfo)
-*(.text.simple_strtoll)
-*(.text.set_termios)
-*(.text.set_task_comm)
-*(.text.set_shrinker)
-*(.text.set_normalized_timespec)
-*(.text.set_brk)
-*(.text.serial_in)
-*(.text.seq_printf)
-*(.text.secure_dccp_sequence_number)
-*(.text.rwlock_bug)
-*(.text.rt_hash_code)
-*(.text.__rta_fill)
-*(.text.__request_resource)
-*(.text.relocate_new_kernel)
-*(.text.release_thread)
-*(.text.release_mem)
-*(.text.rb_prev)
-*(.text.rb_first)
-*(.text.random_poll)
-*(.text.__put_super_and_need_restart)
-*(.text.pty_write)
-*(.text.ptrace_stop)
-*(.text.proc_self_readlink)
-*(.text.proc_root_lookup)
-*(.text.proc_root_link)
-*(.text.proc_pid_make_inode)
-*(.text.proc_pid_attr_write)
-*(.text.proc_lookupfd)
-*(.text.proc_delete_inode)
-*(.text.posix_same_owner)
-*(.text.posix_block_lock)
-*(.text.poll_initwait)
-*(.text.pipe_write)
-*(.text.pipe_read_fasync)
-*(.text.pipe_ioctl)
-*(.text.pdflush)
-*(.text.pci_user_read_config_dword)
-*(.text.page_readlink)
-*(.text.null_lseek)
-*(.text.nf_hook_slow)
-*(.text.netlink_sock_destruct)
-*(.text.netlink_broadcast)
-*(.text.neigh_resolve_output)
-*(.text.name_to_int)
-*(.text.mwait_idle)
-*(.text.mutex_trylock)
-*(.text.mutex_debug_check_no_locks_held)
-*(.text.m_stop)
-*(.text.mpage_end_io_write)
-*(.text.mpage_alloc)
-*(.text.move_page_tables)
-*(.text.mounts_open)
-*(.text.__memset)
-*(.text.memcpy_fromiovec)
-*(.text.make_8259A_irq)
-*(.text.lookup_user_key_possessed)
-*(.text.lookup_create)
-*(.text.locks_insert_lock)
-*(.text.locks_alloc_lock)
-*(.text.kthread_should_stop)
-*(.text.kswapd)
-*(.text.kobject_uevent)
-*(.text.kobject_get_path)
-*(.text.kobject_get)
-*(.text.klist_children_put)
-*(.text.__ip_route_output_key)
-*(.text.ip_flush_pending_frames)
-*(.text.ip_compute_csum)
-*(.text.ip_append_data)
-*(.text.ioc_set_batching)
-*(.text.invalidate_inode_pages)
-*(.text.__invalidate_device)
-*(.text.install_arg_page)
-*(.text.in_sched_functions)
-*(.text.inotify_unmount_inodes)
-*(.text.init_once)
-*(.text.init_cdrom_command)
-*(.text.inet_stream_connect)
-*(.text.inet_sk_rebuild_header)
-*(.text.inet_csk_addr2sockaddr)
-*(.text.inet_create)
-*(.text.ifind)
-*(.text.ide_setup_dma)
-*(.text.ide_outsw)
-*(.text.ide_fixstring)
-*(.text.ide_dma_setup)
-*(.text.ide_cdrom_packet)
-*(.text.ide_cd_put)
-*(.text.ide_build_sglist)
-*(.text.i8259A_shutdown)
-*(.text.hung_up_tty_ioctl)
-*(.text.hrtimer_nanosleep)
-*(.text.hrtimer_init)
-*(.text.hrtimer_cancel)
-*(.text.hash_futex)
-*(.text.group_send_sig_info)
-*(.text.grab_cache_page_nowait)
-*(.text.get_wchan)
-*(.text.get_stack)
-*(.text.get_page_state)
-*(.text.getnstimeofday)
-*(.text.get_node)
-*(.text.get_kprobe)
-*(.text.generic_unplug_device)
-*(.text.free_task)
-*(.text.frag_show)
-*(.text.find_next_zero_string)
-*(.text.filp_open)
-*(.text.fillonedir)
-*(.text.exit_io_context)
-*(.text.exit_idle)
-*(.text.exact_lock)
-*(.text.eth_header)
-*(.text.dummy_unregister_security)
-*(.text.dummy_socket_post_create)
-*(.text.dummy_socket_listen)
-*(.text.dummy_quota_on)
-*(.text.dummy_inode_follow_link)
-*(.text.dummy_file_receive)
-*(.text.dummy_file_mprotect)
-*(.text.dummy_file_lock)
-*(.text.dummy_file_ioctl)
-*(.text.dummy_bprm_post_apply_creds)
-*(.text.do_writepages)
-*(.text.__down_interruptible)
-*(.text.do_notify_resume)
-*(.text.do_acct_process)
-*(.text.del_timer_sync)
-*(.text.default_rebuild_header)
-*(.text.d_callback)
-*(.text.dcache_readdir)
-*(.text.ctrl_dumpfamily)
-*(.text.cpuset_rmdir)
-*(.text.copy_strings_kernel)
-*(.text.con_write_room)
-*(.text.complete_all)
-*(.text.collect_sigign_sigcatch)
-*(.text.clear_user)
-*(.text.check_unthrottle)
-*(.text.cdrom_release)
-*(.text.cdrom_newpc_intr)
-*(.text.cdrom_ioctl)
-*(.text.cdrom_check_status)
-*(.text.cdev_put)
-*(.text.cdev_add)
-*(.text.cap_ptrace)
-*(.text.cap_bprm_secureexec)
-*(.text.cache_alloc_refill)
-*(.text.bmap)
-*(.text.blk_run_queue)
-*(.text.blk_queue_dma_alignment)
-*(.text.blk_ordered_req_seq)
-*(.text.blk_backing_dev_unplug)
-*(.text.__bitmap_subset)
-*(.text.__bitmap_and)
-*(.text.bio_unmap_user)
-*(.text.__bforget)
-*(.text.bd_forget)
-*(.text.bad_pipe_w)
-*(.text.bad_get_user)
-*(.text.audit_free)
-*(.text.anon_vma_ctor)
-*(.text.anon_pipe_buf_map)
-*(.text.alloc_sock_iocb)
-*(.text.alloc_fdset)
-*(.text.aio_kick_handler)
-*(.text.__add_entropy_words)
-*(.text.add_disk_randomness)
index 0b3603a..47496a4 100644 (file)
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/string.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/init.h>
-#include <linux/module.h>
 
 #include <asm/smp.h>
 #include <asm/ipi.h>
+#include <asm/genapic.h>
 
-#if defined(CONFIG_ACPI)
+#ifdef CONFIG_ACPI
 #include <acpi/acpi_bus.h>
 #endif
 
 /* which logical CPU number maps to which CPU (physical APIC ID) */
-u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly
+                                       = { [0 ... NR_CPUS-1] = BAD_APICID };
 EXPORT_SYMBOL(x86_cpu_to_apicid);
-u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 
-extern struct genapic apic_cluster;
-extern struct genapic apic_flat;
-extern struct genapic apic_physflat;
+u8 x86_cpu_to_log_apicid[NR_CPUS]      = { [0 ... NR_CPUS-1] = BAD_APICID };
 
-struct genapic *genapic = &apic_flat;
-struct genapic *genapic_force;
+struct genapic __read_mostly *genapic = &apic_flat;
 
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  */
-void __init clustered_apic_check(void)
+void __init setup_apic_routing(void)
 {
-       long i;
-       u8 clusters, max_cluster;
-       u8 id;
-       u8 cluster_cnt[NUM_APIC_CLUSTERS];
-       int max_apic = 0;
-
-       /* genapic selection can be forced because of certain quirks.
-        */
-       if (genapic_force) {
-               genapic = genapic_force;
-               goto print;
-       }
-
-#if defined(CONFIG_ACPI)
+#ifdef CONFIG_ACPI
        /*
-        * Some x86_64 machines use physical APIC mode regardless of how many
-        * procs/clusters are present (x86_64 ES7000 is an example).
+        * Quirk: some x86_64 machines can only use physical APIC mode
+        * regardless of how many processors are present (x86_64 ES7000
+        * is an example).
         */
-       if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID)
-               if (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) {
-                       genapic = &apic_cluster;
-                       goto print;
-               }
-#endif
-
-       memset(cluster_cnt, 0, sizeof(cluster_cnt));
-       for (i = 0; i < NR_CPUS; i++) {
-               id = bios_cpu_apicid[i];
-               if (id == BAD_APICID)
-                       continue;
-               if (id > max_apic)
-                       max_apic = id;
-               cluster_cnt[APIC_CLUSTERID(id)]++;
-       }
-
-       /* Don't use clustered mode on AMD platforms. */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+       if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
+                       (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
                genapic = &apic_physflat;
-#ifndef CONFIG_HOTPLUG_CPU
-               /* In the CPU hotplug case we cannot use broadcast mode
-                  because that opens a race when a CPU is removed.
-                  Stay at physflat mode in this case.
-                  It is bad to do this unconditionally though. Once
-                  we have ACPI platform support for CPU hotplug
-                  we should detect hotplug capablity from ACPI tables and
-                  only do this when really needed. -AK */
-               if (max_apic <= 8)
-                       genapic = &apic_flat;
+       else
 #endif
-               goto print;
-       }
 
-       clusters = 0;
-       max_cluster = 0;
-
-       for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
-               if (cluster_cnt[i] > 0) {
-                       ++clusters;
-                       if (cluster_cnt[i] > max_cluster)
-                               max_cluster = cluster_cnt[i];
-               }
-       }
-
-       /*
-        * If we have clusters <= 1 and CPUs <= 8 in cluster 0, then flat mode,
-        * else if max_cluster <= 4 and cluster_cnt[15] == 0, clustered logical
-        * else physical mode.
-        * (We don't use lowest priority delivery + HW APIC IRQ steering, so
-        * can ignore the clustered logical case and go straight to physical.)
-        */
-       if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) {
-#ifdef CONFIG_HOTPLUG_CPU
-               /* Don't use APIC shortcuts in CPU hotplug to avoid races */
-               genapic = &apic_physflat;
-#else
+       if (cpus_weight(cpu_possible_map) <= 8)
                genapic = &apic_flat;
-#endif
-       } else
-               genapic = &apic_cluster;
+       else
+               genapic = &apic_physflat;
 
-print:
        printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
 }
 
-/* Same for both flat and clustered. */
+/* Same for both flat and physical. */
 
 void send_IPI_self(int vector)
 {
diff --git a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
deleted file mode 100644 (file)
index 73d7630..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2004 James Cleverdon, IBM.
- * Subject to the GNU Public License, v.2
- *
- * Clustered APIC subarch code.  Up to 255 CPUs, physical delivery.
- * (A more realistic maximum is around 230 CPUs.)
- *
- * Hacked for x86-64 by James Cleverdon from i386 architecture code by
- * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
- * James Cleverdon.
- */
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <asm/smp.h>
-#include <asm/ipi.h>
-
-
-/*
- * Set up the logical destination ID.
- *
- * Intel recommends to set DFR, LDR and TPR before enabling
- * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116).  So here it goes...
- */
-static void cluster_init_apic_ldr(void)
-{
-       unsigned long val, id;
-       long i, count;
-       u8 lid;
-       u8 my_id = hard_smp_processor_id();
-       u8 my_cluster = APIC_CLUSTER(my_id);
-
-       /* Create logical APIC IDs by counting CPUs already in cluster. */
-       for (count = 0, i = NR_CPUS; --i >= 0; ) {
-               lid = x86_cpu_to_log_apicid[i];
-               if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
-                       ++count;
-       }
-       /*
-        * We only have a 4 wide bitmap in cluster mode.  There's no way
-        * to get above 60 CPUs and still give each one it's own bit.
-        * But, we're using physical IRQ delivery, so we don't care.
-        * Use bit 3 for the 4th through Nth CPU in each cluster.
-        */
-       if (count >= XAPIC_DEST_CPUS_SHIFT)
-               count = 3;
-       id = my_cluster | (1UL << count);
-       x86_cpu_to_log_apicid[smp_processor_id()] = id;
-       apic_write(APIC_DFR, APIC_DFR_CLUSTER);
-       val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
-       val |= SET_APIC_LOGICAL_ID(id);
-       apic_write(APIC_LDR, val);
-}
-
-/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
-
-static cpumask_t cluster_target_cpus(void)
-{
-       return cpumask_of_cpu(0);
-}
-
-static cpumask_t cluster_vector_allocation_domain(int cpu)
-{
-       cpumask_t domain = CPU_MASK_NONE;
-       cpu_set(cpu, domain);
-       return domain;
-}
-
-static void cluster_send_IPI_mask(cpumask_t mask, int vector)
-{
-       send_IPI_mask_sequence(mask, vector);
-}
-
-static void cluster_send_IPI_allbutself(int vector)
-{
-       cpumask_t mask = cpu_online_map;
-
-       cpu_clear(smp_processor_id(), mask);
-
-       if (!cpus_empty(mask))
-               cluster_send_IPI_mask(mask, vector);
-}
-
-static void cluster_send_IPI_all(int vector)
-{
-       cluster_send_IPI_mask(cpu_online_map, vector);
-}
-
-static int cluster_apic_id_registered(void)
-{
-       return 1;
-}
-
-static unsigned int cluster_cpu_mask_to_apicid(cpumask_t cpumask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       cpu = first_cpu(cpumask);
-       if ((unsigned)cpu < NR_CPUS)
-               return x86_cpu_to_apicid[cpu];
-       else
-               return BAD_APICID;
-}
-
-/* cpuid returns the value latched in the HW at reset, not the APIC ID
- * register's value.  For any box whose BIOS changes APIC IDs, like
- * clustered APIC systems, we must use hard_smp_processor_id.
- *
- * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
- */
-static unsigned int phys_pkg_id(int index_msb)
-{
-       return hard_smp_processor_id() >> index_msb;
-}
-
-struct genapic apic_cluster = {
-       .name = "clustered",
-       .int_delivery_mode = dest_Fixed,
-       .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
-       .target_cpus = cluster_target_cpus,
-       .vector_allocation_domain = cluster_vector_allocation_domain,
-       .apic_id_registered = cluster_apic_id_registered,
-       .init_apic_ldr = cluster_init_apic_ldr,
-       .send_IPI_all = cluster_send_IPI_all,
-       .send_IPI_allbutself = cluster_send_IPI_allbutself,
-       .send_IPI_mask = cluster_send_IPI_mask,
-       .cpu_mask_to_apicid = cluster_cpu_mask_to_apicid,
-       .phys_pkg_id = phys_pkg_id,
-};
index 7c01db8..ecb01ee 100644 (file)
@@ -8,6 +8,7 @@
  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
  * James Cleverdon.
  */
+#include <linux/errno.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/string.h>
@@ -16,6 +17,7 @@
 #include <linux/init.h>
 #include <asm/smp.h>
 #include <asm/ipi.h>
+#include <asm/genapic.h>
 
 static cpumask_t flat_target_cpus(void)
 {
@@ -60,31 +62,10 @@ static void flat_init_apic_ldr(void)
 static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
 {
        unsigned long mask = cpus_addr(cpumask)[0];
-       unsigned long cfg;
        unsigned long flags;
 
        local_irq_save(flags);
-
-       /*
-        * Wait for idle.
-        */
-       apic_wait_icr_idle();
-
-       /*
-        * prepare target chip field
-        */
-       cfg = __prepare_ICR2(mask);
-       apic_write(APIC_ICR2, cfg);
-
-       /*
-        * program the ICR
-        */
-       cfg = __prepare_ICR(0, vector, APIC_DEST_LOGICAL);
-
-       /*
-        * Send the IPI. The write to APIC_ICR fires this off.
-        */
-       apic_write(APIC_ICR, cfg);
+       __send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
        local_irq_restore(flags);
 }
 
index 598a4d0..1fab487 100644 (file)
@@ -5,6 +5,7 @@
  *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
  *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
  *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
+ *  Copyright (C) 2005 Eric Biederman <ebiederm@xmission.com>
  */
 
 
 #include <linux/init.h>
 #include <asm/desc.h>
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/msr.h>
 #include <asm/cache.h>
-       
+
 /* we are not able to switch in one step to the final KERNEL ADRESS SPACE
- * because we need identity-mapped pages on setup so define __START_KERNEL to
- * 0x100000 for this stage
- * 
+ * because we need identity-mapped pages.
+ *
  */
 
        .text
        .section .bootstrap.text
-       .code32
-       .globl startup_32
-/* %bx:         1 if coming from smp trampoline on secondary cpu */ 
-startup_32:
-       
+       .code64
+       .globl startup_64
+startup_64:
+
        /*
-        * At this point the CPU runs in 32bit protected mode (CS.D = 1) with
-        * paging disabled and the point of this file is to switch to 64bit
-        * long mode with a kernel mapping for kerneland to jump into the
-        * kernel virtual addresses.
-        * There is no stack until we set one up.
+        * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 1,
+        * and someone has loaded an identity mapped page table
+        * for us.  These identity mapped page tables map all of the
+        * kernel pages and possibly all of memory.
+        *
+        * %esi holds a physical pointer to real_mode_data.
+        *
+        * We come here either directly from a 64bit bootloader, or from
+        * arch/x86_64/boot/compressed/head.S.
+        *
+        * We only come here initially at boot nothing else comes here.
+        *
+        * Since we may be loaded at an address different from what we were
+        * compiled to run at we first fixup the physical addresses in our page
+        * tables and then reload them.
         */
 
-       /* Initialize the %ds segment register */
-       movl $__KERNEL_DS,%eax
-       movl %eax,%ds
-
-       /* Load new GDT with the 64bit segments using 32bit descriptor */
-       lgdt    pGDT32 - __START_KERNEL_map
-
-       /* If the CPU doesn't support CPUID this will double fault.
-        * Unfortunately it is hard to check for CPUID without a stack. 
+       /* Compute the delta between the address I am compiled to run at and the
+        * address I am actually running at.
         */
-       
-       /* Check if extended functions are implemented */               
-       movl    $0x80000000, %eax
-       cpuid
-       cmpl    $0x80000000, %eax
-       jbe     no_long_mode
-       /* Check if long mode is implemented */
-       mov     $0x80000001, %eax
-       cpuid
-       btl     $29, %edx
-       jnc     no_long_mode
-
-       /*
-        * Prepare for entering 64bits mode
+       leaq    _text(%rip), %rbp
+       subq    $_text - __START_KERNEL_map, %rbp
+
+       /* Is the address not 2M aligned? */
+       movq    %rbp, %rax
+       andl    $~LARGE_PAGE_MASK, %eax
+       testl   %eax, %eax
+       jnz     bad_address
+
+       /* Is the address too large? */
+       leaq    _text(%rip), %rdx
+       movq    $PGDIR_SIZE, %rax
+       cmpq    %rax, %rdx
+       jae     bad_address
+
+       /* Fixup the physical addresses in the page table
         */
+       addq    %rbp, init_level4_pgt + 0(%rip)
+       addq    %rbp, init_level4_pgt + (258*8)(%rip)
+       addq    %rbp, init_level4_pgt + (511*8)(%rip)
+
+       addq    %rbp, level3_ident_pgt + 0(%rip)
+       addq    %rbp, level3_kernel_pgt + (510*8)(%rip)
+
+       /* Add an Identity mapping if I am above 1G */
+       leaq    _text(%rip), %rdi
+       andq    $LARGE_PAGE_MASK, %rdi
+
+       movq    %rdi, %rax
+       shrq    $PUD_SHIFT, %rax
+       andq    $(PTRS_PER_PUD - 1), %rax
+       jz      ident_complete
+
+       leaq    (level2_spare_pgt - __START_KERNEL_map + _KERNPG_TABLE)(%rbp), %rdx
+       leaq    level3_ident_pgt(%rip), %rbx
+       movq    %rdx, 0(%rbx, %rax, 8)
+
+       movq    %rdi, %rax
+       shrq    $PMD_SHIFT, %rax
+       andq    $(PTRS_PER_PMD - 1), %rax
+       leaq    __PAGE_KERNEL_LARGE_EXEC(%rdi), %rdx
+       leaq    level2_spare_pgt(%rip), %rbx
+       movq    %rdx, 0(%rbx, %rax, 8)
+ident_complete:
+
+       /* Fixup the kernel text+data virtual addresses
+        */
+       leaq    level2_kernel_pgt(%rip), %rdi
+       leaq    4096(%rdi), %r8
+       /* See if it is a valid page table entry */
+1:     testq   $1, 0(%rdi)
+       jz      2f
+       addq    %rbp, 0(%rdi)
+       /* Go to the next page */
+2:     addq    $8, %rdi
+       cmp     %r8, %rdi
+       jne     1b
+
+       /* Fixup phys_base */
+       addq    %rbp, phys_base(%rip)
 
-       /* Enable PAE mode */
-       xorl    %eax, %eax
-       btsl    $5, %eax
-       movl    %eax, %cr4
-
-       /* Setup early boot stage 4 level pagetables */
-       movl    $(boot_level4_pgt - __START_KERNEL_map), %eax
-       movl    %eax, %cr3
-
-       /* Setup EFER (Extended Feature Enable Register) */
-       movl    $MSR_EFER, %ecx
-       rdmsr
-
-       /* Enable Long Mode */
-       btsl    $_EFER_LME, %eax
-                               
-       /* Make changes effective */
-       wrmsr
+#ifdef CONFIG_SMP
+       addq    %rbp, trampoline_level4_pgt + 0(%rip)
+       addq    %rbp, trampoline_level4_pgt + (511*8)(%rip)
+#endif
+#ifdef CONFIG_ACPI_SLEEP
+       addq    %rbp, wakeup_level4_pgt + 0(%rip)
+       addq    %rbp, wakeup_level4_pgt + (511*8)(%rip)
+#endif
 
-       xorl    %eax, %eax
-       btsl    $31, %eax                       /* Enable paging and in turn activate Long Mode */
-       btsl    $0, %eax                        /* Enable protected mode */
-       /* Make changes effective */
-       movl    %eax, %cr0
-       /*
-        * At this point we're in long mode but in 32bit compatibility mode
-        * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
-        * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
-        * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+       /* Due to ENTRY(), sometimes the empty space gets filled with
+        * zeros. Better take a jmp than relying on empty space being
+        * filled with 0x90 (nop)
         */
-       ljmp    $__KERNEL_CS, $(startup_64 - __START_KERNEL_map)
-
-       .code64
-       .org 0x100      
-       .globl startup_64
-startup_64:
-       /* We come here either from startup_32
-        * or directly from a 64bit bootloader.
-        * Since we may have come directly from a bootloader we
-        * reload the page tables here.
+       jmp secondary_startup_64
+ENTRY(secondary_startup_64)
+       /*
+        * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 1,
+        * and someone has loaded a mapped page table.
+        *
+        * %esi holds a physical pointer to real_mode_data.
+        *
+        * We come here either from startup_64 (using physical addresses)
+        * or from trampoline.S (using virtual addresses).
+        *
+        * Using virtual addresses from trampoline.S removes the need
+        * to have any identity mapped pages in the kernel page table
+        * after the boot processor executes this code.
         */
 
        /* Enable PAE mode and PGE */
@@ -113,9 +148,15 @@ startup_64:
        movq    %rax, %cr4
 
        /* Setup early boot stage 4 level pagetables. */
-       movq    $(boot_level4_pgt - __START_KERNEL_map), %rax
+       movq    $(init_level4_pgt - __START_KERNEL_map), %rax
+       addq    phys_base(%rip), %rax
        movq    %rax, %cr3
 
+       /* Ensure I am executing from virtual addresses */
+       movq    $1f, %rax
+       jmp     *%rax
+1:
+
        /* Check if nx is implemented */
        movl    $0x80000001, %eax
        cpuid
@@ -124,17 +165,11 @@ startup_64:
        /* Setup EFER (Extended Feature Enable Register) */
        movl    $MSR_EFER, %ecx
        rdmsr
-
-       /* Enable System Call */
-       btsl    $_EFER_SCE, %eax
-
-       /* No Execute supported? */
-       btl     $20,%edi
+       btsl    $_EFER_SCE, %eax        /* Enable System Call */
+       btl     $20,%edi                /* No Execute supported? */
        jnc     1f
        btsl    $_EFER_NX, %eax
-1:
-       /* Make changes effective */
-       wrmsr
+1:     wrmsr                           /* Make changes effective */
 
        /* Setup cr0 */
 #define CR0_PM                         1               /* protected mode */
@@ -161,7 +196,7 @@ startup_64:
         * addresses where we're currently running on. We have to do that here
         * because in 32bit we couldn't load a 64bit linear address.
         */
-       lgdt    cpu_gdt_descr
+       lgdt    cpu_gdt_descr(%rip)
 
        /* set up data segments. actually 0 would do too */
        movl $__KERNEL_DS,%eax
@@ -212,6 +247,9 @@ initial_code:
 init_rsp:
        .quad  init_thread_union+THREAD_SIZE-8
 
+bad_address:
+       jmp bad_address
+
 ENTRY(early_idt_handler)
        cmpl $2,early_recursion_flag(%rip)
        jz  1f
@@ -240,110 +278,66 @@ early_idt_msg:
 early_idt_ripmsg:
        .asciz "RIP %s\n"
 
-.code32
-ENTRY(no_long_mode)
-       /* This isn't an x86-64 CPU so hang */
-1:
-       jmp     1b
-
-.org 0xf00
-       .globl pGDT32
-pGDT32:
-       .word   gdt_end-cpu_gdt_table-1
-       .long   cpu_gdt_table-__START_KERNEL_map
-
-.org 0xf10     
-ljumpvector:
-       .long   startup_64-__START_KERNEL_map
-       .word   __KERNEL_CS
+.balign PAGE_SIZE
 
-ENTRY(stext)
-ENTRY(_stext)
-
-       $page = 0
 #define NEXT_PAGE(name) \
-       $page = $page + 1; \
-       .org $page * 0x1000; \
-       phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \
+       .balign PAGE_SIZE; \
 ENTRY(name)
 
+/* Automate the creation of 1 to 1 mapping pmd entries */
+#define PMDS(START, PERM, COUNT)               \
+       i = 0 ;                                 \
+       .rept (COUNT) ;                         \
+       .quad   (START) + (i << 21) + (PERM) ;  \
+       i = i + 1 ;                             \
+       .endr
+
+       /*
+        * This default setting generates an ident mapping at address 0x100000
+        * and a mapping for the kernel that precisely maps virtual address
+        * 0xffffffff80000000 to physical address 0x000000. (always using
+        * 2Mbyte large pages provided by PAE mode)
+        */
 NEXT_PAGE(init_level4_pgt)
-       /* This gets initialized in x86_64_start_kernel */
-       .fill   512,8,0
+       .quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+       .fill   257,8,0
+       .quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+       .fill   252,8,0
+       /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
+       .quad   level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
 
 NEXT_PAGE(level3_ident_pgt)
-       .quad   phys_level2_ident_pgt | 0x007
+       .quad   level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
        .fill   511,8,0
 
 NEXT_PAGE(level3_kernel_pgt)
        .fill   510,8,0
        /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
-       .quad   phys_level2_kernel_pgt | 0x007
+       .quad   level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
        .fill   1,8,0
 
 NEXT_PAGE(level2_ident_pgt)
-       /* 40MB for bootup.     */
-       i = 0
-       .rept 20
-       .quad   i << 21 | 0x083
-       i = i + 1
-       .endr
-       /* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */
-       .globl temp_boot_pmds
-temp_boot_pmds:
-       .fill   492,8,0
-       
+       /* Since I easily can, map the first 1G.
+        * Don't set NX because code runs from these pages.
+        */
+       PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD)
+
 NEXT_PAGE(level2_kernel_pgt)
        /* 40MB kernel mapping. The kernel code cannot be bigger than that.
           When you change this change KERNEL_TEXT_SIZE in page.h too. */
        /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */
-       i = 0
-       .rept 20
-       .quad   i << 21 | 0x183
-       i = i + 1
-       .endr
+       PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL,
+               KERNEL_TEXT_SIZE/PMD_SIZE)
        /* Module mapping starts here */
-       .fill   492,8,0
+       .fill   (PTRS_PER_PMD - (KERNEL_TEXT_SIZE/PMD_SIZE)),8,0
 
-NEXT_PAGE(level3_physmem_pgt)
-       .quad   phys_level2_kernel_pgt | 0x007  /* so that __va works even before pagetable_init */
-       .fill   511,8,0
+NEXT_PAGE(level2_spare_pgt)
+       .fill   512,8,0
 
+#undef PMDS
 #undef NEXT_PAGE
 
        .data
-
-#ifdef CONFIG_ACPI_SLEEP
-       .align PAGE_SIZE
-ENTRY(wakeup_level4_pgt)
-       .quad   phys_level3_ident_pgt | 0x007
-       .fill   255,8,0
-       .quad   phys_level3_physmem_pgt | 0x007
-       .fill   254,8,0
-       /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-       .quad   phys_level3_kernel_pgt | 0x007
-#endif
-
-#ifndef CONFIG_HOTPLUG_CPU
-       __INITDATA
-#endif
-       /*
-        * This default setting generates an ident mapping at address 0x100000
-        * and a mapping for the kernel that precisely maps virtual address
-        * 0xffffffff80000000 to physical address 0x000000. (always using
-        * 2Mbyte large pages provided by PAE mode)
-        */
-       .align PAGE_SIZE
-ENTRY(boot_level4_pgt)
-       .quad   phys_level3_ident_pgt | 0x007
-       .fill   255,8,0
-       .quad   phys_level3_physmem_pgt | 0x007
-       .fill   254,8,0
-       /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-       .quad   phys_level3_kernel_pgt | 0x007
-
-       .data
-
        .align 16
        .globl cpu_gdt_descr
 cpu_gdt_descr:
@@ -357,6 +351,10 @@ gdt:
        .endr
 #endif
 
+ENTRY(phys_base)
+       /* This must match the first entry in level2_kernel_pgt */
+       .quad   0x0000000000000000
+
 /* We need valid kernel segments for data and code in long mode too
  * IRET will check the segment types  kkeil 2000/10/28
  * Also sysret mandates a special GDT layout 
@@ -370,13 +368,13 @@ gdt:
        
 ENTRY(cpu_gdt_table)
        .quad   0x0000000000000000      /* NULL descriptor */
+       .quad   0x00cf9b000000ffff      /* __KERNEL32_CS */
+       .quad   0x00af9b000000ffff      /* __KERNEL_CS */
+       .quad   0x00cf93000000ffff      /* __KERNEL_DS */
+       .quad   0x00cffb000000ffff      /* __USER32_CS */
+       .quad   0x00cff3000000ffff      /* __USER_DS, __USER32_DS  */
+       .quad   0x00affb000000ffff      /* __USER_CS */
        .quad   0x0                     /* unused */
-       .quad   0x00af9a000000ffff      /* __KERNEL_CS */
-       .quad   0x00cf92000000ffff      /* __KERNEL_DS */
-       .quad   0x00cffa000000ffff      /* __USER32_CS */
-       .quad   0x00cff2000000ffff      /* __USER_DS, __USER32_DS  */           
-       .quad   0x00affa000000ffff      /* __USER_CS */
-       .quad   0x00cf9a000000ffff      /* __KERNEL32_CS */
        .quad   0,0                     /* TSS */
        .quad   0,0                     /* LDT */
        .quad   0,0,0                   /* three TLS descriptors */ 
index 5f197b0..213d90e 100644 (file)
 #include <asm/setup.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 #include <asm/sections.h>
 
+static void __init zap_identity_mappings(void)
+{
+       pgd_t *pgd = pgd_offset_k(0UL);
+       pgd_clear(pgd);
+       __flush_tlb();
+}
+
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
 static void __init clear_bss(void)
@@ -29,25 +37,24 @@ static void __init clear_bss(void)
 }
 
 #define NEW_CL_POINTER         0x228   /* Relative to real mode data */
-#define OLD_CL_MAGIC_ADDR      0x90020
+#define OLD_CL_MAGIC_ADDR      0x20
 #define OLD_CL_MAGIC            0xA33F
-#define OLD_CL_BASE_ADDR        0x90000
-#define OLD_CL_OFFSET           0x90022
+#define OLD_CL_OFFSET           0x22
 
 static void __init copy_bootdata(char *real_mode_data)
 {
-       int new_data;
+       unsigned long new_data;
        char * command_line;
 
        memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
-       new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
+       new_data = *(u32 *) (x86_boot_params + NEW_CL_POINTER);
        if (!new_data) {
-               if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
+               if (OLD_CL_MAGIC != *(u16 *)(real_mode_data + OLD_CL_MAGIC_ADDR)) {
                        return;
                }
-               new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
+               new_data = __pa(real_mode_data) + *(u16 *)(real_mode_data + OLD_CL_OFFSET);
        }
-       command_line = (char *) ((u64)(new_data));
+       command_line = __va(new_data);
        memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 }
 
@@ -55,26 +62,30 @@ void __init x86_64_start_kernel(char * real_mode_data)
 {
        int i;
 
+       /*
+        * Make sure kernel is aligned to 2MB address. Catching it at compile
+        * time is better. Change your config file and compile the kernel
+        * for a 2MB aligned address (CONFIG_PHYSICAL_START)
+        */
+       BUILD_BUG_ON(CONFIG_PHYSICAL_START & (__KERNEL_ALIGN - 1));
+
        /* clear bss before set_intr_gate with early_idt_handler */
        clear_bss();
 
+       /* Make NULL pointers segfault */
+       zap_identity_mappings();
+
        for (i = 0; i < IDT_ENTRIES; i++)
                set_intr_gate(i, early_idt_handler);
        asm volatile("lidt %0" :: "m" (idt_descr));
 
        early_printk("Kernel alive\n");
 
-       /*
-        * switch to init_level4_pgt from boot_level4_pgt
-        */
-       memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t));
-       asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));
-
        for (i = 0; i < NR_CPUS; i++)
                cpu_pda(i) = &boot_cpu_pda[i];
 
        pda_init(0);
-       copy_bootdata(real_mode_data);
+       copy_bootdata(__va(real_mode_data));
 #ifdef CONFIG_SMP
        cpu_set(0, cpu_online_map);
 #endif
index c6a5bc7..2a2df14 100644 (file)
@@ -907,10 +907,6 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
        enable_8259A_irq(0);
 }
 
-void __init UNEXPECTED_IO_APIC(void)
-{
-}
-
 void __apicdebuginit print_IO_APIC(void)
 {
        int apic, i;
@@ -946,40 +942,16 @@ void __apicdebuginit print_IO_APIC(void)
        printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
        printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
        printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
-       if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
-               UNEXPECTED_IO_APIC();
 
        printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
        printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
-       if (    (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
-               (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
-               (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
-               (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
-               (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
-               (reg_01.bits.entries != 0x2E) &&
-               (reg_01.bits.entries != 0x3F) &&
-               (reg_01.bits.entries != 0x03) 
-       )
-               UNEXPECTED_IO_APIC();
 
        printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
        printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
-       if (    (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
-               (reg_01.bits.version != 0x02) && /* 82801BA IO-APICs (ICH2) */
-               (reg_01.bits.version != 0x10) && /* oldest IO-APICs */
-               (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
-               (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
-               (reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
-       )
-               UNEXPECTED_IO_APIC();
-       if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
-               UNEXPECTED_IO_APIC();
 
        if (reg_01.bits.version >= 0x10) {
                printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
                printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
-               if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
-                       UNEXPECTED_IO_APIC();
        }
 
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
@@ -1407,8 +1379,7 @@ static void irq_complete_move(unsigned int irq)
 
        vector = ~get_irq_regs()->orig_rax;
        me = smp_processor_id();
-       if ((vector == cfg->vector) &&
-           cpu_isset(smp_processor_id(), cfg->domain)) {
+       if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
                cpumask_t cleanup_mask;
 
                cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
@@ -1983,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 745b1f0..387d347 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/thread_info.h>
+#include <linux/syscalls.h>
 
 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
 static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
index 0497e3b..a8bb33c 100644 (file)
@@ -191,19 +191,19 @@ NORET_TYPE void machine_kexec(struct kimage *image)
 
        page_list[PA_CONTROL_PAGE] = __pa(control_page);
        page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
-       page_list[PA_PGD] = __pa(kexec_pgd);
+       page_list[PA_PGD] = __pa_symbol(&kexec_pgd);
        page_list[VA_PGD] = (unsigned long)kexec_pgd;
-       page_list[PA_PUD_0] = __pa(kexec_pud0);
+       page_list[PA_PUD_0] = __pa_symbol(&kexec_pud0);
        page_list[VA_PUD_0] = (unsigned long)kexec_pud0;
-       page_list[PA_PMD_0] = __pa(kexec_pmd0);
+       page_list[PA_PMD_0] = __pa_symbol(&kexec_pmd0);
        page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
-       page_list[PA_PTE_0] = __pa(kexec_pte0);
+       page_list[PA_PTE_0] = __pa_symbol(&kexec_pte0);
        page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
-       page_list[PA_PUD_1] = __pa(kexec_pud1);
+       page_list[PA_PUD_1] = __pa_symbol(&kexec_pud1);
        page_list[VA_PUD_1] = (unsigned long)kexec_pud1;
-       page_list[PA_PMD_1] = __pa(kexec_pmd1);
+       page_list[PA_PMD_1] = __pa_symbol(&kexec_pmd1);
        page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
-       page_list[PA_PTE_1] = __pa(kexec_pte1);
+       page_list[PA_PTE_1] = __pa_symbol(&kexec_pte1);
        page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
 
        page_list[PA_TABLE_PAGE] =
index 8011a8e..fa26726 100644 (file)
@@ -323,10 +323,13 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status)
 #endif /* CONFIG_X86_MCE_INTEL */
 
 /*
- * Periodic polling timer for "silent" machine check errors.
+ * Periodic polling timer for "silent" machine check errors.  If the
+ * poller finds an MCE, poll 2x faster.  When the poller finds no more
+ * errors, poll 2x slower (up to check_interval seconds).
  */
 
 static int check_interval = 5 * 60; /* 5 minutes */
+static int next_interval; /* in jiffies */
 static void mcheck_timer(struct work_struct *work);
 static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer);
 
@@ -339,7 +342,6 @@ static void mcheck_check_cpu(void *info)
 static void mcheck_timer(struct work_struct *work)
 {
        on_each_cpu(mcheck_check_cpu, NULL, 1, 1);
-       schedule_delayed_work(&mcheck_work, check_interval * HZ);
 
        /*
         * It's ok to read stale data here for notify_user and
@@ -349,17 +351,30 @@ static void mcheck_timer(struct work_struct *work)
         * writes.
         */
        if (notify_user && console_logged) {
+               static unsigned long last_print;
+               unsigned long now = jiffies;
+
+               /* if we logged an MCE, reduce the polling interval */
+               next_interval = max(next_interval/2, HZ/100);
                notify_user = 0;
                clear_bit(0, &console_logged);
-               printk(KERN_INFO "Machine check events logged\n");
+               if (time_after_eq(now, last_print + (check_interval*HZ))) {
+                       last_print = now;
+                       printk(KERN_INFO "Machine check events logged\n");
+               }
+       } else {
+               next_interval = min(next_interval*2, check_interval*HZ);
        }
+
+       schedule_delayed_work(&mcheck_work, next_interval);
 }
 
 
 static __init int periodic_mcheck_init(void)
 { 
-       if (check_interval)
-               schedule_delayed_work(&mcheck_work, check_interval*HZ);
+       next_interval = check_interval * HZ;
+       if (next_interval)
+               schedule_delayed_work(&mcheck_work, next_interval);
        return 0;
 } 
 __initcall(periodic_mcheck_init);
@@ -597,12 +612,13 @@ static int mce_resume(struct sys_device *dev)
 /* Reinit MCEs after user configuration changes */
 static void mce_restart(void) 
 { 
-       if (check_interval)
+       if (next_interval)
                cancel_delayed_work(&mcheck_work);
        /* Timer race is harmless here */
        on_each_cpu(mce_init, NULL, 1, 1);       
-       if (check_interval)
-               schedule_delayed_work(&mcheck_work, check_interval*HZ);
+       next_interval = check_interval * HZ;
+       if (next_interval)
+               schedule_delayed_work(&mcheck_work, next_interval);
 }
 
 static struct sysdev_class mce_sysclass = {
index 455aa0b..d0dc489 100644 (file)
@@ -300,7 +300,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                        }
                }
        }
-       clustered_apic_check();
+       setup_apic_routing();
        if (!num_processors)
                printk(KERN_ERR "MPTABLE: no processors registered!\n");
        return num_processors;
index dfab9f1..6cd2b30 100644 (file)
 #include <asm/proto.h>
 #include <asm/kdebug.h>
 #include <asm/mce.h>
-#include <asm/intel_arch_perfmon.h>
 
 int unknown_nmi_panic;
 int nmi_watchdog_enabled;
 int panic_on_unrecovered_nmi;
 
-/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
- * evtsel_nmi_owner tracks the ownership of the event selection
- * - different performance counters/ event selection may be reserved for
- *   different subsystems this reservation system just tries to coordinate
- *   things a little
- */
-
-/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
- * offset from MSR_P4_BSU_ESCR0.  It will be the max for all platforms (for now)
- */
-#define NMI_MAX_COUNTER_BITS 66
-#define NMI_MAX_COUNTER_LONGS BITS_TO_LONGS(NMI_MAX_COUNTER_BITS)
-
-static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner[NMI_MAX_COUNTER_LONGS]);
-static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[NMI_MAX_COUNTER_LONGS]);
-
 static cpumask_t backtrace_mask = CPU_MASK_NONE;
 
 /* nmi_active:
@@ -63,191 +46,11 @@ int panic_on_timeout;
 unsigned int nmi_watchdog = NMI_DEFAULT;
 static unsigned int nmi_hz = HZ;
 
-struct nmi_watchdog_ctlblk {
-       int enabled;
-       u64 check_bit;
-       unsigned int cccr_msr;
-       unsigned int perfctr_msr;  /* the MSR to reset in NMI handler */
-       unsigned int evntsel_msr;  /* the MSR to select the events to handle */
-};
-static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
+static DEFINE_PER_CPU(short, wd_enabled);
 
 /* local prototypes */
 static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
 
-/* converts an msr to an appropriate reservation bit */
-static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
-{
-       /* returns the bit offset of the performance counter register */
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               return (msr - MSR_K7_PERFCTR0);
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-                       return (msr - MSR_ARCH_PERFMON_PERFCTR0);
-               else
-                       return (msr - MSR_P4_BPU_PERFCTR0);
-       }
-       return 0;
-}
-
-/* converts an msr to an appropriate reservation bit */
-static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
-{
-       /* returns the bit offset of the event selection register */
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               return (msr - MSR_K7_EVNTSEL0);
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-                       return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
-               else
-                       return (msr - MSR_P4_BSU_ESCR0);
-       }
-       return 0;
-}
-
-/* checks for a bit availability (hack for oprofile) */
-int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
-{
-       int cpu;
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-       for_each_possible_cpu (cpu) {
-               if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)))
-                       return 0;
-       }
-       return 1;
-}
-
-/* checks the an msr for availability */
-int avail_to_resrv_perfctr_nmi(unsigned int msr)
-{
-       unsigned int counter;
-       int cpu;
-
-       counter = nmi_perfctr_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       for_each_possible_cpu (cpu) {
-               if (test_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)))
-                       return 0;
-       }
-       return 1;
-}
-
-static int __reserve_perfctr_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_perfctr_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       if (!test_and_set_bit(counter, &per_cpu(perfctr_nmi_owner, cpu)))
-               return 1;
-       return 0;
-}
-
-static void __release_perfctr_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_perfctr_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       clear_bit(counter, &per_cpu(perfctr_nmi_owner, cpu));
-}
-
-int reserve_perfctr_nmi(unsigned int msr)
-{
-       int cpu, i;
-       for_each_possible_cpu (cpu) {
-               if (!__reserve_perfctr_nmi(cpu, msr)) {
-                       for_each_possible_cpu (i) {
-                               if (i >= cpu)
-                                       break;
-                               __release_perfctr_nmi(i, msr);
-                       }
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-void release_perfctr_nmi(unsigned int msr)
-{
-       int cpu;
-       for_each_possible_cpu (cpu)
-               __release_perfctr_nmi(cpu, msr);
-}
-
-int __reserve_evntsel_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_evntsel_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       if (!test_and_set_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]))
-               return 1;
-       return 0;
-}
-
-static void __release_evntsel_nmi(int cpu, unsigned int msr)
-{
-       unsigned int counter;
-       if (cpu < 0)
-               cpu = smp_processor_id();
-
-       counter = nmi_evntsel_msr_to_bit(msr);
-       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
-
-       clear_bit(counter, &per_cpu(evntsel_nmi_owner, cpu)[0]);
-}
-
-int reserve_evntsel_nmi(unsigned int msr)
-{
-       int cpu, i;
-       for_each_possible_cpu (cpu) {
-               if (!__reserve_evntsel_nmi(cpu, msr)) {
-                       for_each_possible_cpu (i) {
-                               if (i >= cpu)
-                                       break;
-                               __release_evntsel_nmi(i, msr);
-                       }
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-void release_evntsel_nmi(unsigned int msr)
-{
-       int cpu;
-       for_each_possible_cpu (cpu) {
-               __release_evntsel_nmi(cpu, msr);
-       }
-}
-
-static __cpuinit inline int nmi_known_cpu(void)
-{
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               return boot_cpu_data.x86 == 15 || boot_cpu_data.x86 == 16;
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-                       return 1;
-               else
-                       return (boot_cpu_data.x86 == 15);
-       }
-       return 0;
-}
-
 /* Run after command line and cpu_init init, but before all other checks */
 void nmi_watchdog_default(void)
 {
@@ -277,23 +80,6 @@ static __init void nmi_cpu_busy(void *data)
 }
 #endif
 
-static unsigned int adjust_for_32bit_ctr(unsigned int hz)
-{
-       unsigned int retval = hz;
-
-       /*
-        * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
-        * are writable, with higher bits sign extending from bit 31.
-        * So, we can only program the counter with 31 bit values and
-        * 32nd bit should be 1, for 33.. to be 1.
-        * Find the appropriate nmi_hz
-        */
-       if ((((u64)cpu_khz * 1000) / retval) > 0x7fffffffULL) {
-               retval = ((u64)cpu_khz * 1000) / 0x7fffffffUL + 1;
-       }
-       return retval;
-}
-
 int __init check_nmi_watchdog (void)
 {
        int *counts;
@@ -322,14 +108,14 @@ int __init check_nmi_watchdog (void)
        mdelay((20*1000)/nmi_hz); // wait 20 ticks
 
        for_each_online_cpu(cpu) {
-               if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
+               if (!per_cpu(wd_enabled, cpu))
                        continue;
                if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) {
                        printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
                               cpu,
                               counts[cpu],
                               cpu_pda(cpu)->__nmi_count);
-                       per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
+                       per_cpu(wd_enabled, cpu) = 0;
                        atomic_dec(&nmi_active);
                }
        }
@@ -344,13 +130,8 @@ int __init check_nmi_watchdog (void)
 
        /* now that we know it works we can reduce NMI frequency to
           something more reasonable; makes a difference in some configs */
-       if (nmi_watchdog == NMI_LOCAL_APIC) {
-               struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-               nmi_hz = 1;
-               if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0)
-                       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-       }
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               nmi_hz = lapic_adjust_nmi_hz(1);
 
        kfree(counts);
        return 0;
@@ -379,57 +160,6 @@ int __init setup_nmi_watchdog(char *str)
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-static void disable_lapic_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-
-       if (atomic_read(&nmi_active) <= 0)
-               return;
-
-       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
-
-       BUG_ON(atomic_read(&nmi_active) != 0);
-}
-
-static void enable_lapic_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-
-       /* are we already enabled */
-       if (atomic_read(&nmi_active) != 0)
-               return;
-
-       /* are we lapic aware */
-       if (nmi_known_cpu() <= 0)
-               return;
-
-       on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
-       touch_nmi_watchdog();
-}
-
-void disable_timer_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_IO_APIC);
-
-       if (atomic_read(&nmi_active) <= 0)
-               return;
-
-       disable_irq(0);
-       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
-
-       BUG_ON(atomic_read(&nmi_active) != 0);
-}
-
-void enable_timer_nmi_watchdog(void)
-{
-       BUG_ON(nmi_watchdog != NMI_IO_APIC);
-
-       if (atomic_read(&nmi_active) == 0) {
-               touch_nmi_watchdog();
-               on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
-               enable_irq(0);
-       }
-}
 
 static void __acpi_nmi_disable(void *__unused)
 {
@@ -515,275 +245,9 @@ late_initcall(init_lapic_nmi_sysfs);
 
 #endif /* CONFIG_PM */
 
-/*
- * Activate the NMI watchdog via the local APIC.
- * Original code written by Keith Owens.
- */
-
-/* Note that these events don't tick when the CPU idles. This means
-   the frequency varies with CPU load. */
-
-#define K7_EVNTSEL_ENABLE      (1 << 22)
-#define K7_EVNTSEL_INT         (1 << 20)
-#define K7_EVNTSEL_OS          (1 << 17)
-#define K7_EVNTSEL_USR         (1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
-#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-
-static int setup_k7_watchdog(void)
-{
-       unsigned int perfctr_msr, evntsel_msr;
-       unsigned int evntsel;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       perfctr_msr = MSR_K7_PERFCTR0;
-       evntsel_msr = MSR_K7_EVNTSEL0;
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       /* Simulator may not support it */
-       if (checking_wrmsrl(evntsel_msr, 0UL))
-               goto fail2;
-       wrmsrl(perfctr_msr, 0UL);
-
-       evntsel = K7_EVNTSEL_INT
-               | K7_EVNTSEL_OS
-               | K7_EVNTSEL_USR
-               | K7_NMI_EVENT;
-
-       /* setup the timer */
-       wrmsr(evntsel_msr, evntsel, 0);
-       wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       evntsel |= K7_EVNTSEL_ENABLE;
-       wrmsr(evntsel_msr, evntsel, 0);
-
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = 0;  //unused
-       wd->check_bit = 1ULL<<63;
-       return 1;
-fail2:
-       __release_evntsel_nmi(-1, evntsel_msr);
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
-}
-
-static void stop_k7_watchdog(void)
-{
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       wrmsr(wd->evntsel_msr, 0, 0);
-
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
-}
-
-/* Note that these events don't tick when the CPU idles. This means
-   the frequency varies with CPU load. */
-
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
-#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
-#define P4_ESCR_OS             (1<<3)
-#define P4_ESCR_USR            (1<<2)
-#define P4_CCCR_OVF_PMI0       (1<<26)
-#define P4_CCCR_OVF_PMI1       (1<<27)
-#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
-#define P4_CCCR_COMPLEMENT     (1<<19)
-#define P4_CCCR_COMPARE                (1<<18)
-#define P4_CCCR_REQUIRED       (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE         (1<<12)
-#define P4_CCCR_OVF            (1<<31)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
-   CRU_ESCR0 (with any non-null event selector) through a complemented
-   max threshold. [IA32-Vol3, Section 14.9.9] */
-
-static int setup_p4_watchdog(void)
-{
-       unsigned int perfctr_msr, evntsel_msr, cccr_msr;
-       unsigned int evntsel, cccr_val;
-       unsigned int misc_enable, dummy;
-       unsigned int ht_num;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
-       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
-               return 0;
-
-#ifdef CONFIG_SMP
-       /* detect which hyperthread we are on */
-       if (smp_num_siblings == 2) {
-               unsigned int ebx, apicid;
-
-               ebx = cpuid_ebx(1);
-               apicid = (ebx >> 24) & 0xff;
-               ht_num = apicid & 1;
-       } else
-#endif
-               ht_num = 0;
-
-       /* performance counters are shared resources
-        * assign each hyperthread its own set
-        * (re-use the ESCR0 register, seems safe
-        * and keeps the cccr_val the same)
-        */
-       if (!ht_num) {
-               /* logical cpu 0 */
-               perfctr_msr = MSR_P4_IQ_PERFCTR0;
-               evntsel_msr = MSR_P4_CRU_ESCR0;
-               cccr_msr = MSR_P4_IQ_CCCR0;
-               cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
-       } else {
-               /* logical cpu 1 */
-               perfctr_msr = MSR_P4_IQ_PERFCTR1;
-               evntsel_msr = MSR_P4_CRU_ESCR0;
-               cccr_msr = MSR_P4_IQ_CCCR1;
-               cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
-       }
-
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       evntsel = P4_ESCR_EVENT_SELECT(0x3F)
-               | P4_ESCR_OS
-               | P4_ESCR_USR;
-
-       cccr_val |= P4_CCCR_THRESHOLD(15)
-                | P4_CCCR_COMPLEMENT
-                | P4_CCCR_COMPARE
-                | P4_CCCR_REQUIRED;
-
-       wrmsr(evntsel_msr, evntsel, 0);
-       wrmsr(cccr_msr, cccr_val, 0);
-       wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       cccr_val |= P4_CCCR_ENABLE;
-       wrmsr(cccr_msr, cccr_val, 0);
-
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = cccr_msr;
-       wd->check_bit = 1ULL<<39;
-       return 1;
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
-}
-
-static void stop_p4_watchdog(void)
-{
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       wrmsr(wd->cccr_msr, 0, 0);
-       wrmsr(wd->evntsel_msr, 0, 0);
-
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
-}
-
-#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
-
-static int setup_intel_arch_watchdog(void)
-{
-       unsigned int ebx;
-       union cpuid10_eax eax;
-       unsigned int unused;
-       unsigned int perfctr_msr, evntsel_msr;
-       unsigned int evntsel;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebx indicates event present.
-        */
-       cpuid(10, &(eax.full), &ebx, &unused, &unused);
-       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
-           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               goto fail;
-
-       perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
-       evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
-
-       if (!__reserve_perfctr_nmi(-1, perfctr_msr))
-               goto fail;
-
-       if (!__reserve_evntsel_nmi(-1, evntsel_msr))
-               goto fail1;
-
-       wrmsrl(perfctr_msr, 0UL);
-
-       evntsel = ARCH_PERFMON_EVENTSEL_INT
-               | ARCH_PERFMON_EVENTSEL_OS
-               | ARCH_PERFMON_EVENTSEL_USR
-               | ARCH_PERFMON_NMI_EVENT_SEL
-               | ARCH_PERFMON_NMI_EVENT_UMASK;
-
-       /* setup the timer */
-       wrmsr(evntsel_msr, evntsel, 0);
-
-       nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-       wrmsr(perfctr_msr, (u32)(-((u64)cpu_khz * 1000 / nmi_hz)), 0);
-
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
-       wrmsr(evntsel_msr, evntsel, 0);
-
-       wd->perfctr_msr = perfctr_msr;
-       wd->evntsel_msr = evntsel_msr;
-       wd->cccr_msr = 0;  //unused
-       wd->check_bit = 1ULL << (eax.split.bit_width - 1);
-       return 1;
-fail1:
-       __release_perfctr_nmi(-1, perfctr_msr);
-fail:
-       return 0;
-}
-
-static void stop_intel_arch_watchdog(void)
-{
-       unsigned int ebx;
-       union cpuid10_eax eax;
-       unsigned int unused;
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebx indicates event present.
-        */
-       cpuid(10, &(eax.full), &ebx, &unused, &unused);
-       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
-           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               return;
-
-       wrmsr(wd->evntsel_msr, 0, 0);
-
-       __release_evntsel_nmi(-1, wd->evntsel_msr);
-       __release_perfctr_nmi(-1, wd->perfctr_msr);
-}
-
 void setup_apic_nmi_watchdog(void *unused)
 {
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-       /* only support LOCAL and IO APICs for now */
-       if ((nmi_watchdog != NMI_LOCAL_APIC) &&
-           (nmi_watchdog != NMI_IO_APIC))
-               return;
-
-       if (wd->enabled == 1)
+       if (__get_cpu_var(wd_enabled) == 1)
                return;
 
        /* cheap hack to support suspend/resume */
@@ -791,62 +255,31 @@ void setup_apic_nmi_watchdog(void *unused)
        if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0))
                return;
 
-       if (nmi_watchdog == NMI_LOCAL_APIC) {
-               switch (boot_cpu_data.x86_vendor) {
-               case X86_VENDOR_AMD:
-                       if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
-                               return;
-                       if (!setup_k7_watchdog())
-                               return;
-                       break;
-               case X86_VENDOR_INTEL:
-                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                               if (!setup_intel_arch_watchdog())
-                                       return;
-                               break;
-                       }
-                       if (!setup_p4_watchdog())
-                               return;
-                       break;
-               default:
+       switch (nmi_watchdog) {
+       case NMI_LOCAL_APIC:
+               __get_cpu_var(wd_enabled) = 1;
+               if (lapic_watchdog_init(nmi_hz) < 0) {
+                       __get_cpu_var(wd_enabled) = 0;
                        return;
                }
+               /* FALL THROUGH */
+       case NMI_IO_APIC:
+               __get_cpu_var(wd_enabled) = 1;
+               atomic_inc(&nmi_active);
        }
-       wd->enabled = 1;
-       atomic_inc(&nmi_active);
 }
 
 void stop_apic_nmi_watchdog(void *unused)
 {
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
        /* only support LOCAL and IO APICs for now */
        if ((nmi_watchdog != NMI_LOCAL_APIC) &&
            (nmi_watchdog != NMI_IO_APIC))
                return;
-
-       if (wd->enabled == 0)
+       if (__get_cpu_var(wd_enabled) == 0)
                return;
-
-       if (nmi_watchdog == NMI_LOCAL_APIC) {
-               switch (boot_cpu_data.x86_vendor) {
-               case X86_VENDOR_AMD:
-                       if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
-                               return;
-                       stop_k7_watchdog();
-                       break;
-               case X86_VENDOR_INTEL:
-                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                               stop_intel_arch_watchdog();
-                               break;
-                       }
-                       stop_p4_watchdog();
-                       break;
-               default:
-                       return;
-               }
-       }
-       wd->enabled = 0;
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               lapic_watchdog_stop();
+       __get_cpu_var(wd_enabled) = 0;
        atomic_dec(&nmi_active);
 }
 
@@ -885,9 +318,7 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
        int sum;
        int touched = 0;
        int cpu = smp_processor_id();
-       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-       u64 dummy;
-       int rc=0;
+       int rc = 0;
 
        /* check for other users first */
        if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
@@ -934,55 +365,20 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
        }
 
        /* see if the nmi watchdog went off */
-       if (wd->enabled) {
-               if (nmi_watchdog == NMI_LOCAL_APIC) {
-                       rdmsrl(wd->perfctr_msr, dummy);
-                       if (dummy & wd->check_bit){
-                               /* this wasn't a watchdog timer interrupt */
-                               goto done;
-                       }
-
-                       /* only Intel uses the cccr msr */
-                       if (wd->cccr_msr != 0) {
-                               /*
-                                * P4 quirks:
-                                * - An overflown perfctr will assert its interrupt
-                                *   until the OVF flag in its CCCR is cleared.
-                                * - LVTPC is masked on interrupt and must be
-                                *   unmasked by the LVTPC handler.
-                                */
-                               rdmsrl(wd->cccr_msr, dummy);
-                               dummy &= ~P4_CCCR_OVF;
-                               wrmsrl(wd->cccr_msr, dummy);
-                               apic_write(APIC_LVTPC, APIC_DM_NMI);
-                               /* start the cycle over again */
-                               wrmsrl(wd->perfctr_msr,
-                                      -((u64)cpu_khz * 1000 / nmi_hz));
-                       } else if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-                               /*
-                                * ArchPerfom/Core Duo needs to re-unmask
-                                * the apic vector
-                                */
-                               apic_write(APIC_LVTPC, APIC_DM_NMI);
-                               /* ARCH_PERFMON has 32 bit counter writes */
-                               wrmsr(wd->perfctr_msr,
-                                    (u32)(-((u64)cpu_khz * 1000 / nmi_hz)), 0);
-                       } else {
-                               /* start the cycle over again */
-                               wrmsrl(wd->perfctr_msr,
-                                      -((u64)cpu_khz * 1000 / nmi_hz));
-                       }
-                       rc = 1;
-               } else  if (nmi_watchdog == NMI_IO_APIC) {
-                       /* don't know how to accurately check for this.
-                        * just assume it was a watchdog timer interrupt
-                        * This matches the old behaviour.
-                        */
-                       rc = 1;
-               } else
-                       printk(KERN_WARNING "Unknown enabled NMI hardware?!\n");
+       if (!__get_cpu_var(wd_enabled))
+               return rc;
+       switch (nmi_watchdog) {
+       case NMI_LOCAL_APIC:
+               rc |= lapic_wd_event(nmi_hz);
+               break;
+       case NMI_IO_APIC:
+               /* don't know how to accurately check for this.
+                * just assume it was a watchdog timer interrupt
+                * This matches the old behaviour.
+                */
+               rc = 1;
+               break;
        }
-done:
        return rc;
 }
 
@@ -1067,12 +463,4 @@ void __trigger_all_cpu_backtrace(void)
 
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
-EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
-EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
-EXPORT_SYMBOL(reserve_perfctr_nmi);
-EXPORT_SYMBOL(release_perfctr_nmi);
-EXPORT_SYMBOL(reserve_evntsel_nmi);
-EXPORT_SYMBOL(release_evntsel_nmi);
-EXPORT_SYMBOL(disable_timer_nmi_watchdog);
-EXPORT_SYMBOL(enable_timer_nmi_watchdog);
 EXPORT_SYMBOL(touch_nmi_watchdog);
index 04480c3..5bd20b5 100644 (file)
@@ -507,7 +507,7 @@ error:
        return ret;
 }
 
-static struct dma_mapping_ops calgary_dma_ops = {
+static const struct dma_mapping_ops calgary_dma_ops = {
        .alloc_coherent = calgary_alloc_coherent,
        .map_single = calgary_map_single,
        .unmap_single = calgary_unmap_single,
index 0bae862..0a762e1 100644 (file)
@@ -556,7 +556,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
 
 extern int agp_amd64_init(void);
 
-static struct dma_mapping_ops gart_dma_ops = {
+static const struct dma_mapping_ops gart_dma_ops = {
        .mapping_error = NULL,
        .map_single = gart_map_single,
        .map_simple = gart_map_simple,
index df09ab0..6dade0c 100644 (file)
@@ -79,7 +79,7 @@ void nommu_unmap_sg(struct device *dev, struct scatterlist *sg,
 {
 }
 
-struct dma_mapping_ops nommu_dma_ops = {
+const struct dma_mapping_ops nommu_dma_ops = {
        .map_single = nommu_map_single,
        .unmap_single = nommu_unmap_single,
        .map_sg = nommu_map_sg,
index eb18be5..4b4569a 100644 (file)
@@ -12,7 +12,7 @@
 int swiotlb __read_mostly;
 EXPORT_SYMBOL(swiotlb);
 
-struct dma_mapping_ops swiotlb_dma_ops = {
+const struct dma_mapping_ops swiotlb_dma_ops = {
        .mapping_error = swiotlb_dma_mapping_error,
        .alloc_coherent = swiotlb_alloc_coherent,
        .free_coherent = swiotlb_free_coherent,
index d8d5ccc..4f21765 100644 (file)
@@ -288,16 +288,18 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 
 static int __init idle_setup (char *str)
 {
-       if (!strncmp(str, "poll", 4)) {
+       if (!strcmp(str, "poll")) {
                printk("using polling idle threads.\n");
                pm_idle = poll_idle;
-       }
+       } else if (!strcmp(str, "mwait"))
+               force_mwait = 1;
+       else
+               return -1;
 
        boot_option_idle_override = 1;
-       return 1;
+       return 0;
 }
-
-__setup("idle=", idle_setup);
+early_param("idle", idle_setup);
 
 /* Prints also some state that isn't saved in the pt_regs */ 
 void __show_regs(struct pt_regs * regs)
index 3d98b69..db30b5b 100644 (file)
@@ -79,6 +79,8 @@ int bootloader_type;
 
 unsigned long saved_video_mode;
 
+int force_mwait __cpuinitdata;
+
 /* 
  * Early DMI memory
  */
@@ -205,10 +207,10 @@ static void discover_ebda(void)
         * there is a real-mode segmented pointer pointing to the 
         * 4K EBDA area at 0x40E
         */
-       ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
+       ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
        ebda_addr <<= 4;
 
-       ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
+       ebda_size = *(unsigned short *)__va(ebda_addr);
 
        /* Round EBDA up to pages */
        if (ebda_size == 0)
@@ -243,11 +245,12 @@ void __init setup_arch(char **cmdline_p)
        init_mm.end_code = (unsigned long) &_etext;
        init_mm.end_data = (unsigned long) &_edata;
        init_mm.brk = (unsigned long) &_end;
+       init_mm.pgd = __va(__pa_symbol(&init_level4_pgt));
 
-       code_resource.start = virt_to_phys(&_text);
-       code_resource.end = virt_to_phys(&_etext)-1;
-       data_resource.start = virt_to_phys(&_etext);
-       data_resource.end = virt_to_phys(&_edata)-1;
+       code_resource.start = __pa_symbol(&_text);
+       code_resource.end = __pa_symbol(&_etext)-1;
+       data_resource.start = __pa_symbol(&_etext);
+       data_resource.end = __pa_symbol(&_edata)-1;
 
        early_identify_cpu(&boot_cpu_data);
 
@@ -274,8 +277,6 @@ void __init setup_arch(char **cmdline_p)
 
        dmi_scan_machine();
 
-       zap_low_mappings(0);
-
 #ifdef CONFIG_ACPI
        /*
         * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
@@ -329,15 +330,8 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
 #ifdef CONFIG_SMP
-       /*
-        * But first pinch a few for the stack/trampoline stuff
-        * FIXME: Don't need the extra page at 4K, but need to fix
-        * trampoline before removing it. (see the GDT stuff)
-        */
-       reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);
-
        /* Reserve SMP trampoline */
-       reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);
+       reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
 #endif
 
 #ifdef CONFIG_ACPI_SLEEP
@@ -612,6 +606,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 
        /* RDTSC can be speculated around */
        clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+
+       /* Family 10 doesn't support C states in MWAIT so don't use it */
+       if (c->x86 == 0x10 && !force_mwait)
+               clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
 }
 
 static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -987,9 +985,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "stc",
                "100mhzsteps",
                "hwpstate",
-               NULL,   /* tsc invariant mapped to constant_tsc */
-               NULL,
-               /* nothing */   /* constant_tsc - moved to flags */
+               "",     /* tsc invariant mapped to constant_tsc */
+               /* nothing */
        };
 
 
index 6a70b55..64379a8 100644 (file)
@@ -103,9 +103,9 @@ void __init setup_per_cpu_areas(void)
                if (!NODE_DATA(cpu_to_node(i))) {
                        printk("cpu with no node %d, num_online_nodes %d\n",
                               i, num_online_nodes());
-                       ptr = alloc_bootmem(size);
+                       ptr = alloc_bootmem_pages(size);
                } else { 
-                       ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
+                       ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size);
                }
                if (!ptr)
                        panic("Cannot allocate cpu data for CPU %d\n", i);
@@ -201,7 +201,6 @@ void __cpuinit cpu_init (void)
        /* CPU 0 is initialised in head64.c */
        if (cpu != 0) {
                pda_init(cpu);
-               zap_low_mappings(cpu);
        } else 
                estacks = boot_exception_stacks; 
 
index 49ec324..c819625 100644 (file)
@@ -141,7 +141,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
 #ifdef DEBUG_SIG
-       printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs.rip,regs.rsp,frame,eax);
+       printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs->rip,regs->rsp,frame,eax);
 #endif
 
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->rsp) == -EFAULT)
@@ -301,7 +301,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (test_thread_flag(TIF_SINGLESTEP))
                ptrace_notify(SIGTRAP);
 #ifdef DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+       printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%p\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
@@ -463,7 +463,7 @@ void
 do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 {
 #ifdef DEBUG_SIG
-       printk("do_notify_resume flags:%x rip:%lx rsp:%lx caller:%lx pending:%lx\n",
+       printk("do_notify_resume flags:%x rip:%lx rsp:%lx caller:%p pending:%x\n",
               thread_info_flags, regs->rip, regs->rsp, __builtin_return_address(0),signal_pending(current)); 
 #endif
               
index af1ec4d..22abae4 100644 (file)
@@ -76,7 +76,7 @@ static inline void leave_mm(int cpu)
        if (read_pda(mmu_state) == TLBSTATE_OK)
                BUG();
        cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
-       load_cr3(swapper_pg_dir);
+       load_cr3(init_mm.pgd);
 }
 
 /*
@@ -452,42 +452,34 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
 }
 EXPORT_SYMBOL(smp_call_function);
 
-void smp_stop_cpu(void)
+static void stop_this_cpu(void *dummy)
 {
-       unsigned long flags;
+       local_irq_disable();
        /*
         * Remove this CPU:
         */
        cpu_clear(smp_processor_id(), cpu_online_map);
-       local_irq_save(flags);
        disable_local_APIC();
-       local_irq_restore(flags);
-}
-
-static void smp_really_stop_cpu(void *dummy)
-{
-       smp_stop_cpu(); 
        for (;;) 
                halt();
 } 
 
 void smp_send_stop(void)
 {
-       int nolock = 0;
+       int nolock;
+       unsigned long flags;
+
        if (reboot_force)
                return;
+
        /* Don't deadlock on the call lock in panic */
-       if (!spin_trylock(&call_lock)) {
-               /* ignore locking because we have panicked anyways */
-               nolock = 1;
-       }
-       __smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
+       nolock = !spin_trylock(&call_lock);
+       local_irq_save(flags);
+       __smp_call_function(stop_this_cpu, NULL, 0, 0);
        if (!nolock)
                spin_unlock(&call_lock);
-
-       local_irq_disable();
        disable_local_APIC();
-       local_irq_enable();
+       local_irq_restore(flags);
 }
 
 /*
index cd4643a..4d9dacf 100644 (file)
@@ -60,7 +60,6 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/numa.h>
-#include <asm/genapic.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -68,7 +67,6 @@ EXPORT_SYMBOL(smp_num_siblings);
 
 /* Last level cache ID of each logical CPU */
 u8 cpu_llc_id[NR_CPUS] __cpuinitdata  = {[0 ... NR_CPUS-1] = BAD_APICID};
-EXPORT_SYMBOL(cpu_llc_id);
 
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map __read_mostly;
@@ -392,7 +390,8 @@ static void inquire_remote_apic(int apicid)
 {
        unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
        char *names[] = { "ID", "VERSION", "SPIV" };
-       int timeout, status;
+       int timeout;
+       unsigned int status;
 
        printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
 
@@ -402,7 +401,9 @@ static void inquire_remote_apic(int apicid)
                /*
                 * Wait for idle.
                 */
-               apic_wait_icr_idle();
+               status = safe_apic_wait_icr_idle();
+               if (status)
+                       printk("a previous APIC delivery may have failed\n");
 
                apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
                apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
@@ -430,8 +431,8 @@ static void inquire_remote_apic(int apicid)
  */
 static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int start_rip)
 {
-       unsigned long send_status = 0, accept_status = 0;
-       int maxlvt, timeout, num_starts, j;
+       unsigned long send_status, accept_status = 0;
+       int maxlvt, num_starts, j;
 
        Dprintk("Asserting INIT.\n");
 
@@ -447,12 +448,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
                                | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        mdelay(10);
 
@@ -465,12 +461,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
-       timeout = 0;
-       do {
-               Dprintk("+");
-               udelay(100);
-               send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-       } while (send_status && (timeout++ < 1000));
+       send_status = safe_apic_wait_icr_idle();
 
        mb();
        atomic_set(&init_deasserted, 1);
@@ -509,12 +500,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
                Dprintk("Startup point 1.\n");
 
                Dprintk("Waiting for send to finish...\n");
-               timeout = 0;
-               do {
-                       Dprintk("+");
-                       udelay(100);
-                       send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
-               } while (send_status && (timeout++ < 1000));
+               send_status = safe_apic_wait_icr_idle();
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -945,6 +931,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
                return -ENOSYS;
        }
 
+       /*
+        * Save current MTRR state in case it was changed since early boot
+        * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+        */
+       mtrr_save_state();
+
        per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
        /* Boot it! */
        err = do_boot_cpu(cpu, apicid);
@@ -965,13 +957,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
 
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
-
-       if (num_online_cpus() > 8 && genapic == &apic_flat) {
-               printk(KERN_WARNING
-                      "flat APIC routing can't be used with > 8 cpus\n");
-               BUG();
-       }
-
        err = 0;
 
        return err;
index 91f7e67..6a5a98f 100644 (file)
 #include <asm/proto.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/mtrr.h>
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
 
 struct saved_context saved_context;
 
@@ -33,7 +37,6 @@ void __save_processor_state(struct saved_context *ctxt)
        asm volatile ("str %0"  : "=m" (ctxt->tr));
 
        /* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
-       /* EFER should be constant for kernel version, no need to handle it. */
        /*
         * segment registers
         */
@@ -46,10 +49,12 @@ void __save_processor_state(struct saved_context *ctxt)
        rdmsrl(MSR_FS_BASE, ctxt->fs_base);
        rdmsrl(MSR_GS_BASE, ctxt->gs_base);
        rdmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
+       mtrr_save_fixed_ranges(NULL);
 
        /*
         * control registers 
         */
+       rdmsrl(MSR_EFER, ctxt->efer);
        asm volatile ("movq %%cr0, %0" : "=r" (ctxt->cr0));
        asm volatile ("movq %%cr2, %0" : "=r" (ctxt->cr2));
        asm volatile ("movq %%cr3, %0" : "=r" (ctxt->cr3));
@@ -75,6 +80,7 @@ void __restore_processor_state(struct saved_context *ctxt)
        /*
         * control registers
         */
+       wrmsrl(MSR_EFER, ctxt->efer);
        asm volatile ("movq %0, %%cr8" :: "r" (ctxt->cr8));
        asm volatile ("movq %0, %%cr4" :: "r" (ctxt->cr4));
        asm volatile ("movq %0, %%cr3" :: "r" (ctxt->cr3));
@@ -219,4 +225,15 @@ int swsusp_arch_resume(void)
        restore_image();
        return 0;
 }
+
+/*
+ *     pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+       unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
+       unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
+       return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
 #endif /* CONFIG_SOFTWARE_SUSPEND */
index bfbe007..16d183f 100644 (file)
@@ -71,9 +71,10 @@ loop:
        jmp     loop
 done:
        /* go back to the original page tables */
-       leaq    init_level4_pgt(%rip), %rax
-       subq    $__START_KERNEL_map, %rax
-       movq    %rax, %cr3
+       movq    $(init_level4_pgt - __START_KERNEL_map), %rax
+       addq    phys_base(%rip), %rax
+       movq    %rax, %cr3
+
        /* Flush TLB, including "global" things (vmalloc) */
        movq    mmu_cr4_features(%rip), %rax
        movq    %rax, %rdx
index 213fd6a..63d592c 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/linkage.h>
 #include <linux/sys.h>
 #include <linux/cache.h>
+#include <asm/asm-offsets.h>
 
 #define __NO_STUBS
 
index 75d73a9..0652e17 100644 (file)
 #include <asm/proto.h>
 #include <asm/hpet.h>
 #include <asm/sections.h>
-#include <linux/cpufreq.h>
 #include <linux/hpet.h>
 #include <asm/apic.h>
 #include <asm/hpet.h>
-
-extern void i8254_timer_resume(void);
-extern int using_apic_timer;
+#include <asm/mpspec.h>
+#include <asm/nmi.h>
 
 static char *timename = NULL;
 
@@ -252,6 +250,51 @@ static unsigned long get_cmos_time(void)
        return mktime(year, mon, day, hour, min, sec);
 }
 
+/* calibrate_cpu is used on systems with fixed rate TSCs to determine
+ * processor frequency */
+#define TICK_COUNT 100000000
+static unsigned int __init tsc_calibrate_cpu_khz(void)
+{
+       int tsc_start, tsc_now;
+       int i, no_ctr_free;
+       unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
+       unsigned long flags;
+
+       for (i = 0; i < 4; i++)
+               if (avail_to_resrv_perfctr_nmi_bit(i))
+                       break;
+       no_ctr_free = (i == 4);
+       if (no_ctr_free) {
+               i = 3;
+               rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
+               wrmsrl(MSR_K7_EVNTSEL3, 0);
+               rdmsrl(MSR_K7_PERFCTR3, pmc3);
+       } else {
+               reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+               reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+       }
+       local_irq_save(flags);
+       /* start meauring cycles, incrementing from 0 */
+       wrmsrl(MSR_K7_PERFCTR0 + i, 0);
+       wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
+       rdtscl(tsc_start);
+       do {
+               rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
+               tsc_now = get_cycles_sync();
+       } while ((tsc_now - tsc_start) < TICK_COUNT);
+
+       local_irq_restore(flags);
+       if (no_ctr_free) {
+               wrmsrl(MSR_K7_EVNTSEL3, 0);
+               wrmsrl(MSR_K7_PERFCTR3, pmc3);
+               wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
+       } else {
+               release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+               release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+       }
+
+       return pmc_now * tsc_khz / (tsc_now - tsc_start);
+}
 
 /*
  * pit_calibrate_tsc() uses the speaker output (channel 2) of
@@ -285,7 +328,7 @@ static unsigned int __init pit_calibrate_tsc(void)
 #define PIT_MODE 0x43
 #define PIT_CH0  0x40
 
-static void __init __pit_init(int val, u8 mode)
+static void __pit_init(int val, u8 mode)
 {
        unsigned long flags;
 
@@ -301,12 +344,12 @@ void __init pit_init(void)
        __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
 }
 
-void __init pit_stop_interrupt(void)
+void pit_stop_interrupt(void)
 {
        __pit_init(0, 0x30); /* mode 0 */
 }
 
-void __init stop_timer_interrupt(void)
+void stop_timer_interrupt(void)
 {
        char *name;
        if (hpet_address) {
@@ -339,23 +382,29 @@ void __init time_init(void)
        if (hpet_use_timer) {
                /* set tick_nsec to use the proper rate for HPET */
                tick_nsec = TICK_NSEC_HPET;
-               cpu_khz = hpet_calibrate_tsc();
+               tsc_khz = hpet_calibrate_tsc();
                timename = "HPET";
        } else {
                pit_init();
-               cpu_khz = pit_calibrate_tsc();
+               tsc_khz = pit_calibrate_tsc();
                timename = "PIT";
        }
 
+       cpu_khz = tsc_khz;
+       if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
+               boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+               boot_cpu_data.x86 == 16)
+               cpu_khz = tsc_calibrate_cpu_khz();
+
        if (unsynchronized_tsc())
-               mark_tsc_unstable();
+               mark_tsc_unstable("TSCs unsynchronized");
 
        if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
                vgetcpu_mode = VGETCPU_RDTSCP;
        else
                vgetcpu_mode = VGETCPU_LSL;
 
-       set_cyc2ns_scale(cpu_khz);
+       set_cyc2ns_scale(tsc_khz);
        printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
                cpu_khz / 1000, cpu_khz % 1000);
        init_tsc_clocksource();
index c79b99a..e7e2764 100644 (file)
@@ -3,6 +3,7 @@
  *     Trampoline.S    Derived from Setup.S by Linus Torvalds
  *
  *     4 Jan 1997 Michael Chastain: changed to gnu as.
+ *     15 Sept 2005 Eric Biederman: 64bit PIC support
  *
  *     Entry: CS:IP point to the start of our code, we are 
  *     in real mode with no stack, but the rest of the 
  *     and IP is zero.  Thus, data addresses need to be absolute
  *     (no relocation) and are taken with regard to r_base.
  *
+ *     With the addition of trampoline_level4_pgt this code can
+ *     now enter a 64bit kernel that lives at arbitrary 64bit
+ *     physical addresses.
+ *
  *     If you work on this file, check the object module with objdump
  *     --full-contents --reloc to make sure there are no relocation
- *     entries. For the GDT entry we do hand relocation in smpboot.c
- *     because of 64bit linker limitations.
+ *     entries.
  */
 
 #include <linux/linkage.h>
-#include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/segment.h>
 
 .data
 
 
 ENTRY(trampoline_data)
 r_base = .
+       cli                     # We should be safe anyway
        wbinvd  
        mov     %cs, %ax        # Code and data in the same place
        mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %ss
 
-       cli                     # We should be safe anyway
 
        movl    $0xA5A5A5A5, trampoline_data - r_base
                                # write marker for master knows we're running
 
+                                       # Setup stack
+       movw    $(trampoline_stack_end - r_base), %sp
+
+       call    verify_cpu              # Verify the cpu supports long mode
+       testl   %eax, %eax              # Check for return code
+       jnz     no_longmode
+
+       mov     %cs, %ax
+       movzx   %ax, %esi               # Find the 32bit trampoline location
+       shll    $4, %esi
+
+                                       # Fixup the vectors
+       addl    %esi, startup_32_vector - r_base
+       addl    %esi, startup_64_vector - r_base
+       addl    %esi, tgdt + 2 - r_base # Fixup the gdt pointer
+
        /*
         * GDT tables in non default location kernel can be beyond 16MB and
         * lgdt will not be able to load the address as in real mode default
@@ -49,23 +73,94 @@ r_base = .
         * to 32 bit.
         */
 
-       lidtl   idt_48 - r_base # load idt with 0, 0
-       lgdtl   gdt_48 - r_base # load gdt with whatever is appropriate
+       lidtl   tidt - r_base   # load idt with 0, 0
+       lgdtl   tgdt - r_base   # load gdt with whatever is appropriate
 
        xor     %ax, %ax
        inc     %ax             # protected mode (PE) bit
        lmsw    %ax             # into protected mode
-       # flaush prefetch and jump to startup_32 in arch/x86_64/kernel/head.S
-       ljmpl   $__KERNEL32_CS, $(startup_32-__START_KERNEL_map)
+
+       # flush prefetch and jump to startup_32
+       ljmpl   *(startup_32_vector - r_base)
+
+       .code32
+       .balign 4
+startup_32:
+       movl    $__KERNEL_DS, %eax      # Initialize the %ds segment register
+       movl    %eax, %ds
+
+       xorl    %eax, %eax
+       btsl    $5, %eax                # Enable PAE mode
+       movl    %eax, %cr4
+
+                                       # Setup trampoline 4 level pagetables
+       leal    (trampoline_level4_pgt - r_base)(%esi), %eax
+       movl    %eax, %cr3
+
+       movl    $MSR_EFER, %ecx
+       movl    $(1 << _EFER_LME), %eax # Enable Long Mode
+       xorl    %edx, %edx
+       wrmsr
+
+       xorl    %eax, %eax
+       btsl    $31, %eax               # Enable paging and in turn activate Long Mode
+       btsl    $0, %eax                # Enable protected mode
+       movl    %eax, %cr0
+
+       /*
+        * At this point we're in long mode but in 32bit compatibility mode
+        * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
+        * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
+        * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+        */
+       ljmp    *(startup_64_vector - r_base)(%esi)
+
+       .code64
+       .balign 4
+startup_64:
+       # Now jump into the kernel using virtual addresses
+       movq    $secondary_startup_64, %rax
+       jmp     *%rax
+
+       .code16
+no_longmode:
+       hlt
+       jmp no_longmode
+#include "verify_cpu.S"
 
        # Careful these need to be in the same 64K segment as the above;
-idt_48:
+tidt:
        .word   0                       # idt limit = 0
        .word   0, 0                    # idt base = 0L
 
-gdt_48:
-       .short  GDT_ENTRIES*8 - 1       # gdt limit
-       .long   cpu_gdt_table-__START_KERNEL_map
+       # Duplicate the global descriptor table
+       # so the kernel can live anywhere
+       .balign 4
+tgdt:
+       .short  tgdt_end - tgdt         # gdt limit
+       .long   tgdt - r_base
+       .short 0
+       .quad   0x00cf9b000000ffff      # __KERNEL32_CS
+       .quad   0x00af9b000000ffff      # __KERNEL_CS
+       .quad   0x00cf93000000ffff      # __KERNEL_DS
+tgdt_end:
+
+       .balign 4
+startup_32_vector:
+       .long   startup_32 - r_base
+       .word   __KERNEL32_CS, 0
+
+       .balign 4
+startup_64_vector:
+       .long   startup_64 - r_base
+       .word   __KERNEL_CS, 0
+
+trampoline_stack:
+       .org 0x1000
+trampoline_stack_end:
+ENTRY(trampoline_level4_pgt)
+       .quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+       .fill   510,8,0
+       .quad   level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
 
-.globl trampoline_end
-trampoline_end:        
+ENTRY(trampoline_end)
index 09d2e8a..d76fc32 100644 (file)
@@ -426,8 +426,7 @@ void show_registers(struct pt_regs *regs)
        const int cpu = smp_processor_id();
        struct task_struct *cur = cpu_pda(cpu)->pcurrent;
 
-               rsp = regs->rsp;
-
+       rsp = regs->rsp;
        printk("CPU %d ", cpu);
        __show_regs(regs);
        printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
@@ -438,7 +437,6 @@ void show_registers(struct pt_regs *regs)
         * time of the fault..
         */
        if (in_kernel) {
-
                printk("Stack: ");
                _show_stack(NULL, regs, (unsigned long*)rsp);
 
@@ -581,10 +579,20 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
 {
        struct task_struct *tsk = current;
 
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = trapnr;
-
        if (user_mode(regs)) {
+               /*
+                * We want error_code and trap_no set for userspace
+                * faults and kernelspace faults which result in
+                * die(), but not kernelspace faults which are fixed
+                * up.  die() gives the process no chance to handle
+                * the signal and notice the kernel fault information,
+                * so that won't result in polluting the information
+                * about previously queued, but not yet delivered,
+                * faults.  See also do_general_protection below.
+                */
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
+
                if (exception_trace && unhandled_signal(tsk, signr))
                        printk(KERN_INFO
                               "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
@@ -605,8 +613,11 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
                fixup = search_exception_tables(regs->rip);
                if (fixup)
                        regs->rip = fixup->fixup;
-               else    
+               else {
+                       tsk->thread.error_code = error_code;
+                       tsk->thread.trap_no = trapnr;
                        die(str, regs, error_code);
+               }
                return;
        }
 }
@@ -682,10 +693,10 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
 
        conditional_sti(regs);
 
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
-
        if (user_mode(regs)) {
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = 13;
+
                if (exception_trace && unhandled_signal(tsk, SIGSEGV))
                        printk(KERN_INFO
                       "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
@@ -704,6 +715,9 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
                        regs->rip = fixup->fixup;
                        return;
                }
+
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = 13;
                if (notify_die(DIE_GPF, "general protection fault", regs,
                                        error_code, 13, SIGSEGV) == NOTIFY_STOP)
                        return;
index 1a0edbb..48f9a8e 100644 (file)
@@ -13,6 +13,8 @@ static int notsc __initdata = 0;
 
 unsigned int cpu_khz;          /* TSC clocks / usec, not used here */
 EXPORT_SYMBOL(cpu_khz);
+unsigned int tsc_khz;
+EXPORT_SYMBOL(tsc_khz);
 
 static unsigned int cyc2ns_scale __read_mostly;
 
@@ -77,7 +79,7 @@ static void handle_cpufreq_delayed_get(struct work_struct *v)
 static unsigned int  ref_freq = 0;
 static unsigned long loops_per_jiffy_ref = 0;
 
-static unsigned long cpu_khz_ref = 0;
+static unsigned long tsc_khz_ref = 0;
 
 static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
                                 void *data)
@@ -99,7 +101,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
        if (!ref_freq) {
                ref_freq = freq->old;
                loops_per_jiffy_ref = *lpj;
-               cpu_khz_ref = cpu_khz;
+               tsc_khz_ref = tsc_khz;
        }
        if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
                (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
@@ -107,12 +109,12 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
                *lpj =
                cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 
-               cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
+               tsc_khz = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new);
                if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-                       mark_tsc_unstable();
+                       mark_tsc_unstable("cpufreq changes");
        }
 
-       set_cyc2ns_scale(cpu_khz_ref);
+       set_cyc2ns_scale(tsc_khz_ref);
 
        return 0;
 }
@@ -197,10 +199,11 @@ static struct clocksource clocksource_tsc = {
        .vread                  = vread_tsc,
 };
 
-void mark_tsc_unstable(void)
+void mark_tsc_unstable(char *reason)
 {
        if (!tsc_unstable) {
                tsc_unstable = 1;
+               printk("Marking TSC unstable due to %s\n", reason);
                /* Change only the rating, when not registered */
                if (clocksource_tsc.mult)
                        clocksource_change_rating(&clocksource_tsc, 0);
@@ -213,7 +216,7 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 void __init init_tsc_clocksource(void)
 {
        if (!notsc) {
-               clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
+               clocksource_tsc.mult = clocksource_khz2mult(tsc_khz,
                                                        clocksource_tsc.shift);
                if (check_tsc_unstable())
                        clocksource_tsc.rating = 0;
index 014f0db..355f5f5 100644 (file)
@@ -50,7 +50,7 @@ static __cpuinit void check_tsc_warp(void)
        /*
         * The measurement runs for 20 msecs:
         */
-       end = start + cpu_khz * 20ULL;
+       end = start + tsc_khz * 20ULL;
        now = start;
 
        for (i = 0; ; i++) {
@@ -138,7 +138,7 @@ void __cpuinit check_tsc_sync_source(int cpu)
                printk("\n");
                printk(KERN_WARNING "Measured %Ld cycles TSC warp between CPUs,"
                                    " turning off TSC clock.\n", max_warp);
-               mark_tsc_unstable();
+               mark_tsc_unstable("check_tsc_sync_source failed");
                nr_warps = 0;
                max_warp = 0;
                last_tsc = 0;
diff --git a/arch/x86_64/kernel/verify_cpu.S b/arch/x86_64/kernel/verify_cpu.S
new file mode 100644 (file)
index 0000000..e035f59
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *
+ *     verify_cpu.S - Code for cpu long mode and SSE verification. This
+ *     code has been borrowed from boot/setup.S and was introduced by
+ *     Andi Kleen.
+ *
+ *     Copyright (c) 2007  Andi Kleen (ak@suse.de)
+ *     Copyright (c) 2007  Eric Biederman (ebiederm@xmission.com)
+ *     Copyright (c) 2007  Vivek Goyal (vgoyal@in.ibm.com)
+ *
+ *     This source code is licensed under the GNU General Public License,
+ *     Version 2.  See the file COPYING for more details.
+ *
+ *     This is a common code for verification whether CPU supports
+ *     long mode and SSE or not. It is not called directly instead this
+ *     file is included at various places and compiled in that context.
+ *     Following are the current usage.
+ *
+ *     This file is included by both 16bit and 32bit code.
+ *
+ *     arch/x86_64/boot/setup.S : Boot cpu verification (16bit)
+ *     arch/x86_64/boot/compressed/head.S: Boot cpu verification (32bit)
+ *     arch/x86_64/kernel/trampoline.S: secondary processor verfication (16bit)
+ *     arch/x86_64/kernel/acpi/wakeup.S:Verfication at resume (16bit)
+ *
+ *     verify_cpu, returns the status of cpu check in register %eax.
+ *             0: Success    1: Failure
+ *
+ *     The caller needs to check for the error code and take the action
+ *     appropriately. Either display a message or halt.
+ */
+
+#include <asm/cpufeature.h>
+
+verify_cpu:
+       pushfl                          # Save caller passed flags
+       pushl   $0                      # Kill any dangerous flags
+       popfl
+
+       /* minimum CPUID flags for x86-64 as defined by AMD */
+#define M(x) (1<<(x))
+#define M2(a,b) M(a)|M(b)
+#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d)
+
+#define SSE_MASK \
+       (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2))
+#define REQUIRED_MASK1 \
+       (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\
+        M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\
+        M(X86_FEATURE_FXSR))
+#define REQUIRED_MASK2 \
+       (M(X86_FEATURE_LM - 32))
+
+       pushfl                          # standard way to check for cpuid
+       popl    %eax
+       movl    %eax,%ebx
+       xorl    $0x200000,%eax
+       pushl   %eax
+       popfl
+       pushfl
+       popl    %eax
+       cmpl    %eax,%ebx
+       jz      verify_cpu_no_longmode  # cpu has no cpuid
+
+       movl    $0x0,%eax               # See if cpuid 1 is implemented
+       cpuid
+       cmpl    $0x1,%eax
+       jb      verify_cpu_no_longmode  # no cpuid 1
+
+       xor     %di,%di
+       cmpl    $0x68747541,%ebx        # AuthenticAMD
+       jnz     verify_cpu_noamd
+       cmpl    $0x69746e65,%edx
+       jnz     verify_cpu_noamd
+       cmpl    $0x444d4163,%ecx
+       jnz     verify_cpu_noamd
+       mov     $1,%di                  # cpu is from AMD
+
+verify_cpu_noamd:
+       movl    $0x1,%eax               # Does the cpu have what it takes
+       cpuid
+       andl    $REQUIRED_MASK1,%edx
+       xorl    $REQUIRED_MASK1,%edx
+       jnz     verify_cpu_no_longmode
+
+       movl    $0x80000000,%eax        # See if extended cpuid is implemented
+       cpuid
+       cmpl    $0x80000001,%eax
+       jb      verify_cpu_no_longmode  # no extended cpuid
+
+       movl    $0x80000001,%eax        # Does the cpu have what it takes
+       cpuid
+       andl    $REQUIRED_MASK2,%edx
+       xorl    $REQUIRED_MASK2,%edx
+       jnz     verify_cpu_no_longmode
+
+verify_cpu_sse_test:
+       movl    $1,%eax
+       cpuid
+       andl    $SSE_MASK,%edx
+       cmpl    $SSE_MASK,%edx
+       je      verify_cpu_sse_ok
+       test    %di,%di
+       jz      verify_cpu_no_longmode  # only try to force SSE on AMD
+       movl    $0xc0010015,%ecx        # HWCR
+       rdmsr
+       btr     $15,%eax                # enable SSE
+       wrmsr
+       xor     %di,%di                 # don't loop
+       jmp     verify_cpu_sse_test     # try again
+
+verify_cpu_no_longmode:
+       popfl                           # Restore caller passed flags
+       movl $1,%eax
+       ret
+verify_cpu_sse_ok:
+       popfl                           # Restore caller passed flags
+       xorl %eax, %eax
+       ret
index 5176ecf..88cfa50 100644 (file)
@@ -29,9 +29,7 @@ SECTIONS
   .text :  AT(ADDR(.text) - LOAD_OFFSET) {
        /* First the code that has to be first for bootstrapping */
        *(.bootstrap.text)
-       /* Then all the functions that are "hot" in profiles, to group them
-           onto the same hugetlb entry */
-       #include "functionlist"
+       _stext = .;
        /* Then the rest */
        *(.text)
        SCHED_TEXT
@@ -50,10 +48,10 @@ SECTIONS
   __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
   __stop___ex_table = .;
 
-  RODATA
-
   BUG_TABLE
 
+  RODATA
+
   . = ALIGN(PAGE_SIZE);        /* Align data segment to page size boundary */
                                /* Data */
   .data : AT(ADDR(.data) - LOAD_OFFSET) {
@@ -94,6 +92,12 @@ SECTIONS
                { *(.vsyscall_gtod_data) }
   vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
 
+
+  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
+               { *(.vsyscall_1) }
+  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
+               { *(.vsyscall_2) }
+
   .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
   vgetcpu_mode = VVIRT(.vgetcpu_mode);
 
@@ -101,10 +105,6 @@ SECTIONS
   .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
   jiffies = VVIRT(.jiffies);
 
-  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
-               { *(.vsyscall_1) }
-  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
-               { *(.vsyscall_2) }
   .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
                { *(.vsyscall_3) }
 
@@ -194,7 +194,7 @@ SECTIONS
   __initramfs_end = .;
 #endif
 
-    . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
   __per_cpu_end = .;
index b43c698..dc32cef 100644 (file)
 
 #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
 #define __syscall_clobber "r11","rcx","memory"
+#define __pa_vsymbol(x)                        \
+       ({unsigned long v;              \
+       extern char __vsyscall_0;       \
+         asm("" : "=r" (v) : "0" (x)); \
+         ((v - VSYSCALL_FIRST_PAGE) + __pa_symbol(&__vsyscall_0)); })
 
+/*
+ * vsyscall_gtod_data contains data that is :
+ * - readonly from vsyscalls
+ * - writen by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
+ * Try to keep this structure as small as possible to avoid cache line ping pongs
+ */
 struct vsyscall_gtod_data_t {
-       seqlock_t lock;
-       int sysctl_enabled;
-       struct timeval wall_time_tv;
+       seqlock_t       lock;
+
+       /* open coded 'struct timespec' */
+       time_t          wall_time_sec;
+       u32             wall_time_nsec;
+
+       int             sysctl_enabled;
        struct timezone sys_tz;
-       cycle_t offset_base;
-       struct clocksource clock;
+       struct { /* extract of a clocksource struct */
+               cycle_t (*vread)(void);
+               cycle_t cycle_last;
+               cycle_t mask;
+               u32     mult;
+               u32     shift;
+       } clock;
 };
 int __vgetcpu_mode __section_vgetcpu_mode;
 
@@ -68,9 +88,13 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
 
        write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
        /* copy vsyscall data */
-       vsyscall_gtod_data.clock = *clock;
-       vsyscall_gtod_data.wall_time_tv.tv_sec = wall_time->tv_sec;
-       vsyscall_gtod_data.wall_time_tv.tv_usec = wall_time->tv_nsec/1000;
+       vsyscall_gtod_data.clock.vread = clock->vread;
+       vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
+       vsyscall_gtod_data.clock.mask = clock->mask;
+       vsyscall_gtod_data.clock.mult = clock->mult;
+       vsyscall_gtod_data.clock.shift = clock->shift;
+       vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+       vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
        vsyscall_gtod_data.sys_tz = sys_tz;
        write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
 }
@@ -105,7 +129,8 @@ static __always_inline long time_syscall(long *t)
 static __always_inline void do_vgettimeofday(struct timeval * tv)
 {
        cycle_t now, base, mask, cycle_delta;
-       unsigned long seq, mult, shift, nsec_delta;
+       unsigned seq;
+       unsigned long mult, shift, nsec;
        cycle_t (*vread)(void);
        do {
                seq = read_seqbegin(&__vsyscall_gtod_data.lock);
@@ -121,21 +146,20 @@ static __always_inline void do_vgettimeofday(struct timeval * tv)
                mult = __vsyscall_gtod_data.clock.mult;
                shift = __vsyscall_gtod_data.clock.shift;
 
-               *tv = __vsyscall_gtod_data.wall_time_tv;
-
+               tv->tv_sec = __vsyscall_gtod_data.wall_time_sec;
+               nsec = __vsyscall_gtod_data.wall_time_nsec;
        } while (read_seqretry(&__vsyscall_gtod_data.lock, seq));
 
        /* calculate interval: */
        cycle_delta = (now - base) & mask;
        /* convert to nsecs: */
-       nsec_delta = (cycle_delta * mult) >> shift;
+       nsec += (cycle_delta * mult) >> shift;
 
-       /* convert to usecs and add to timespec: */
-       tv->tv_usec += nsec_delta / NSEC_PER_USEC;
-       while (tv->tv_usec > USEC_PER_SEC) {
+       while (nsec >= NSEC_PER_SEC) {
                tv->tv_sec += 1;
-               tv->tv_usec -= USEC_PER_SEC;
+               nsec -= NSEC_PER_SEC;
        }
+       tv->tv_usec = nsec / NSEC_PER_USEC;
 }
 
 int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
@@ -151,11 +175,13 @@ int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
  * unlikely */
 time_t __vsyscall(1) vtime(time_t *t)
 {
+       time_t result;
        if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
                return time_syscall(t);
-       else if (t)
-               *t = __vsyscall_gtod_data.wall_time_tv.tv_sec;
-       return __vsyscall_gtod_data.wall_time_tv.tv_sec;
+       result = __vsyscall_gtod_data.wall_time_sec;
+       if (t)
+               *t = result;
+       return result;
 }
 
 /* Fast way to get current CPU and node.
@@ -224,10 +250,10 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
                return ret;
        /* gcc has some trouble with __va(__pa()), so just do it this
           way. */
-       map1 = ioremap(__pa_symbol(&vsysc1), 2);
+       map1 = ioremap(__pa_vsymbol(&vsysc1), 2);
        if (!map1)
                return -ENOMEM;
-       map2 = ioremap(__pa_symbol(&vsysc2), 2);
+       map2 = ioremap(__pa_vsymbol(&vsysc2), 2);
        if (!map2) {
                ret = -ENOMEM;
                goto out;
index 6ada723..de99dba 100644 (file)
@@ -585,7 +585,7 @@ do_sigbus:
 }
 
 DEFINE_SPINLOCK(pgd_lock);
-struct page *pgd_list;
+LIST_HEAD(pgd_list);
 
 void vmalloc_sync_all(void)
 {
@@ -605,8 +605,7 @@ void vmalloc_sync_all(void)
                        if (pgd_none(*pgd_ref))
                                continue;
                        spin_lock(&pgd_lock);
-                       for (page = pgd_list; page;
-                            page = (struct page *)page->index) {
+                       list_for_each_entry(page, &pgd_list, lru) {
                                pgd_t *pgd;
                                pgd = (pgd_t *)page_address(page) + pgd_index(address);
                                if (pgd_none(*pgd))
index ec31534..282b0a8 100644 (file)
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
+#include <linux/pfn.h>
 #include <linux/poison.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/memory_hotplug.h>
+#include <linux/nmi.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -46,7 +48,7 @@
 #define Dprintk(x...)
 #endif
 
-struct dma_mapping_ops* dma_ops;
+const struct dma_mapping_ops* dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
 static unsigned long dma_reserve __initdata;
@@ -72,6 +74,11 @@ void show_mem(void)
 
        for_each_online_pgdat(pgdat) {
                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+                       /* this loop can take a while with 256 GB and 4k pages
+                          so update the NMI watchdog */
+                       if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
+                               touch_nmi_watchdog();
+                       }
                        page = pfn_to_page(pgdat->node_start_pfn + i);
                        total++;
                        if (PageReserved(page))
@@ -167,23 +174,9 @@ __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 
 unsigned long __initdata table_start, table_end; 
 
-extern pmd_t temp_boot_pmds[]; 
-
-static  struct temp_map { 
-       pmd_t *pmd;
-       void  *address; 
-       int    allocated; 
-} temp_mappings[] __initdata = { 
-       { &temp_boot_pmds[0], (void *)(40UL * 1024 * 1024) },
-       { &temp_boot_pmds[1], (void *)(42UL * 1024 * 1024) }, 
-       {}
-}; 
-
-static __meminit void *alloc_low_page(int *index, unsigned long *phys)
+static __meminit void *alloc_low_page(unsigned long *phys)
 { 
-       struct temp_map *ti;
-       int i; 
-       unsigned long pfn = table_end++, paddr; 
+       unsigned long pfn = table_end++;
        void *adr;
 
        if (after_bootmem) {
@@ -194,57 +187,63 @@ static __meminit void *alloc_low_page(int *index, unsigned long *phys)
 
        if (pfn >= end_pfn) 
                panic("alloc_low_page: ran out of memory"); 
-       for (i = 0; temp_mappings[i].allocated; i++) {
-               if (!temp_mappings[i].pmd) 
-                       panic("alloc_low_page: ran out of temp mappings"); 
-       } 
-       ti = &temp_mappings[i];
-       paddr = (pfn << PAGE_SHIFT) & PMD_MASK; 
-       set_pmd(ti->pmd, __pmd(paddr | _KERNPG_TABLE | _PAGE_PSE)); 
-       ti->allocated = 1; 
-       __flush_tlb();         
-       adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK); 
+
+       adr = early_ioremap(pfn * PAGE_SIZE, PAGE_SIZE);
        memset(adr, 0, PAGE_SIZE);
-       *index = i; 
-       *phys  = pfn * PAGE_SIZE;  
-       return adr; 
-} 
+       *phys  = pfn * PAGE_SIZE;
+       return adr;
+}
 
-static __meminit void unmap_low_page(int i)
+static __meminit void unmap_low_page(void *adr)
 { 
-       struct temp_map *ti;
 
        if (after_bootmem)
                return;
 
-       ti = &temp_mappings[i];
-       set_pmd(ti->pmd, __pmd(0));
-       ti->allocated = 0; 
+       early_iounmap(adr, PAGE_SIZE);
 } 
 
 /* Must run before zap_low_mappings */
 __init void *early_ioremap(unsigned long addr, unsigned long size)
 {
-       unsigned long map = round_down(addr, LARGE_PAGE_SIZE); 
-
-       /* actually usually some more */
-       if (size >= LARGE_PAGE_SIZE) { 
-               return NULL;
+       unsigned long vaddr;
+       pmd_t *pmd, *last_pmd;
+       int i, pmds;
+
+       pmds = ((addr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
+       vaddr = __START_KERNEL_map;
+       pmd = level2_kernel_pgt;
+       last_pmd = level2_kernel_pgt + PTRS_PER_PMD - 1;
+       for (; pmd <= last_pmd; pmd++, vaddr += PMD_SIZE) {
+               for (i = 0; i < pmds; i++) {
+                       if (pmd_present(pmd[i]))
+                               goto next;
+               }
+               vaddr += addr & ~PMD_MASK;
+               addr &= PMD_MASK;
+               for (i = 0; i < pmds; i++, addr += PMD_SIZE)
+                       set_pmd(pmd + i,__pmd(addr | _KERNPG_TABLE | _PAGE_PSE));
+               __flush_tlb();
+               return (void *)vaddr;
+       next:
+               ;
        }
-       set_pmd(temp_mappings[0].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
-       map += LARGE_PAGE_SIZE;
-       set_pmd(temp_mappings[1].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
-       __flush_tlb();
-       return temp_mappings[0].address + (addr & (LARGE_PAGE_SIZE-1));
+       printk("early_ioremap(0x%lx, %lu) failed\n", addr, size);
+       return NULL;
 }
 
 /* To avoid virtual aliases later */
 __init void early_iounmap(void *addr, unsigned long size)
 {
-       if ((void *)round_down((unsigned long)addr, LARGE_PAGE_SIZE) != temp_mappings[0].address)
-               printk("early_iounmap: bad address %p\n", addr);
-       set_pmd(temp_mappings[0].pmd, __pmd(0));
-       set_pmd(temp_mappings[1].pmd, __pmd(0));
+       unsigned long vaddr;
+       pmd_t *pmd;
+       int i, pmds;
+
+       vaddr = (unsigned long)addr;
+       pmds = ((vaddr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
+       pmd = level2_kernel_pgt + pmd_index(vaddr);
+       for (i = 0; i < pmds; i++)
+               pmd_clear(pmd + i);
        __flush_tlb();
 }
 
@@ -289,7 +288,6 @@ static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigne
 
 
        for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE ) {
-               int map; 
                unsigned long pmd_phys;
                pud_t *pud = pud_page + pud_index(addr);
                pmd_t *pmd;
@@ -307,12 +305,12 @@ static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigne
                        continue;
                }
 
-               pmd = alloc_low_page(&map, &pmd_phys);
+               pmd = alloc_low_page(&pmd_phys);
                spin_lock(&init_mm.page_table_lock);
                set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
                phys_pmd_init(pmd, addr, end);
                spin_unlock(&init_mm.page_table_lock);
-               unmap_low_page(map);
+               unmap_low_page(pmd);
        }
        __flush_tlb();
 } 
@@ -364,7 +362,6 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end)
        end = (unsigned long)__va(end);
 
        for (; start < end; start = next) {
-               int map;
                unsigned long pud_phys; 
                pgd_t *pgd = pgd_offset_k(start);
                pud_t *pud;
@@ -372,7 +369,7 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end)
                if (after_bootmem)
                        pud = pud_offset(pgd, start & PGDIR_MASK);
                else
-                       pud = alloc_low_page(&map, &pud_phys);
+                       pud = alloc_low_page(&pud_phys);
 
                next = start + PGDIR_SIZE;
                if (next > end) 
@@ -380,7 +377,7 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end)
                phys_pud_init(pud, __pa(start), __pa(next));
                if (!after_bootmem)
                        set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
-               unmap_low_page(map);   
+               unmap_low_page(pud);
        } 
 
        if (!after_bootmem)
@@ -388,21 +385,6 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end)
        __flush_tlb_all();
 }
 
-void __cpuinit zap_low_mappings(int cpu)
-{
-       if (cpu == 0) {
-               pgd_t *pgd = pgd_offset_k(0UL);
-               pgd_clear(pgd);
-       } else {
-               /*
-                * For AP's, zap the low identity mappings by changing the cr3
-                * to init_level4_pgt and doing local flush tlb all
-                */
-               asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));
-       }
-       __flush_tlb_all();
-}
-
 #ifndef CONFIG_NUMA
 void __init paging_init(void)
 {
@@ -579,15 +561,6 @@ void __init mem_init(void)
                reservedpages << (PAGE_SHIFT-10),
                datasize >> 10,
                initsize >> 10);
-
-#ifdef CONFIG_SMP
-       /*
-        * Sync boot_level4_pgt mappings with the init_level4_pgt
-        * except for the low identity mappings which are already zapped
-        * in init_level4_pgt. This sync-up is essential for AP's bringup
-        */
-       memcpy(boot_level4_pgt+1, init_level4_pgt+1, (PTRS_PER_PGD-1)*sizeof(pgd_t));
-#endif
 }
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
@@ -597,37 +570,44 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
        if (begin >= end)
                return;
 
-       printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+       printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
        for (addr = begin; addr < end; addr += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(addr));
-               init_page_count(virt_to_page(addr));
-               memset((void *)(addr & ~(PAGE_SIZE-1)),
-                       POISON_FREE_INITMEM, PAGE_SIZE);
-               free_page(addr);
+               struct page *page = pfn_to_page(addr >> PAGE_SHIFT);
+               ClearPageReserved(page);
+               init_page_count(page);
+               memset(page_address(page), POISON_FREE_INITMEM, PAGE_SIZE);
+               if (addr >= __START_KERNEL_map)
+                       change_page_attr_addr(addr, 1, __pgprot(0));
+               __free_page(page);
                totalram_pages++;
        }
+       if (addr > __START_KERNEL_map)
+               global_flush_tlb();
 }
 
 void free_initmem(void)
 {
-       memset(__initdata_begin, POISON_FREE_INITDATA,
-               __initdata_end - __initdata_begin);
        free_init_pages("unused kernel memory",
-                       (unsigned long)(&__init_begin),
-                       (unsigned long)(&__init_end));
+                       __pa_symbol(&__init_begin),
+                       __pa_symbol(&__init_end));
 }
 
 #ifdef CONFIG_DEBUG_RODATA
 
 void mark_rodata_ro(void)
 {
-       unsigned long addr = (unsigned long)__start_rodata;
+       unsigned long start = PFN_ALIGN(__va(__pa_symbol(&_stext))), size;
 
-       for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
-               change_page_attr_addr(addr, 1, PAGE_KERNEL_RO);
+#ifdef CONFIG_HOTPLUG_CPU
+       /* It must still be possible to apply SMP alternatives. */
+       if (num_possible_cpus() > 1)
+               start = PFN_ALIGN(__va(__pa_symbol(&_etext)));
+#endif
+       size = (unsigned long)__va(__pa_symbol(&__end_rodata)) - start;
+       change_page_attr_addr(start, size >> PAGE_SHIFT, PAGE_KERNEL_RO);
 
-       printk ("Write protecting the kernel read-only data: %luk\n",
-                       (__end_rodata - __start_rodata) >> 10);
+       printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+              size >> 10);
 
        /*
         * change_page_attr_addr() requires a global_flush_tlb() call after it.
@@ -642,7 +622,7 @@ void mark_rodata_ro(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-       free_init_pages("initrd memory", start, end);
+       free_init_pages("initrd memory", __pa(start), __pa(end));
 }
 #endif
 
index b5b8dba..f983c75 100644 (file)
@@ -49,11 +49,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        int found = 0;
        u32 reg;
        unsigned numnodes;
-       nodemask_t nodes_parsed;
        unsigned dualcore = 0;
 
-       nodes_clear(nodes_parsed);
-
        if (!early_pci_allowed())
                return -1;
 
@@ -65,6 +62,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 
        reg = read_pci_config(0, nb, 0, 0x60); 
        numnodes = ((reg >> 4) & 0xF) + 1;
+       if (numnodes <= 1)
+               return -1;
 
        printk(KERN_INFO "Number of nodes %d\n", numnodes);
 
@@ -102,7 +101,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
                               nodeid, (base>>8)&3, (limit>>8) & 3); 
                        return -1; 
                }       
-               if (node_isset(nodeid, nodes_parsed)) { 
+               if (node_isset(nodeid, node_possible_map)) {
                        printk(KERN_INFO "Node %d already present. Skipping\n", 
                               nodeid);
                        continue;
@@ -155,7 +154,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 
                prevbase = base;
 
-               node_set(nodeid, nodes_parsed);
+               node_set(nodeid, node_possible_map);
        } 
 
        if (!found)
index 41b8fb0..5154894 100644 (file)
@@ -273,125 +273,213 @@ void __init numa_init_array(void)
 
 #ifdef CONFIG_NUMA_EMU
 /* Numa emulation */
-int numa_fake __initdata = 0;
+#define E820_ADDR_HOLE_SIZE(start, end)                                        \
+       (e820_hole_size((start) >> PAGE_SHIFT, (end) >> PAGE_SHIFT) <<  \
+       PAGE_SHIFT)
+char *cmdline __initdata;
 
 /*
- * This function is used to find out if the start and end correspond to
- * different zones.
+ * Setups up nid to range from addr to addr + size.  If the end boundary is
+ * greater than max_addr, then max_addr is used instead.  The return value is 0
+ * if there is additional memory left for allocation past addr and -1 otherwise.
+ * addr is adjusted to be at the end of the node.
  */
-int zone_cross_over(unsigned long start, unsigned long end)
+static int __init setup_node_range(int nid, struct bootnode *nodes, u64 *addr,
+                                  u64 size, u64 max_addr)
 {
-       if ((start < (MAX_DMA32_PFN << PAGE_SHIFT)) &&
-                       (end >= (MAX_DMA32_PFN << PAGE_SHIFT)))
-               return 1;
-       return 0;
+       int ret = 0;
+       nodes[nid].start = *addr;
+       *addr += size;
+       if (*addr >= max_addr) {
+               *addr = max_addr;
+               ret = -1;
+       }
+       nodes[nid].end = *addr;
+       node_set(nid, node_possible_map);
+       printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
+              nodes[nid].start, nodes[nid].end,
+              (nodes[nid].end - nodes[nid].start) >> 20);
+       return ret;
 }
 
-static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+/*
+ * Splits num_nodes nodes up equally starting at node_start.  The return value
+ * is the number of nodes split up and addr is adjusted to be at the end of the
+ * last node allocated.
+ */
+static int __init split_nodes_equally(struct bootnode *nodes, u64 *addr,
+                                     u64 max_addr, int node_start,
+                                     int num_nodes)
 {
-       int i, big;
-       struct bootnode nodes[MAX_NUMNODES];
-       unsigned long sz, old_sz;
-       unsigned long hole_size;
-       unsigned long start, end;
-       unsigned long max_addr = (end_pfn << PAGE_SHIFT);
-
-       start = (start_pfn << PAGE_SHIFT);
-       hole_size = e820_hole_size(start, max_addr);
-       sz = (max_addr - start - hole_size) / numa_fake;
-
-       /* Kludge needed for the hash function */
-
-       old_sz = sz;
-       /*
-        * Round down to the nearest FAKE_NODE_MIN_SIZE.
-        */
-       sz &= FAKE_NODE_MIN_HASH_MASK;
+       unsigned int big;
+       u64 size;
+       int i;
 
+       if (num_nodes <= 0)
+               return -1;
+       if (num_nodes > MAX_NUMNODES)
+               num_nodes = MAX_NUMNODES;
+       size = (max_addr - *addr - E820_ADDR_HOLE_SIZE(*addr, max_addr)) /
+              num_nodes;
        /*
-        * We ensure that each node is at least 64MB big.  Smaller than this
-        * size can cause VM hiccups.
+        * Calculate the number of big nodes that can be allocated as a result
+        * of consolidating the leftovers.
         */
-       if (sz == 0) {
-               printk(KERN_INFO "Not enough memory for %d nodes.  Reducing "
-                               "the number of nodes\n", numa_fake);
-               numa_fake = (max_addr - start - hole_size) / FAKE_NODE_MIN_SIZE;
-               printk(KERN_INFO "Number of fake nodes will be = %d\n",
-                               numa_fake);
-               sz = FAKE_NODE_MIN_SIZE;
+       big = ((size & ~FAKE_NODE_MIN_HASH_MASK) * num_nodes) /
+             FAKE_NODE_MIN_SIZE;
+
+       /* Round down to nearest FAKE_NODE_MIN_SIZE. */
+       size &= FAKE_NODE_MIN_HASH_MASK;
+       if (!size) {
+               printk(KERN_ERR "Not enough memory for each node.  "
+                      "NUMA emulation disabled.\n");
+               return -1;
        }
-       /*
-        * Find out how many nodes can get an extra NODE_MIN_SIZE granule.
-        * This logic ensures the extra memory gets distributed among as many
-        * nodes as possible (as compared to one single node getting all that
-        * extra memory.
-        */
-       big = ((old_sz - sz) * numa_fake) / FAKE_NODE_MIN_SIZE;
-       printk(KERN_INFO "Fake node Size: %luMB hole_size: %luMB big nodes: "
-                       "%d\n",
-                       (sz >> 20), (hole_size >> 20), big);
-       memset(&nodes,0,sizeof(nodes));
-       end = start;
-       for (i = 0; i < numa_fake; i++) {
-               /*
-                * In case we are not able to allocate enough memory for all
-                * the nodes, we reduce the number of fake nodes.
-                */
-               if (end >= max_addr) {
-                       numa_fake = i - 1;
-                       break;
-               }
-               start = nodes[i].start = end;
-               /*
-                * Final node can have all the remaining memory.
-                */
-               if (i == numa_fake-1)
-                       sz = max_addr - start;
-               end = nodes[i].start + sz;
-               /*
-                * Fir "big" number of nodes get extra granule.
-                */
+
+       for (i = node_start; i < num_nodes + node_start; i++) {
+               u64 end = *addr + size;
                if (i < big)
                        end += FAKE_NODE_MIN_SIZE;
                /*
-                * Iterate over the range to ensure that this node gets at
-                * least sz amount of RAM (excluding holes)
+                * The final node can have the remaining system RAM.  Other
+                * nodes receive roughly the same amount of available pages.
                 */
-               while ((end - start - e820_hole_size(start, end)) < sz) {
-                       end += FAKE_NODE_MIN_SIZE;
-                       if (end >= max_addr)
-                               break;
+               if (i == num_nodes + node_start - 1)
+                       end = max_addr;
+               else
+                       while (end - *addr - E820_ADDR_HOLE_SIZE(*addr, end) <
+                              size) {
+                               end += FAKE_NODE_MIN_SIZE;
+                               if (end > max_addr) {
+                                       end = max_addr;
+                                       break;
+                               }
+                       }
+               if (setup_node_range(i, nodes, addr, end - *addr, max_addr) < 0)
+                       break;
+       }
+       return i - node_start + 1;
+}
+
+/*
+ * Splits the remaining system RAM into chunks of size.  The remaining memory is
+ * always assigned to a final node and can be asymmetric.  Returns the number of
+ * nodes split.
+ */
+static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
+                                     u64 max_addr, int node_start, u64 size)
+{
+       int i = node_start;
+       size = (size << 20) & FAKE_NODE_MIN_HASH_MASK;
+       while (!setup_node_range(i++, nodes, addr, size, max_addr))
+               ;
+       return i - node_start;
+}
+
+/*
+ * Sets up the system RAM area from start_pfn to end_pfn according to the
+ * numa=fake command-line option.
+ */
+static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+{
+       struct bootnode nodes[MAX_NUMNODES];
+       u64 addr = start_pfn << PAGE_SHIFT;
+       u64 max_addr = end_pfn << PAGE_SHIFT;
+       int num_nodes = 0;
+       int coeff_flag;
+       int coeff = -1;
+       int num = 0;
+       u64 size;
+       int i;
+
+       memset(&nodes, 0, sizeof(nodes));
+       /*
+        * If the numa=fake command-line is just a single number N, split the
+        * system RAM into N fake nodes.
+        */
+       if (!strchr(cmdline, '*') && !strchr(cmdline, ',')) {
+               num_nodes = split_nodes_equally(nodes, &addr, max_addr, 0,
+                                               simple_strtol(cmdline, NULL, 0));
+               if (num_nodes < 0)
+                       return num_nodes;
+               goto out;
+       }
+
+       /* Parse the command line. */
+       for (coeff_flag = 0; ; cmdline++) {
+               if (*cmdline && isdigit(*cmdline)) {
+                       num = num * 10 + *cmdline - '0';
+                       continue;
                }
-               /*
-                * Look at the next node to make sure there is some real memory
-                * to map.  Bad things happen when the only memory present
-                * in a zone on a fake node is IO hole.
-                */
-               while (e820_hole_size(end, end + FAKE_NODE_MIN_SIZE) > 0) {
-                       if (zone_cross_over(start, end + sz)) {
-                               end = (MAX_DMA32_PFN << PAGE_SHIFT);
+               if (*cmdline == '*') {
+                       if (num > 0)
+                               coeff = num;
+                       coeff_flag = 1;
+               }
+               if (!*cmdline || *cmdline == ',') {
+                       if (!coeff_flag)
+                               coeff = 1;
+                       /*
+                        * Round down to the nearest FAKE_NODE_MIN_SIZE.
+                        * Command-line coefficients are in megabytes.
+                        */
+                       size = ((u64)num << 20) & FAKE_NODE_MIN_HASH_MASK;
+                       if (size)
+                               for (i = 0; i < coeff; i++, num_nodes++)
+                                       if (setup_node_range(num_nodes, nodes,
+                                               &addr, size, max_addr) < 0)
+                                               goto done;
+                       if (!*cmdline)
                                break;
-                       }
-                       if (end >= max_addr)
+                       coeff_flag = 0;
+                       coeff = -1;
+               }
+               num = 0;
+       }
+done:
+       if (!num_nodes)
+               return -1;
+       /* Fill remainder of system RAM, if appropriate. */
+       if (addr < max_addr) {
+               if (coeff_flag && coeff < 0) {
+                       /* Split remaining nodes into num-sized chunks */
+                       num_nodes += split_nodes_by_size(nodes, &addr, max_addr,
+                                                        num_nodes, num);
+                       goto out;
+               }
+               switch (*(cmdline - 1)) {
+               case '*':
+                       /* Split remaining nodes into coeff chunks */
+                       if (coeff <= 0)
                                break;
-                       end += FAKE_NODE_MIN_SIZE;
+                       num_nodes += split_nodes_equally(nodes, &addr, max_addr,
+                                                        num_nodes, coeff);
+                       break;
+               case ',':
+                       /* Do not allocate remaining system RAM */
+                       break;
+               default:
+                       /* Give one final node */
+                       setup_node_range(num_nodes, nodes, &addr,
+                                        max_addr - addr, max_addr);
+                       num_nodes++;
                }
-               if (end > max_addr)
-                       end = max_addr;
-               nodes[i].end = end;
-               printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n",
-                      i,
-                      nodes[i].start, nodes[i].end,
-                      (nodes[i].end - nodes[i].start) >> 20);
-               node_set_online(i);
-       }
-       memnode_shift = compute_hash_shift(nodes, numa_fake);
-       if (memnode_shift < 0) {
-               memnode_shift = 0;
-               printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
-               return -1;
-       }
-       for_each_online_node(i) {
+       }
+out:
+       memnode_shift = compute_hash_shift(nodes, num_nodes);
+       if (memnode_shift < 0) {
+               memnode_shift = 0;
+               printk(KERN_ERR "No NUMA hash function found.  NUMA emulation "
+                      "disabled.\n");
+               return -1;
+       }
+
+       /*
+        * We need to vacate all active ranges that may have been registered by
+        * SRAT.
+        */
+       remove_all_active_ranges();
+       for_each_node_mask(i, node_possible_map) {
                e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
                                                nodes[i].end >> PAGE_SHIFT);
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
@@ -399,26 +487,32 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
        numa_init_array();
        return 0;
 }
-#endif
+#undef E820_ADDR_HOLE_SIZE
+#endif /* CONFIG_NUMA_EMU */
 
 void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 { 
        int i;
 
+       nodes_clear(node_possible_map);
+
 #ifdef CONFIG_NUMA_EMU
-       if (numa_fake && !numa_emulation(start_pfn, end_pfn))
+       if (cmdline && !numa_emulation(start_pfn, end_pfn))
                return;
+       nodes_clear(node_possible_map);
 #endif
 
 #ifdef CONFIG_ACPI_NUMA
        if (!numa_off && !acpi_scan_nodes(start_pfn << PAGE_SHIFT,
                                          end_pfn << PAGE_SHIFT))
                return;
+       nodes_clear(node_possible_map);
 #endif
 
 #ifdef CONFIG_K8_NUMA
        if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT))
                return;
+       nodes_clear(node_possible_map);
 #endif
        printk(KERN_INFO "%s\n",
               numa_off ? "NUMA turned off" : "No NUMA configuration found");
@@ -432,6 +526,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
        memnodemap[0] = 0;
        nodes_clear(node_online_map);
        node_set_online(0);
+       node_set(0, node_possible_map);
        for (i = 0; i < NR_CPUS; i++)
                numa_set_node(i, 0);
        node_to_cpumask[0] = cpumask_of_cpu(0);
@@ -486,11 +581,8 @@ static __init int numa_setup(char *opt)
        if (!strncmp(opt,"off",3))
                numa_off = 1;
 #ifdef CONFIG_NUMA_EMU
-       if(!strncmp(opt, "fake=", 5)) {
-               numa_fake = simple_strtoul(opt+5,NULL,0); ;
-               if (numa_fake >= MAX_NUMNODES)
-                       numa_fake = MAX_NUMNODES;
-       }
+       if (!strncmp(opt, "fake=", 5))
+               cmdline = opt + 5;
 #endif
 #ifdef CONFIG_ACPI_NUMA
        if (!strncmp(opt,"noacpi",6))
index 081409a..bf4aa8d 100644 (file)
@@ -51,7 +51,6 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
        SetPagePrivate(base);
        page_private(base) = 0;
 
-       address = __pa(address);
        addr = address & LARGE_PAGE_MASK; 
        pbase = (pte_t *)page_address(base);
        for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
@@ -101,13 +100,12 @@ static inline void save_page(struct page *fpage)
  * No more special protections in this 2/4MB area - revert to a
  * large page again. 
  */
-static void revert_page(unsigned long address, pgprot_t ref_prot)
+static void revert_page(unsigned long address, unsigned long pfn, pgprot_t ref_prot)
 {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t large_pte;
-       unsigned long pfn;
 
        pgd = pgd_offset_k(address);
        BUG_ON(pgd_none(*pgd));
@@ -115,7 +113,6 @@ static void revert_page(unsigned long address, pgprot_t ref_prot)
        BUG_ON(pud_none(*pud));
        pmd = pmd_offset(pud, address);
        BUG_ON(pmd_val(*pmd) & _PAGE_PSE);
-       pfn = (__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT;
        large_pte = pfn_pte(pfn, ref_prot);
        large_pte = pte_mkhuge(large_pte);
        set_pte((pte_t *)pmd, large_pte);
@@ -141,7 +138,8 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
                         */
                        struct page *split;
                        ref_prot2 = pte_pgprot(pte_clrhuge(*kpte));
-                       split = split_large_page(address, prot, ref_prot2);
+                       split = split_large_page(pfn << PAGE_SHIFT, prot,
+                                                       ref_prot2);
                        if (!split)
                                return -ENOMEM;
                        set_pte(kpte, mk_pte(split, ref_prot2));
@@ -160,7 +158,7 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
 
        if (page_private(kpte_page) == 0) {
                save_page(kpte_page);
-               revert_page(address, ref_prot);
+               revert_page(address, pfn, ref_prot);
        }
        return 0;
 } 
@@ -180,22 +178,32 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
  */
 int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
 {
-       int err = 0; 
+       unsigned long phys_base_pfn = __pa_symbol(__START_KERNEL_map) >> PAGE_SHIFT;
+       int err = 0, kernel_map = 0;
        int i; 
 
+       if (address >= __START_KERNEL_map
+           && address < __START_KERNEL_map + KERNEL_TEXT_SIZE) {
+               address = (unsigned long)__va(__pa(address));
+               kernel_map = 1;
+       }
+
        down_write(&init_mm.mmap_sem);
        for (i = 0; i < numpages; i++, address += PAGE_SIZE) {
                unsigned long pfn = __pa(address) >> PAGE_SHIFT;
 
-               err = __change_page_attr(address, pfn, prot, PAGE_KERNEL);
-               if (err) 
-                       break; 
+               if (!kernel_map || pte_present(pfn_pte(0, prot))) {
+                       err = __change_page_attr(address, pfn, prot, PAGE_KERNEL);
+                       if (err)
+                               break;
+               }
                /* Handle kernel mapping too which aliases part of the
                 * lowmem */
-               if (__pa(address) < KERNEL_TEXT_SIZE) {
+               if ((pfn >= phys_base_pfn) &&
+                       ((pfn - phys_base_pfn) < (KERNEL_TEXT_SIZE >> PAGE_SHIFT))) {
                        unsigned long addr2;
                        pgprot_t prot2;
-                       addr2 = __START_KERNEL_map + __pa(address);
+                       addr2 = __START_KERNEL_map + ((pfn - phys_base_pfn) << PAGE_SHIFT);
                        /* Make sure the kernel mappings stay executable */
                        prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
                        err = __change_page_attr(addr2, pfn, prot2,
index 2efe215..1e76bb0 100644 (file)
@@ -419,19 +419,21 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
                return -1;
        }
 
+       node_possible_map = nodes_parsed;
+
        /* Finally register nodes */
-       for_each_node_mask(i, nodes_parsed)
+       for_each_node_mask(i, node_possible_map)
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
        /* Try again in case setup_node_bootmem missed one due
           to missing bootmem */
-       for_each_node_mask(i, nodes_parsed)
+       for_each_node_mask(i, node_possible_map)
                if (!node_online(i))
                        setup_node_bootmem(i, nodes[i].start, nodes[i].end);
 
        for (i = 0; i < NR_CPUS; i++) {
                if (cpu_to_node[i] == NUMA_NO_NODE)
                        continue;
-               if (!node_isset(cpu_to_node[i], nodes_parsed))
+               if (!node_isset(cpu_to_node[i], node_possible_map))
                        numa_set_node(i, NUMA_NO_NODE);
        }
        numa_init_array();
index ab63700..4fbd66a 100644 (file)
@@ -198,7 +198,7 @@ SECTIONS
   __ftr_fixup : { *(__ftr_fixup) }
   __stop___ftr_fixup = .;
 
-  . = ALIGN(32);
+  . = ALIGN(4096);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
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 ae0654c..ee5759b 100644 (file)
@@ -475,7 +475,7 @@ static void acpi_processor_idle(void)
 
 #ifdef CONFIG_GENERIC_TIME
                /* TSC halts in C2, so notify users */
-               mark_tsc_unstable();
+               mark_tsc_unstable("possible TSC halt in C2");
 #endif
                /* Re-enable interrupts */
                local_irq_enable();
@@ -517,7 +517,7 @@ static void acpi_processor_idle(void)
 
 #ifdef CONFIG_GENERIC_TIME
                /* TSC halts in C3, so notify users */
-               mark_tsc_unstable();
+               mark_tsc_unstable("TSC halts in C3");
 #endif
                /* Re-enable interrupts */
                local_irq_enable();
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 365c306..45dbdc1 100644 (file)
@@ -550,13 +550,21 @@ config PATA_WINBOND_VLB
 
 config PATA_PLATFORM
        tristate "Generic platform device PATA support"
-       depends on EMBEDDED
+       depends on EMBEDDED || ARCH_RPC
        help
          This option enables support for generic directly connected ATA
          devices commonly found on embedded systems.
 
          If unsure, say N.
 
+config PATA_ICSIDE
+       tristate "Acorn ICS PATA support"
+       depends on ARM && ARCH_ACORN
+       help
+         On Acorn systems, say Y here if you wish to use the ICS PATA
+         interface card.  This is not required for ICS partition support.
+         If you are unsure, say N to this.
+
 config PATA_IXP4XX_CF
        tristate "IXP4XX Compact Flash support"
        depends on ARCH_IXP4XX
index b7055e3..6f42a0e 100644 (file)
@@ -62,6 +62,7 @@ obj-$(CONFIG_PATA_TRIFLEX)    += pata_triflex.o
 obj-$(CONFIG_PATA_IXP4XX_CF)   += pata_ixp4xx_cf.o
 obj-$(CONFIG_PATA_SCC)         += pata_scc.o
 obj-$(CONFIG_PATA_PLATFORM)    += pata_platform.o
+obj-$(CONFIG_PATA_ICSIDE)      += pata_icside.o
 # Should be last but one libata driver
 obj-$(CONFIG_ATA_GENERIC)      += ata_generic.o
 # Should be last libata driver
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
new file mode 100644 (file)
index 0000000..dbc8ee2
--- /dev/null
@@ -0,0 +1,686 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
+#include <linux/ata.h>
+#include <linux/libata.h>
+
+#include <asm/dma.h>
+#include <asm/ecard.h>
+
+#define DRV_NAME       "pata_icside"
+
+#define ICS_IDENT_OFFSET               0x2280
+
+#define ICS_ARCIN_V5_INTRSTAT          0x0000
+#define ICS_ARCIN_V5_INTROFFSET                0x0004
+
+#define ICS_ARCIN_V6_INTROFFSET_1      0x2200
+#define ICS_ARCIN_V6_INTRSTAT_1                0x2290
+#define ICS_ARCIN_V6_INTROFFSET_2      0x3200
+#define ICS_ARCIN_V6_INTRSTAT_2                0x3290
+
+struct portinfo {
+       unsigned int dataoffset;
+       unsigned int ctrloffset;
+       unsigned int stepping;
+};
+
+static const struct portinfo pata_icside_portinfo_v5 = {
+       .dataoffset     = 0x2800,
+       .ctrloffset     = 0x2b80,
+       .stepping       = 6,
+};
+
+static const struct portinfo pata_icside_portinfo_v6_1 = {
+       .dataoffset     = 0x2000,
+       .ctrloffset     = 0x2380,
+       .stepping       = 6,
+};
+
+static const struct portinfo pata_icside_portinfo_v6_2 = {
+       .dataoffset     = 0x3000,
+       .ctrloffset     = 0x3380,
+       .stepping       = 6,
+};
+
+#define PATA_ICSIDE_MAX_SG     128
+
+struct pata_icside_state {
+       void __iomem *irq_port;
+       void __iomem *ioc_base;
+       unsigned int type;
+       unsigned int dma;
+       struct {
+               u8 port_sel;
+               u8 disabled;
+               unsigned int speed[ATA_MAX_DEVICES];
+       } port[2];
+       struct scatterlist sg[PATA_ICSIDE_MAX_SG];
+};
+
+#define ICS_TYPE_A3IN  0
+#define ICS_TYPE_A3USER        1
+#define ICS_TYPE_V6    3
+#define ICS_TYPE_V5    15
+#define ICS_TYPE_NOTYPE        ((unsigned int)-1)
+
+/* ---------------- Version 5 PCB Support Functions --------------------- */
+/* Prototype: pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
+ * Purpose  : enable interrupts from card
+ */
+static void pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
+{
+       struct pata_icside_state *state = ec->irq_data;
+
+       writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
+}
+
+/* Prototype: pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
+ * Purpose  : disable interrupts from card
+ */
+static void pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
+{
+       struct pata_icside_state *state = ec->irq_data;
+
+       readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
+}
+
+static const expansioncard_ops_t pata_icside_ops_arcin_v5 = {
+       .irqenable      = pata_icside_irqenable_arcin_v5,
+       .irqdisable     = pata_icside_irqdisable_arcin_v5,
+};
+
+
+/* ---------------- Version 6 PCB Support Functions --------------------- */
+/* Prototype: pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
+ * Purpose  : enable interrupts from card
+ */
+static void pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
+{
+       struct pata_icside_state *state = ec->irq_data;
+       void __iomem *base = state->irq_port;
+
+       if (!state->port[0].disabled)
+               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
+       if (!state->port[1].disabled)
+               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
+}
+
+/* Prototype: pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
+ * Purpose  : disable interrupts from card
+ */
+static void pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
+{
+       struct pata_icside_state *state = ec->irq_data;
+
+       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+}
+
+/* Prototype: pata_icside_irqprobe(struct expansion_card *ec)
+ * Purpose  : detect an active interrupt from card
+ */
+static int pata_icside_irqpending_arcin_v6(struct expansion_card *ec)
+{
+       struct pata_icside_state *state = ec->irq_data;
+
+       return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
+              readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
+}
+
+static const expansioncard_ops_t pata_icside_ops_arcin_v6 = {
+       .irqenable      = pata_icside_irqenable_arcin_v6,
+       .irqdisable     = pata_icside_irqdisable_arcin_v6,
+       .irqpending     = pata_icside_irqpending_arcin_v6,
+};
+
+
+/*
+ * SG-DMA support.
+ *
+ * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
+ * There is only one DMA controller per card, which means that only
+ * one drive can be accessed at one time.  NOTE! We do not enforce that
+ * here, but we rely on the main IDE driver spotting that both
+ * interfaces use the same IRQ, which should guarantee this.
+ */
+
+/*
+ * Configure the IOMD to give the appropriate timings for the transfer
+ * mode being requested.  We take the advice of the ATA standards, and
+ * calculate the cycle time based on the transfer mode, and the EIDE
+ * MW DMA specs that the drive provides in the IDENTIFY command.
+ *
+ * We have the following IOMD DMA modes to choose from:
+ *
+ *     Type    Active          Recovery        Cycle
+ *     A       250 (250)       312 (550)       562 (800)
+ *     B       187 (200)       250 (550)       437 (750)
+ *     C       125 (125)       125 (375)       250 (500)
+ *     D       62  (50)        125 (375)       187 (425)
+ *
+ * (figures in brackets are actual measured timings on DIOR/DIOW)
+ *
+ * However, we also need to take care of the read/write active and
+ * recovery timings:
+ *
+ *                     Read    Write
+ *     Mode    Active  -- Recovery --  Cycle   IOMD type
+ *     MW0     215     50      215     480     A
+ *     MW1     80      50      50      150     C
+ *     MW2     70      25      25      120     C
+ */
+static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+       struct pata_icside_state *state = ap->host->private_data;
+       struct ata_timing t;
+       unsigned int cycle;
+       char iomd_type;
+
+       /*
+        * DMA is based on a 16MHz clock
+        */
+       if (ata_timing_compute(adev, adev->dma_mode, &t, 1000, 1))
+               return;
+
+       /*
+        * Choose the IOMD cycle timing which ensure that the interface
+        * satisfies the measured active, recovery and cycle times.
+        */
+       if (t.active <= 50 && t.recover <= 375 && t.cycle <= 425)
+               iomd_type = 'D', cycle = 187;
+       else if (t.active <= 125 && t.recover <= 375 && t.cycle <= 500)
+               iomd_type = 'C', cycle = 250;
+       else if (t.active <= 200 && t.recover <= 550 && t.cycle <= 750)
+               iomd_type = 'B', cycle = 437;
+       else
+               iomd_type = 'A', cycle = 562;
+
+       ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n",
+               t.active, t.recover, t.cycle, iomd_type);
+
+       state->port[ap->port_no].speed[adev->devno] = cycle;
+}
+
+static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pata_icside_state *state = ap->host->private_data;
+       struct scatterlist *sg, *rsg = state->sg;
+       unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
+
+       /*
+        * We are simplex; BUG if we try to fiddle with DMA
+        * while it's active.
+        */
+       BUG_ON(dma_channel_active(state->dma));
+
+       /*
+        * Copy ATAs scattered sg list into a contiguous array of sg
+        */
+       ata_for_each_sg(sg, qc) {
+               memcpy(rsg, sg, sizeof(*sg));
+               rsg++;
+       }
+
+       /*
+        * Route the DMA signals to the correct interface
+        */
+       writeb(state->port[ap->port_no].port_sel, state->ioc_base);
+
+       set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]);
+       set_dma_sg(state->dma, state->sg, rsg - state->sg);
+       set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
+
+       /* issue r/w command */
+       ap->ops->exec_command(ap, &qc->tf);
+}
+
+static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pata_icside_state *state = ap->host->private_data;
+
+       BUG_ON(dma_channel_active(state->dma));
+       enable_dma(state->dma);
+}
+
+static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pata_icside_state *state = ap->host->private_data;
+
+       disable_dma(state->dma);
+
+       /* see ata_bmdma_stop */
+       ata_altstatus(ap);
+}
+
+static u8 pata_icside_bmdma_status(struct ata_port *ap)
+{
+       struct pata_icside_state *state = ap->host->private_data;
+       void __iomem *irq_port;
+
+       irq_port = state->irq_port + (ap->port_no ? ICS_ARCIN_V6_INTRSTAT_2 :
+                                                   ICS_ARCIN_V6_INTRSTAT_1);
+
+       return readb(irq_port) & 1 ? ATA_DMA_INTR : 0;
+}
+
+static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
+{
+       struct pata_icside_state *state = ae->private_data;
+       int i;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               state->port[0].speed[i] = 480;
+               state->port[1].speed[i] = 480;
+       }
+
+       if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
+               state->dma = ec->dma;
+               ae->mwdma_mask = 0x07;  /* MW0..2 */
+       }
+
+       return 0;
+}
+
+
+static int pata_icside_port_start(struct ata_port *ap)
+{
+       /* No PRD to alloc */
+       return ata_pad_alloc(ap, ap->dev);
+}
+
+static struct scsi_host_template pata_icside_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = PATA_ICSIDE_MAX_SG,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ~0, /* no dma boundaries */
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+/* wish this was exported from libata-core */
+static void ata_dummy_noret(struct ata_port *port)
+{
+}
+
+/*
+ * We need to shut down unused ports to prevent spurious interrupts.
+ * FIXME: the libata core doesn't call this function for PATA interfaces.
+ */
+static void pata_icside_port_disable(struct ata_port *ap)
+{
+       struct pata_icside_state *state = ap->host->private_data;
+
+       ata_port_printk(ap, KERN_ERR, "disabling icside port\n");
+
+       ata_port_disable(ap);
+
+       state->port[ap->port_no].disabled = 1;
+
+       if (state->type == ICS_TYPE_V6) {
+               /*
+                * Disable interrupts from this port, otherwise we
+                * receive spurious interrupts from the floating
+                * interrupt line.
+                */
+               void __iomem *irq_port = state->irq_port +
+                               (ap->port_no ? ICS_ARCIN_V6_INTROFFSET_2 : ICS_ARCIN_V6_INTROFFSET_1);
+               readb(irq_port);
+       }
+}
+
+static u8 pata_icside_irq_ack(struct ata_port *ap, unsigned int chk_drq)
+{
+       unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
+       u8 status;
+
+       status = ata_busy_wait(ap, bits, 1000);
+       if (status & bits)
+               if (ata_msg_err(ap))
+                       printk(KERN_ERR "abnormal status 0x%X\n", status);
+
+       if (ata_msg_intr(ap))
+               printk(KERN_INFO "%s: irq ack: drv_stat 0x%X\n",
+                       __FUNCTION__, status);
+
+       return status;
+}
+
+static struct ata_port_operations pata_icside_port_ops = {
+       .port_disable           = pata_icside_port_disable,
+
+       .set_dmamode            = pata_icside_set_dmamode,
+
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .exec_command           = ata_exec_command,
+       .check_status           = ata_check_status,
+       .dev_select             = ata_std_dev_select,
+
+       .bmdma_setup            = pata_icside_bmdma_setup,
+       .bmdma_start            = pata_icside_bmdma_start,
+
+       .data_xfer              = ata_data_xfer_noirq,
+
+       /* no need to build any PRD tables for DMA */
+       .qc_prep                = ata_noop_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = pata_icside_bmdma_stop,
+
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_dummy_noret,
+       .irq_on                 = ata_irq_on,
+       .irq_ack                = pata_icside_irq_ack,
+
+       .port_start             = pata_icside_port_start,
+
+       .bmdma_stop             = pata_icside_bmdma_stop,
+       .bmdma_status           = pata_icside_bmdma_status,
+};
+
+static void
+pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base,
+                    const struct portinfo *info)
+{
+       struct ata_ioports *ioaddr = &ae->port[ae->n_ports++];
+       void __iomem *cmd = base + info->dataoffset;
+
+       ioaddr->cmd_addr        = cmd;
+       ioaddr->data_addr       = cmd + (ATA_REG_DATA    << info->stepping);
+       ioaddr->error_addr      = cmd + (ATA_REG_ERR     << info->stepping);
+       ioaddr->feature_addr    = cmd + (ATA_REG_FEATURE << info->stepping);
+       ioaddr->nsect_addr      = cmd + (ATA_REG_NSECT   << info->stepping);
+       ioaddr->lbal_addr       = cmd + (ATA_REG_LBAL    << info->stepping);
+       ioaddr->lbam_addr       = cmd + (ATA_REG_LBAM    << info->stepping);
+       ioaddr->lbah_addr       = cmd + (ATA_REG_LBAH    << info->stepping);
+       ioaddr->device_addr     = cmd + (ATA_REG_DEVICE  << info->stepping);
+       ioaddr->status_addr     = cmd + (ATA_REG_STATUS  << info->stepping);
+       ioaddr->command_addr    = cmd + (ATA_REG_CMD     << info->stepping);
+
+       ioaddr->ctl_addr        = base + info->ctrloffset;
+       ioaddr->altstatus_addr  = ioaddr->ctl_addr;
+}
+
+static int __init
+pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec)
+{
+       struct pata_icside_state *state = ae->private_data;
+       void __iomem *base;
+
+       base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
+                      ecard_resource_len(ec, ECARD_RES_MEMC));
+       if (!base)
+               return -ENOMEM;
+
+       state->irq_port = base;
+
+       ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
+       ec->irqmask = 1;
+       ec->irq_data = state;
+       ec->ops = &pata_icside_ops_arcin_v5;
+
+       /*
+        * Be on the safe side - disable interrupts
+        */
+       ec->ops->irqdisable(ec, ec->irq);
+
+       pata_icside_add_port(ae, base, &pata_icside_portinfo_v5);
+
+       return 0;
+}
+
+static int __init
+pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
+{
+       struct pata_icside_state *state = ae->private_data;
+       void __iomem *ioc_base, *easi_base;
+       unsigned int sel = 0;
+       int ret;
+
+       ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+                          ecard_resource_len(ec, ECARD_RES_IOCFAST));
+       if (!ioc_base) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       easi_base = ioc_base;
+
+       if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
+               easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
+                                   ecard_resource_len(ec, ECARD_RES_EASI));
+               if (!easi_base) {
+                       ret = -ENOMEM;
+                       goto unmap_slot;
+               }
+
+               /*
+                * Enable access to the EASI region.
+                */
+               sel = 1 << 5;
+       }
+
+       writeb(sel, ioc_base);
+
+       ec->irq_data = state;
+       ec->ops = &pata_icside_ops_arcin_v6;
+
+       state->irq_port = easi_base;
+       state->ioc_base = ioc_base;
+       state->port[0].port_sel = sel;
+       state->port[1].port_sel = sel | 1;
+
+       /*
+        * Be on the safe side - disable interrupts
+        */
+       ec->ops->irqdisable(ec, ec->irq);
+
+       /*
+        * Find and register the interfaces.
+        */
+       pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1);
+       pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2);
+
+       /*
+        * FIXME: work around libata's aversion to calling port_disable.
+        * This permanently disables interrupts on port 0 - bad luck if
+        * you have a drive on that port.
+        */
+       state->port[0].disabled = 1;
+
+       return icside_dma_init(ae, ec);
+
+ unmap_slot:
+       iounmap(ioc_base);
+ out:
+       return ret;
+}
+
+static int __devinit
+pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+       struct pata_icside_state *state;
+       struct ata_probe_ent ae;
+       void __iomem *idmem;
+       int ret;
+
+       ret = ecard_request_resources(ec);
+       if (ret)
+               goto out;
+
+       state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL);
+       if (!state) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       state->type = ICS_TYPE_NOTYPE;
+       state->dma = NO_DMA;
+
+       idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+                       ecard_resource_len(ec, ECARD_RES_IOCFAST));
+       if (idmem) {
+               unsigned int type;
+
+               type = readb(idmem + ICS_IDENT_OFFSET) & 1;
+               type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
+               type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
+               type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
+               iounmap(idmem);
+
+               state->type = type;
+       }
+
+       memset(&ae, 0, sizeof(ae));
+       INIT_LIST_HEAD(&ae.node);
+       ae.dev          = &ec->dev;
+       ae.port_ops     = &pata_icside_port_ops;
+       ae.sht          = &pata_icside_sht;
+       ae.pio_mask     = 0x1f;
+       ae.irq          = ec->irq;
+       ae.port_flags   = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+       ae._host_flags  = ATA_HOST_SIMPLEX;
+       ae.private_data = state;
+
+       switch (state->type) {
+       case ICS_TYPE_A3IN:
+               dev_warn(&ec->dev, "A3IN unsupported\n");
+               ret = -ENODEV;
+               break;
+
+       case ICS_TYPE_A3USER:
+               dev_warn(&ec->dev, "A3USER unsupported\n");
+               ret = -ENODEV;
+               break;
+
+       case ICS_TYPE_V5:
+               ret = pata_icside_register_v5(&ae, ec);
+               break;
+
+       case ICS_TYPE_V6:
+               ret = pata_icside_register_v6(&ae, ec);
+               break;
+
+       default:
+               dev_warn(&ec->dev, "unknown interface type\n");
+               ret = -ENODEV;
+               break;
+       }
+
+       if (ret == 0)
+               ret = ata_device_add(&ae) == 0 ? -ENODEV : 0;
+
+       if (ret == 0)
+               goto out;
+
+       kfree(state);
+ release:
+       ecard_release_resources(ec);
+ out:
+       return ret;
+}
+
+static void pata_icside_shutdown(struct expansion_card *ec)
+{
+       struct ata_host *host = ecard_get_drvdata(ec);
+       unsigned long flags;
+
+       /*
+        * Disable interrupts from this card.  We need to do
+        * this before disabling EASI since we may be accessing
+        * this register via that region.
+        */
+       local_irq_save(flags);
+       if (ec->ops)
+               ec->ops->irqdisable(ec, ec->irq);
+       local_irq_restore(flags);
+
+       /*
+        * Reset the ROM pointer so that we can read the ROM
+        * after a soft reboot.  This also disables access to
+        * the IDE taskfile via the EASI region.
+        */
+       if (host) {
+               struct pata_icside_state *state = host->private_data;
+               if (state->ioc_base)
+                       writeb(0, state->ioc_base);
+       }
+}
+
+static void __devexit pata_icside_remove(struct expansion_card *ec)
+{
+       struct ata_host *host = ecard_get_drvdata(ec);
+       struct pata_icside_state *state = host->private_data;
+
+       ata_host_detach(host);
+
+       pata_icside_shutdown(ec);
+
+       /*
+        * don't NULL out the drvdata - devres/libata wants it
+        * to free the ata_host structure.
+        */
+       ec->ops = NULL;
+       ec->irq_data = NULL;
+
+       if (state->dma != NO_DMA)
+               free_dma(state->dma);
+       if (state->ioc_base)
+               iounmap(state->ioc_base);
+       if (state->ioc_base != state->irq_port)
+               iounmap(state->irq_port);
+
+       kfree(state);
+       ecard_release_resources(ec);
+}
+
+static const struct ecard_id pata_icside_ids[] = {
+       { MANU_ICS,  PROD_ICS_IDE  },
+       { MANU_ICS2, PROD_ICS2_IDE },
+       { 0xffff, 0xffff }
+};
+
+static struct ecard_driver pata_icside_driver = {
+       .probe          = pata_icside_probe,
+       .remove         = __devexit_p(pata_icside_remove),
+       .shutdown       = pata_icside_shutdown,
+       .id_table       = pata_icside_ids,
+       .drv = {
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init pata_icside_init(void)
+{
+       return ecard_register_driver(&pata_icside_driver);
+}
+
+static void __exit pata_icside_exit(void)
+{
+       ecard_remove_driver(&pata_icside_driver);
+}
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ICS PATA driver");
+
+module_init(pata_icside_init);
+module_exit(pata_icside_exit);
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 4857204..c9f0f25 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/agp_backend.h>
 #include <linux/mmzone.h>
 #include <asm/page.h>          /* PAGE_SIZE */
+#include <asm/e820.h>
 #include <asm/k8.h>
 #include "agp.h"
 
@@ -259,7 +260,6 @@ static const struct agp_bridge_driver amd_8151_driver = {
 /* Some basic sanity checks for the aperture. */
 static int __devinit aperture_valid(u64 aper, u32 size)
 {
-       u32 pfn, c;
        if (aper == 0) {
                printk(KERN_ERR PFX "No aperture\n");
                return 0;
@@ -272,14 +272,9 @@ static int __devinit aperture_valid(u64 aper, u32 size)
                printk(KERN_ERR PFX "Aperture out of bounds\n");
                return 0;
        }
-       pfn = aper >> PAGE_SHIFT;
-       for (c = 0; c < size/PAGE_SIZE; c++) {
-               if (!pfn_valid(pfn + c))
-                       break;
-               if (!PageReserved(pfn_to_page(pfn + c))) {
-                       printk(KERN_ERR PFX "Aperture pointing to RAM\n");
-                       return 0;
-               }
+       if (e820_any_mapped(aper, aper + size, E820_RAM)) {
+               printk(KERN_ERR PFX "Aperture pointing to RAM\n");
+               return 0;
        }
 
        /* Request the Aperture. This catches cases when someone else
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;
@@ -1619,43 +1625,6 @@ error_out:
        return ret;
 }
 
-/**
- *     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..873544a 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,
@@ -839,9 +852,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 {
        struct pxa_i2c *i2c = &i2c_pxa;
        struct resource *res;
-#ifdef CONFIG_I2C_PXA_SLAVE
        struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
-#endif
        int ret;
        int irq;
 
@@ -889,14 +900,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
                pxa_gpio_mode(GPIO117_I2CSCL_MD);
                pxa_gpio_mode(GPIO118_I2CSDA_MD);
 #endif
-               pxa_set_cken(CKEN14_I2C, 1);
+               pxa_set_cken(CKEN_I2C, 1);
                break;
 #ifdef CONFIG_PXA27x
        case 1:
                local_irq_disable();
                PCFR |= PCFR_PI2CEN;
                local_irq_enable();
-               pxa_set_cken(CKEN15_PWRI2C, 1);
+               pxa_set_cken(CKEN_PWRI2C, 1);
 #endif
        }
 
@@ -911,6 +922,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
        i2c->adap.algo_data = i2c;
        i2c->adap.dev.parent = &dev->dev;
 
+       if (plat) {
+               i2c->adap.class = plat->class;
+       }
+
        ret = i2c_add_adapter(&i2c->adap);
        if (ret < 0) {
                printk(KERN_INFO "I2C: Failed to add bus\n");
@@ -933,11 +948,11 @@ eadapt:
 ereqirq:
        switch (dev->id) {
        case 0:
-               pxa_set_cken(CKEN14_I2C, 0);
+               pxa_set_cken(CKEN_I2C, 0);
                break;
 #ifdef CONFIG_PXA27x
        case 1:
-               pxa_set_cken(CKEN15_PWRI2C, 0);
+               pxa_set_cken(CKEN_PWRI2C, 0);
                local_irq_disable();
                PCFR &= ~PCFR_PI2CEN;
                local_irq_enable();
@@ -960,11 +975,11 @@ static int i2c_pxa_remove(struct platform_device *dev)
        free_irq(i2c->irq, i2c);
        switch (dev->id) {
        case 0:
-               pxa_set_cken(CKEN14_I2C, 0);
+               pxa_set_cken(CKEN_I2C, 0);
                break;
 #ifdef CONFIG_PXA27x
        case 1:
-               pxa_set_cken(CKEN15_PWRI2C, 0);
+               pxa_set_cken(CKEN_PWRI2C, 0);
                local_irq_disable();
                PCFR &= ~PCFR_PI2CEN;
                local_irq_enable();
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,15 +831,13 @@ 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)
 {
        int retval;
 
        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);
@@ -618,7 +846,6 @@ static int __init i2c_init(void)
 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);
 }
 
 /**
@@ -353,40 +377,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 }
 };
 
@@ -388,6 +646,133 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_acer_aspire_1500
        },
+       {
+               .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",
@@ -397,6 +782,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_acer_travelmate_240
        },
+       {
+               .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",
@@ -406,6 +800,51 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_acer_travelmate_240
        },
+       {
+               .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",
@@ -424,6 +863,51 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_wistron_ms2111
        },
+       {
+               .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",
@@ -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",
@@ -822,12 +849,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)
@@ -159,6 +159,28 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
                },
        },
+       {
+               /*
+                * 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 = {
@@ -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)
@@ -767,6 +767,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 0d122bf..41634fd 100644 (file)
 #define UNMAPPED_GVA (~(gpa_t)0)
 
 #define KVM_MAX_VCPUS 1
+#define KVM_ALIAS_SLOTS 4
 #define KVM_MEMORY_SLOTS 4
 #define KVM_NUM_MMU_PAGES 256
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
+#define KVM_MAX_CPUID_ENTRIES 40
 
 #define FX_IMAGE_SIZE 512
 #define FX_IMAGE_ALIGN 16
 #define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN)
 
 #define DE_VECTOR 0
+#define NM_VECTOR 7
 #define DF_VECTOR 8
 #define TS_VECTOR 10
 #define NP_VECTOR 11
@@ -73,6 +76,8 @@
 
 #define IOPL_SHIFT 12
 
+#define KVM_PIO_PAGE_OFFSET 1
+
 /*
  * Address types:
  *
@@ -106,6 +111,7 @@ struct kvm_pte_chain {
  *   bits 4:7 - page table level for this shadow (1-4)
  *   bits 8:9 - page table quadrant for 2-level guests
  *   bit   16 - "metaphysical" - gfn is not a real page (huge page/real mode)
+ *   bits 17:18 - "access" - the user and writable bits of a huge page pde
  */
 union kvm_mmu_page_role {
        unsigned word;
@@ -115,6 +121,7 @@ union kvm_mmu_page_role {
                unsigned quadrant : 2;
                unsigned pad_for_nice_hex_output : 6;
                unsigned metaphysical : 1;
+               unsigned hugepage_access : 2;
        };
 };
 
@@ -133,7 +140,6 @@ struct kvm_mmu_page {
        unsigned long slot_bitmap; /* One bit set per slot which has memory
                                    * in this shadow page.
                                    */
-       int global;              /* Set if all ptes in this page are global */
        int multimapped;         /* More than one parent_pte? */
        int root_count;          /* Currently serving as active root */
        union {
@@ -219,6 +225,34 @@ enum {
        VCPU_SREG_LDTR,
 };
 
+struct kvm_pio_request {
+       unsigned long count;
+       int cur_count;
+       struct page *guest_pages[2];
+       unsigned guest_page_offset;
+       int in;
+       int size;
+       int string;
+       int down;
+       int rep;
+};
+
+struct kvm_stat {
+       u32 pf_fixed;
+       u32 pf_guest;
+       u32 tlb_flush;
+       u32 invlpg;
+
+       u32 exits;
+       u32 io_exits;
+       u32 mmio_exits;
+       u32 signal_exits;
+       u32 irq_window_exits;
+       u32 halt_exits;
+       u32 request_irq_exits;
+       u32 irq_exits;
+};
+
 struct kvm_vcpu {
        struct kvm *kvm;
        union {
@@ -228,6 +262,8 @@ struct kvm_vcpu {
        struct mutex mutex;
        int   cpu;
        int   launched;
+       u64 host_tsc;
+       struct kvm_run *run;
        int interrupt_window_open;
        unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
 #define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long)
@@ -266,6 +302,7 @@ struct kvm_vcpu {
        char fx_buf[FX_BUF_SIZE];
        char *host_fx_image;
        char *guest_fx_image;
+       int fpu_active;
 
        int mmio_needed;
        int mmio_read_completed;
@@ -273,6 +310,14 @@ struct kvm_vcpu {
        int mmio_size;
        unsigned char mmio_data[8];
        gpa_t mmio_phys_addr;
+       gva_t mmio_fault_cr2;
+       struct kvm_pio_request pio;
+       void *pio_data;
+
+       int sigset_active;
+       sigset_t sigset;
+
+       struct kvm_stat stat;
 
        struct {
                int active;
@@ -284,6 +329,15 @@ struct kvm_vcpu {
                        u32 ar;
                } tr, es, ds, fs, gs;
        } rmode;
+
+       int cpuid_nent;
+       struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
+};
+
+struct kvm_mem_alias {
+       gfn_t base_gfn;
+       unsigned long npages;
+       gfn_t target_gfn;
 };
 
 struct kvm_memory_slot {
@@ -296,6 +350,8 @@ struct kvm_memory_slot {
 
 struct kvm {
        spinlock_t lock; /* protects everything except vcpus */
+       int naliases;
+       struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS];
        int nmemslots;
        struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS];
        /*
@@ -312,22 +368,6 @@ struct kvm {
        struct file *filp;
 };
 
-struct kvm_stat {
-       u32 pf_fixed;
-       u32 pf_guest;
-       u32 tlb_flush;
-       u32 invlpg;
-
-       u32 exits;
-       u32 io_exits;
-       u32 mmio_exits;
-       u32 signal_exits;
-       u32 irq_window_exits;
-       u32 halt_exits;
-       u32 request_irq_exits;
-       u32 irq_exits;
-};
-
 struct descriptor_table {
        u16 limit;
        unsigned long base;
@@ -358,10 +398,8 @@ struct kvm_arch_ops {
        void (*set_segment)(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
        void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
-       void (*decache_cr0_cr4_guest_bits)(struct kvm_vcpu *vcpu);
+       void (*decache_cr4_guest_bits)(struct kvm_vcpu *vcpu);
        void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
-       void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu,
-                                     unsigned long cr0);
        void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
        void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
        void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
@@ -391,7 +429,6 @@ struct kvm_arch_ops {
                                unsigned char *hypercall_addr);
 };
 
-extern struct kvm_stat kvm_stat;
 extern struct kvm_arch_ops *kvm_arch_ops;
 
 #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt)
@@ -400,28 +437,29 @@ extern struct kvm_arch_ops *kvm_arch_ops;
 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module);
 void kvm_exit_arch(void);
 
+int kvm_mmu_module_init(void);
+void kvm_mmu_module_exit(void);
+
 void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
 int kvm_mmu_create(struct kvm_vcpu *vcpu);
 int kvm_mmu_setup(struct kvm_vcpu *vcpu);
 
 int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm_vcpu *vcpu, int slot);
+void kvm_mmu_zap_all(struct kvm_vcpu *vcpu);
 
 hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa);
 #define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
 #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
 static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
 hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva);
+struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva);
 
 void kvm_emulator_want_group7_invlpg(void);
 
 extern hpa_t bad_page_address;
 
-static inline struct page *gfn_to_page(struct kvm_memory_slot *slot, gfn_t gfn)
-{
-       return slot->phys_mem[gfn - slot->base_gfn];
-}
-
+struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
 
@@ -444,6 +482,10 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
 
 struct x86_emulate_ctxt;
 
+int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
+                 int size, unsigned long count, int string, int down,
+                 gva_t address, int rep, unsigned port);
+void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
 int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
 int emulate_clts(struct kvm_vcpu *vcpu);
 int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
@@ -493,12 +535,6 @@ static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
        return vcpu->mmu.page_fault(vcpu, gva, error_code);
 }
 
-static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn)
-{
-       struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
-       return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL;
-}
-
 static inline int is_long_mode(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_X86_64
index dc7a8c7..c8b8cfa 100644 (file)
@@ -51,27 +51,27 @@ static DEFINE_SPINLOCK(kvm_lock);
 static LIST_HEAD(vm_list);
 
 struct kvm_arch_ops *kvm_arch_ops;
-struct kvm_stat kvm_stat;
-EXPORT_SYMBOL_GPL(kvm_stat);
+
+#define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x)
 
 static struct kvm_stats_debugfs_item {
        const char *name;
-       u32 *data;
+       int offset;
        struct dentry *dentry;
 } debugfs_entries[] = {
-       { "pf_fixed", &kvm_stat.pf_fixed },
-       { "pf_guest", &kvm_stat.pf_guest },
-       { "tlb_flush", &kvm_stat.tlb_flush },
-       { "invlpg", &kvm_stat.invlpg },
-       { "exits", &kvm_stat.exits },
-       { "io_exits", &kvm_stat.io_exits },
-       { "mmio_exits", &kvm_stat.mmio_exits },
-       { "signal_exits", &kvm_stat.signal_exits },
-       { "irq_window", &kvm_stat.irq_window_exits },
-       { "halt_exits", &kvm_stat.halt_exits },
-       { "request_irq", &kvm_stat.request_irq_exits },
-       { "irq_exits", &kvm_stat.irq_exits },
-       { NULL, NULL }
+       { "pf_fixed", STAT_OFFSET(pf_fixed) },
+       { "pf_guest", STAT_OFFSET(pf_guest) },
+       { "tlb_flush", STAT_OFFSET(tlb_flush) },
+       { "invlpg", STAT_OFFSET(invlpg) },
+       { "exits", STAT_OFFSET(exits) },
+       { "io_exits", STAT_OFFSET(io_exits) },
+       { "mmio_exits", STAT_OFFSET(mmio_exits) },
+       { "signal_exits", STAT_OFFSET(signal_exits) },
+       { "irq_window", STAT_OFFSET(irq_window_exits) },
+       { "halt_exits", STAT_OFFSET(halt_exits) },
+       { "request_irq", STAT_OFFSET(request_irq_exits) },
+       { "irq_exits", STAT_OFFSET(irq_exits) },
+       { NULL }
 };
 
 static struct dentry *debugfs_dir;
@@ -346,6 +346,17 @@ static void kvm_free_physmem(struct kvm *kvm)
                kvm_free_physmem_slot(&kvm->memslots[i], NULL);
 }
 
+static void free_pio_guest_pages(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       for (i = 0; i < 2; ++i)
+               if (vcpu->pio.guest_pages[i]) {
+                       __free_page(vcpu->pio.guest_pages[i]);
+                       vcpu->pio.guest_pages[i] = NULL;
+               }
+}
+
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
        if (!vcpu->vmcs)
@@ -355,6 +366,11 @@ static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
        kvm_mmu_destroy(vcpu);
        vcpu_put(vcpu);
        kvm_arch_ops->vcpu_free(vcpu);
+       free_page((unsigned long)vcpu->run);
+       vcpu->run = NULL;
+       free_page((unsigned long)vcpu->pio_data);
+       vcpu->pio_data = NULL;
+       free_pio_guest_pages(vcpu);
 }
 
 static void kvm_free_vcpus(struct kvm *kvm)
@@ -404,12 +420,12 @@ static int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
        u64 pdpte;
        u64 *pdpt;
        int ret;
-       struct kvm_memory_slot *memslot;
+       struct page *page;
 
        spin_lock(&vcpu->kvm->lock);
-       memslot = gfn_to_memslot(vcpu->kvm, pdpt_gfn);
-       /* FIXME: !memslot - emulate? 0xff? */
-       pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0);
+       page = gfn_to_page(vcpu->kvm, pdpt_gfn);
+       /* FIXME: !page - emulate? 0xff? */
+       pdpt = kmap_atomic(page, KM_USER0);
 
        ret = 1;
        for (i = 0; i < 4; ++i) {
@@ -494,7 +510,6 @@ EXPORT_SYMBOL_GPL(set_cr0);
 
 void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 {
-       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
        set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f));
 }
 EXPORT_SYMBOL_GPL(lmsw);
@@ -830,7 +845,73 @@ out:
        return r;
 }
 
-struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
+/*
+ * Set a new alias region.  Aliases map a portion of physical memory into
+ * another portion.  This is useful for memory windows, for example the PC
+ * VGA region.
+ */
+static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
+                                        struct kvm_memory_alias *alias)
+{
+       int r, n;
+       struct kvm_mem_alias *p;
+
+       r = -EINVAL;
+       /* General sanity checks */
+       if (alias->memory_size & (PAGE_SIZE - 1))
+               goto out;
+       if (alias->guest_phys_addr & (PAGE_SIZE - 1))
+               goto out;
+       if (alias->slot >= KVM_ALIAS_SLOTS)
+               goto out;
+       if (alias->guest_phys_addr + alias->memory_size
+           < alias->guest_phys_addr)
+               goto out;
+       if (alias->target_phys_addr + alias->memory_size
+           < alias->target_phys_addr)
+               goto out;
+
+       spin_lock(&kvm->lock);
+
+       p = &kvm->aliases[alias->slot];
+       p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
+       p->npages = alias->memory_size >> PAGE_SHIFT;
+       p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
+
+       for (n = KVM_ALIAS_SLOTS; n > 0; --n)
+               if (kvm->aliases[n - 1].npages)
+                       break;
+       kvm->naliases = n;
+
+       spin_unlock(&kvm->lock);
+
+       vcpu_load(&kvm->vcpus[0]);
+       spin_lock(&kvm->lock);
+       kvm_mmu_zap_all(&kvm->vcpus[0]);
+       spin_unlock(&kvm->lock);
+       vcpu_put(&kvm->vcpus[0]);
+
+       return 0;
+
+out:
+       return r;
+}
+
+static gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+       int i;
+       struct kvm_mem_alias *alias;
+
+       for (i = 0; i < kvm->naliases; ++i) {
+               alias = &kvm->aliases[i];
+               if (gfn >= alias->base_gfn
+                   && gfn < alias->base_gfn + alias->npages)
+                       return alias->target_gfn + gfn - alias->base_gfn;
+       }
+       return gfn;
+}
+
+static struct kvm_memory_slot *__gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
 {
        int i;
 
@@ -843,7 +924,24 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
        }
        return NULL;
 }
-EXPORT_SYMBOL_GPL(gfn_to_memslot);
+
+struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
+{
+       gfn = unalias_gfn(kvm, gfn);
+       return __gfn_to_memslot(kvm, gfn);
+}
+
+struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
+{
+       struct kvm_memory_slot *slot;
+
+       gfn = unalias_gfn(kvm, gfn);
+       slot = __gfn_to_memslot(kvm, gfn);
+       if (!slot)
+               return NULL;
+       return slot->phys_mem[gfn - slot->base_gfn];
+}
+EXPORT_SYMBOL_GPL(gfn_to_page);
 
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
 {
@@ -871,7 +969,7 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
 }
 
 static int emulator_read_std(unsigned long addr,
-                            unsigned long *val,
+                            void *val,
                             unsigned int bytes,
                             struct x86_emulate_ctxt *ctxt)
 {
@@ -883,20 +981,20 @@ static int emulator_read_std(unsigned long addr,
                unsigned offset = addr & (PAGE_SIZE-1);
                unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset);
                unsigned long pfn;
-               struct kvm_memory_slot *memslot;
-               void *page;
+               struct page *page;
+               void *page_virt;
 
                if (gpa == UNMAPPED_GVA)
                        return X86EMUL_PROPAGATE_FAULT;
                pfn = gpa >> PAGE_SHIFT;
-               memslot = gfn_to_memslot(vcpu->kvm, pfn);
-               if (!memslot)
+               page = gfn_to_page(vcpu->kvm, pfn);
+               if (!page)
                        return X86EMUL_UNHANDLEABLE;
-               page = kmap_atomic(gfn_to_page(memslot, pfn), KM_USER0);
+               page_virt = kmap_atomic(page, KM_USER0);
 
-               memcpy(data, page + offset, tocopy);
+               memcpy(data, page_virt + offset, tocopy);
 
-               kunmap_atomic(page, KM_USER0);
+               kunmap_atomic(page_virt, KM_USER0);
 
                bytes -= tocopy;
                data += tocopy;
@@ -907,7 +1005,7 @@ static int emulator_read_std(unsigned long addr,
 }
 
 static int emulator_write_std(unsigned long addr,
-                             unsigned long val,
+                             const void *val,
                              unsigned int bytes,
                              struct x86_emulate_ctxt *ctxt)
 {
@@ -917,7 +1015,7 @@ static int emulator_write_std(unsigned long addr,
 }
 
 static int emulator_read_emulated(unsigned long addr,
-                                 unsigned long *val,
+                                 void *val,
                                  unsigned int bytes,
                                  struct x86_emulate_ctxt *ctxt)
 {
@@ -945,37 +1043,37 @@ static int emulator_read_emulated(unsigned long addr,
 }
 
 static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
-                              unsigned long val, int bytes)
+                              const void *val, int bytes)
 {
-       struct kvm_memory_slot *m;
        struct page *page;
        void *virt;
 
        if (((gpa + bytes - 1) >> PAGE_SHIFT) != (gpa >> PAGE_SHIFT))
                return 0;
-       m = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
-       if (!m)
+       page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
+       if (!page)
                return 0;
-       page = gfn_to_page(m, gpa >> PAGE_SHIFT);
        kvm_mmu_pre_write(vcpu, gpa, bytes);
        mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT);
        virt = kmap_atomic(page, KM_USER0);
-       memcpy(virt + offset_in_page(gpa), &val, bytes);
+       memcpy(virt + offset_in_page(gpa), val, bytes);
        kunmap_atomic(virt, KM_USER0);
        kvm_mmu_post_write(vcpu, gpa, bytes);
        return 1;
 }
 
 static int emulator_write_emulated(unsigned long addr,
-                                  unsigned long val,
+                                  const void *val,
                                   unsigned int bytes,
                                   struct x86_emulate_ctxt *ctxt)
 {
        struct kvm_vcpu *vcpu = ctxt->vcpu;
        gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
 
-       if (gpa == UNMAPPED_GVA)
+       if (gpa == UNMAPPED_GVA) {
+               kvm_arch_ops->inject_page_fault(vcpu, addr, 2);
                return X86EMUL_PROPAGATE_FAULT;
+       }
 
        if (emulator_write_phys(vcpu, gpa, val, bytes))
                return X86EMUL_CONTINUE;
@@ -984,14 +1082,14 @@ static int emulator_write_emulated(unsigned long addr,
        vcpu->mmio_phys_addr = gpa;
        vcpu->mmio_size = bytes;
        vcpu->mmio_is_write = 1;
-       memcpy(vcpu->mmio_data, &val, bytes);
+       memcpy(vcpu->mmio_data, val, bytes);
 
        return X86EMUL_CONTINUE;
 }
 
 static int emulator_cmpxchg_emulated(unsigned long addr,
-                                    unsigned long old,
-                                    unsigned long new,
+                                    const void *old,
+                                    const void *new,
                                     unsigned int bytes,
                                     struct x86_emulate_ctxt *ctxt)
 {
@@ -1004,30 +1102,6 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
        return emulator_write_emulated(addr, new, bytes, ctxt);
 }
 
-#ifdef CONFIG_X86_32
-
-static int emulator_cmpxchg8b_emulated(unsigned long addr,
-                                      unsigned long old_lo,
-                                      unsigned long old_hi,
-                                      unsigned long new_lo,
-                                      unsigned long new_hi,
-                                      struct x86_emulate_ctxt *ctxt)
-{
-       static int reported;
-       int r;
-
-       if (!reported) {
-               reported = 1;
-               printk(KERN_WARNING "kvm: emulating exchange8b as write\n");
-       }
-       r = emulator_write_emulated(addr, new_lo, 4, ctxt);
-       if (r != X86EMUL_CONTINUE)
-               return r;
-       return emulator_write_emulated(addr+4, new_hi, 4, ctxt);
-}
-
-#endif
-
 static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
 {
        return kvm_arch_ops->get_segment_base(vcpu, seg);
@@ -1042,7 +1116,6 @@ int emulate_clts(struct kvm_vcpu *vcpu)
 {
        unsigned long cr0;
 
-       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
        cr0 = vcpu->cr0 & ~CR0_TS_MASK;
        kvm_arch_ops->set_cr0(vcpu, cr0);
        return X86EMUL_CONTINUE;
@@ -1102,9 +1175,6 @@ struct x86_emulate_ops emulate_ops = {
        .read_emulated       = emulator_read_emulated,
        .write_emulated      = emulator_write_emulated,
        .cmpxchg_emulated    = emulator_cmpxchg_emulated,
-#ifdef CONFIG_X86_32
-       .cmpxchg8b_emulated  = emulator_cmpxchg8b_emulated,
-#endif
 };
 
 int emulate_instruction(struct kvm_vcpu *vcpu,
@@ -1116,6 +1186,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
        int r;
        int cs_db, cs_l;
 
+       vcpu->mmio_fault_cr2 = cr2;
        kvm_arch_ops->cache_regs(vcpu);
 
        kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
@@ -1166,8 +1237,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
        kvm_arch_ops->decache_regs(vcpu);
        kvm_arch_ops->set_rflags(vcpu, emulate_ctxt.eflags);
 
-       if (vcpu->mmio_is_write)
+       if (vcpu->mmio_is_write) {
+               vcpu->mmio_needed = 0;
                return EMULATE_DO_MMIO;
+       }
 
        return EMULATE_DONE;
 }
@@ -1177,7 +1250,7 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
        unsigned long nr, a0, a1, a2, a3, a4, a5, ret;
 
-       kvm_arch_ops->decache_regs(vcpu);
+       kvm_arch_ops->cache_regs(vcpu);
        ret = -KVM_EINVAL;
 #ifdef CONFIG_X86_64
        if (is_long_mode(vcpu)) {
@@ -1201,10 +1274,19 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run)
        }
        switch (nr) {
        default:
-               ;
+               run->hypercall.args[0] = a0;
+               run->hypercall.args[1] = a1;
+               run->hypercall.args[2] = a2;
+               run->hypercall.args[3] = a3;
+               run->hypercall.args[4] = a4;
+               run->hypercall.args[5] = a5;
+               run->hypercall.ret = ret;
+               run->hypercall.longmode = is_long_mode(vcpu);
+               kvm_arch_ops->decache_regs(vcpu);
+               return 0;
        }
        vcpu->regs[VCPU_REGS_RAX] = ret;
-       kvm_arch_ops->cache_regs(vcpu);
+       kvm_arch_ops->decache_regs(vcpu);
        return 1;
 }
 EXPORT_SYMBOL_GPL(kvm_hypercall);
@@ -1237,7 +1319,7 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
 
 unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
 {
-       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+       kvm_arch_ops->decache_cr4_guest_bits(vcpu);
        switch (cr) {
        case 0:
                return vcpu->cr0;
@@ -1442,6 +1524,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n",
                       __FUNCTION__, data);
                break;
+       case MSR_IA32_MCG_STATUS:
+               printk(KERN_WARNING "%s: MSR_IA32_MCG_STATUS 0x%llx, nop\n",
+                       __FUNCTION__, data);
+               break;
        case MSR_IA32_UCODE_REV:
        case MSR_IA32_UCODE_WRITE:
        case 0x200 ... 0x2ff: /* MTRRs */
@@ -1478,6 +1564,8 @@ static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
 
 void kvm_resched(struct kvm_vcpu *vcpu)
 {
+       if (!need_resched())
+               return;
        vcpu_put(vcpu);
        cond_resched();
        vcpu_load(vcpu);
@@ -1502,29 +1590,250 @@ void save_msrs(struct vmx_msr_entry *e, int n)
 }
 EXPORT_SYMBOL_GPL(save_msrs);
 
+void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
+{
+       int i;
+       u32 function;
+       struct kvm_cpuid_entry *e, *best;
+
+       kvm_arch_ops->cache_regs(vcpu);
+       function = vcpu->regs[VCPU_REGS_RAX];
+       vcpu->regs[VCPU_REGS_RAX] = 0;
+       vcpu->regs[VCPU_REGS_RBX] = 0;
+       vcpu->regs[VCPU_REGS_RCX] = 0;
+       vcpu->regs[VCPU_REGS_RDX] = 0;
+       best = NULL;
+       for (i = 0; i < vcpu->cpuid_nent; ++i) {
+               e = &vcpu->cpuid_entries[i];
+               if (e->function == function) {
+                       best = e;
+                       break;
+               }
+               /*
+                * Both basic or both extended?
+                */
+               if (((e->function ^ function) & 0x80000000) == 0)
+                       if (!best || e->function > best->function)
+                               best = e;
+       }
+       if (best) {
+               vcpu->regs[VCPU_REGS_RAX] = best->eax;
+               vcpu->regs[VCPU_REGS_RBX] = best->ebx;
+               vcpu->regs[VCPU_REGS_RCX] = best->ecx;
+               vcpu->regs[VCPU_REGS_RDX] = best->edx;
+       }
+       kvm_arch_ops->decache_regs(vcpu);
+       kvm_arch_ops->skip_emulated_instruction(vcpu);
+}
+EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
+
+static int pio_copy_data(struct kvm_vcpu *vcpu)
+{
+       void *p = vcpu->pio_data;
+       void *q;
+       unsigned bytes;
+       int nr_pages = vcpu->pio.guest_pages[1] ? 2 : 1;
+
+       kvm_arch_ops->vcpu_put(vcpu);
+       q = vmap(vcpu->pio.guest_pages, nr_pages, VM_READ|VM_WRITE,
+                PAGE_KERNEL);
+       if (!q) {
+               kvm_arch_ops->vcpu_load(vcpu);
+               free_pio_guest_pages(vcpu);
+               return -ENOMEM;
+       }
+       q += vcpu->pio.guest_page_offset;
+       bytes = vcpu->pio.size * vcpu->pio.cur_count;
+       if (vcpu->pio.in)
+               memcpy(q, p, bytes);
+       else
+               memcpy(p, q, bytes);
+       q -= vcpu->pio.guest_page_offset;
+       vunmap(q);
+       kvm_arch_ops->vcpu_load(vcpu);
+       free_pio_guest_pages(vcpu);
+       return 0;
+}
+
+static int complete_pio(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pio_request *io = &vcpu->pio;
+       long delta;
+       int r;
+
+       kvm_arch_ops->cache_regs(vcpu);
+
+       if (!io->string) {
+               if (io->in)
+                       memcpy(&vcpu->regs[VCPU_REGS_RAX], vcpu->pio_data,
+                              io->size);
+       } else {
+               if (io->in) {
+                       r = pio_copy_data(vcpu);
+                       if (r) {
+                               kvm_arch_ops->cache_regs(vcpu);
+                               return r;
+                       }
+               }
+
+               delta = 1;
+               if (io->rep) {
+                       delta *= io->cur_count;
+                       /*
+                        * The size of the register should really depend on
+                        * current address size.
+                        */
+                       vcpu->regs[VCPU_REGS_RCX] -= delta;
+               }
+               if (io->down)
+                       delta = -delta;
+               delta *= io->size;
+               if (io->in)
+                       vcpu->regs[VCPU_REGS_RDI] += delta;
+               else
+                       vcpu->regs[VCPU_REGS_RSI] += delta;
+       }
+
+       kvm_arch_ops->decache_regs(vcpu);
+
+       io->count -= io->cur_count;
+       io->cur_count = 0;
+
+       if (!io->count)
+               kvm_arch_ops->skip_emulated_instruction(vcpu);
+       return 0;
+}
+
+int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
+                 int size, unsigned long count, int string, int down,
+                 gva_t address, int rep, unsigned port)
+{
+       unsigned now, in_page;
+       int i;
+       int nr_pages = 1;
+       struct page *page;
+
+       vcpu->run->exit_reason = KVM_EXIT_IO;
+       vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
+       vcpu->run->io.size = size;
+       vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE;
+       vcpu->run->io.count = count;
+       vcpu->run->io.port = port;
+       vcpu->pio.count = count;
+       vcpu->pio.cur_count = count;
+       vcpu->pio.size = size;
+       vcpu->pio.in = in;
+       vcpu->pio.string = string;
+       vcpu->pio.down = down;
+       vcpu->pio.guest_page_offset = offset_in_page(address);
+       vcpu->pio.rep = rep;
+
+       if (!string) {
+               kvm_arch_ops->cache_regs(vcpu);
+               memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4);
+               kvm_arch_ops->decache_regs(vcpu);
+               return 0;
+       }
+
+       if (!count) {
+               kvm_arch_ops->skip_emulated_instruction(vcpu);
+               return 1;
+       }
+
+       now = min(count, PAGE_SIZE / size);
+
+       if (!down)
+               in_page = PAGE_SIZE - offset_in_page(address);
+       else
+               in_page = offset_in_page(address) + size;
+       now = min(count, (unsigned long)in_page / size);
+       if (!now) {
+               /*
+                * String I/O straddles page boundary.  Pin two guest pages
+                * so that we satisfy atomicity constraints.  Do just one
+                * transaction to avoid complexity.
+                */
+               nr_pages = 2;
+               now = 1;
+       }
+       if (down) {
+               /*
+                * String I/O in reverse.  Yuck.  Kill the guest, fix later.
+                */
+               printk(KERN_ERR "kvm: guest string pio down\n");
+               inject_gp(vcpu);
+               return 1;
+       }
+       vcpu->run->io.count = now;
+       vcpu->pio.cur_count = now;
+
+       for (i = 0; i < nr_pages; ++i) {
+               spin_lock(&vcpu->kvm->lock);
+               page = gva_to_page(vcpu, address + i * PAGE_SIZE);
+               if (page)
+                       get_page(page);
+               vcpu->pio.guest_pages[i] = page;
+               spin_unlock(&vcpu->kvm->lock);
+               if (!page) {
+                       inject_gp(vcpu);
+                       free_pio_guest_pages(vcpu);
+                       return 1;
+               }
+       }
+
+       if (!vcpu->pio.in)
+               return pio_copy_data(vcpu);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_setup_pio);
+
 static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        int r;
+       sigset_t sigsaved;
 
        vcpu_load(vcpu);
 
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
        /* re-sync apic's tpr */
        vcpu->cr8 = kvm_run->cr8;
 
-       if (kvm_run->emulated) {
-               kvm_arch_ops->skip_emulated_instruction(vcpu);
-               kvm_run->emulated = 0;
+       if (vcpu->pio.cur_count) {
+               r = complete_pio(vcpu);
+               if (r)
+                       goto out;
        }
 
-       if (kvm_run->mmio_completed) {
+       if (vcpu->mmio_needed) {
                memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
                vcpu->mmio_read_completed = 1;
+               vcpu->mmio_needed = 0;
+               r = emulate_instruction(vcpu, kvm_run,
+                                       vcpu->mmio_fault_cr2, 0);
+               if (r == EMULATE_DO_MMIO) {
+                       /*
+                        * Read-modify-write.  Back to userspace.
+                        */
+                       kvm_run->exit_reason = KVM_EXIT_MMIO;
+                       r = 0;
+                       goto out;
+               }
        }
 
-       vcpu->mmio_needed = 0;
+       if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL) {
+               kvm_arch_ops->cache_regs(vcpu);
+               vcpu->regs[VCPU_REGS_RAX] = kvm_run->hypercall.ret;
+               kvm_arch_ops->decache_regs(vcpu);
+       }
 
        r = kvm_arch_ops->run(vcpu, kvm_run);
 
+out:
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
        vcpu_put(vcpu);
        return r;
 }
@@ -1633,7 +1942,7 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
        sregs->gdt.limit = dt.limit;
        sregs->gdt.base = dt.base;
 
-       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+       kvm_arch_ops->decache_cr4_guest_bits(vcpu);
        sregs->cr0 = vcpu->cr0;
        sregs->cr2 = vcpu->cr2;
        sregs->cr3 = vcpu->cr3;
@@ -1665,16 +1974,6 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
        vcpu_load(vcpu);
 
-       set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
-       set_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
-       set_segment(vcpu, &sregs->es, VCPU_SREG_ES);
-       set_segment(vcpu, &sregs->fs, VCPU_SREG_FS);
-       set_segment(vcpu, &sregs->gs, VCPU_SREG_GS);
-       set_segment(vcpu, &sregs->ss, VCPU_SREG_SS);
-
-       set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
-       set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
-
        dt.limit = sregs->idt.limit;
        dt.base = sregs->idt.base;
        kvm_arch_ops->set_idt(vcpu, &dt);
@@ -1694,10 +1993,10 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 #endif
        vcpu->apic_base = sregs->apic_base;
 
-       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+       kvm_arch_ops->decache_cr4_guest_bits(vcpu);
 
        mmu_reset_needed |= vcpu->cr0 != sregs->cr0;
-       kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0);
+       kvm_arch_ops->set_cr0(vcpu, sregs->cr0);
 
        mmu_reset_needed |= vcpu->cr4 != sregs->cr4;
        kvm_arch_ops->set_cr4(vcpu, sregs->cr4);
@@ -1714,6 +2013,16 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                if (vcpu->irq_pending[i])
                        __set_bit(i, &vcpu->irq_summary);
 
+       set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
+       set_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
+       set_segment(vcpu, &sregs->es, VCPU_SREG_ES);
+       set_segment(vcpu, &sregs->fs, VCPU_SREG_FS);
+       set_segment(vcpu, &sregs->gs, VCPU_SREG_GS);
+       set_segment(vcpu, &sregs->ss, VCPU_SREG_SS);
+
+       set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
+       set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
+
        vcpu_put(vcpu);
 
        return 0;
@@ -1887,6 +2196,36 @@ static int kvm_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
        return r;
 }
 
+static struct page *kvm_vcpu_nopage(struct vm_area_struct *vma,
+                                   unsigned long address,
+                                   int *type)
+{
+       struct kvm_vcpu *vcpu = vma->vm_file->private_data;
+       unsigned long pgoff;
+       struct page *page;
+
+       *type = VM_FAULT_MINOR;
+       pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+       if (pgoff == 0)
+               page = virt_to_page(vcpu->run);
+       else if (pgoff == KVM_PIO_PAGE_OFFSET)
+               page = virt_to_page(vcpu->pio_data);
+       else
+               return NOPAGE_SIGBUS;
+       get_page(page);
+       return page;
+}
+
+static struct vm_operations_struct kvm_vcpu_vm_ops = {
+       .nopage = kvm_vcpu_nopage,
+};
+
+static int kvm_vcpu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       vma->vm_ops = &kvm_vcpu_vm_ops;
+       return 0;
+}
+
 static int kvm_vcpu_release(struct inode *inode, struct file *filp)
 {
        struct kvm_vcpu *vcpu = filp->private_data;
@@ -1899,6 +2238,7 @@ static struct file_operations kvm_vcpu_fops = {
        .release        = kvm_vcpu_release,
        .unlocked_ioctl = kvm_vcpu_ioctl,
        .compat_ioctl   = kvm_vcpu_ioctl,
+       .mmap           = kvm_vcpu_mmap,
 };
 
 /*
@@ -1947,6 +2287,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
 {
        int r;
        struct kvm_vcpu *vcpu;
+       struct page *page;
 
        r = -EINVAL;
        if (!valid_vcpu(n))
@@ -1961,9 +2302,22 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
                return -EEXIST;
        }
 
+       page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+       r = -ENOMEM;
+       if (!page)
+               goto out_unlock;
+       vcpu->run = page_address(page);
+
+       page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+       r = -ENOMEM;
+       if (!page)
+               goto out_free_run;
+       vcpu->pio_data = page_address(page);
+
        vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf,
                                           FX_IMAGE_ALIGN);
        vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
+       vcpu->cr0 = 0x10;
 
        r = kvm_arch_ops->vcpu_create(vcpu);
        if (r < 0)
@@ -1990,11 +2344,107 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
 
 out_free_vcpus:
        kvm_free_vcpu(vcpu);
+out_free_run:
+       free_page((unsigned long)vcpu->run);
+       vcpu->run = NULL;
+out_unlock:
        mutex_unlock(&vcpu->mutex);
 out:
        return r;
 }
 
+static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
+                                   struct kvm_cpuid *cpuid,
+                                   struct kvm_cpuid_entry __user *entries)
+{
+       int r;
+
+       r = -E2BIG;
+       if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
+               goto out;
+       r = -EFAULT;
+       if (copy_from_user(&vcpu->cpuid_entries, entries,
+                          cpuid->nent * sizeof(struct kvm_cpuid_entry)))
+               goto out;
+       vcpu->cpuid_nent = cpuid->nent;
+       return 0;
+
+out:
+       return r;
+}
+
+static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
+{
+       if (sigset) {
+               sigdelsetmask(sigset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+               vcpu->sigset_active = 1;
+               vcpu->sigset = *sigset;
+       } else
+               vcpu->sigset_active = 0;
+       return 0;
+}
+
+/*
+ * fxsave fpu state.  Taken from x86_64/processor.h.  To be killed when
+ * we have asm/x86/processor.h
+ */
+struct fxsave {
+       u16     cwd;
+       u16     swd;
+       u16     twd;
+       u16     fop;
+       u64     rip;
+       u64     rdp;
+       u32     mxcsr;
+       u32     mxcsr_mask;
+       u32     st_space[32];   /* 8*16 bytes for each FP-reg = 128 bytes */
+#ifdef CONFIG_X86_64
+       u32     xmm_space[64];  /* 16*16 bytes for each XMM-reg = 256 bytes */
+#else
+       u32     xmm_space[32];  /* 8*16 bytes for each XMM-reg = 128 bytes */
+#endif
+};
+
+static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image;
+
+       vcpu_load(vcpu);
+
+       memcpy(fpu->fpr, fxsave->st_space, 128);
+       fpu->fcw = fxsave->cwd;
+       fpu->fsw = fxsave->swd;
+       fpu->ftwx = fxsave->twd;
+       fpu->last_opcode = fxsave->fop;
+       fpu->last_ip = fxsave->rip;
+       fpu->last_dp = fxsave->rdp;
+       memcpy(fpu->xmm, fxsave->xmm_space, sizeof fxsave->xmm_space);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image;
+
+       vcpu_load(vcpu);
+
+       memcpy(fxsave->st_space, fpu->fpr, 128);
+       fxsave->cwd = fpu->fcw;
+       fxsave->swd = fpu->fsw;
+       fxsave->twd = fpu->ftwx;
+       fxsave->fop = fpu->last_opcode;
+       fxsave->rip = fpu->last_ip;
+       fxsave->rdp = fpu->last_dp;
+       memcpy(fxsave->xmm_space, fpu->xmm, sizeof fxsave->xmm_space);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
 static long kvm_vcpu_ioctl(struct file *filp,
                           unsigned int ioctl, unsigned long arg)
 {
@@ -2003,21 +2453,12 @@ static long kvm_vcpu_ioctl(struct file *filp,
        int r = -EINVAL;
 
        switch (ioctl) {
-       case KVM_RUN: {
-               struct kvm_run kvm_run;
-
-               r = -EFAULT;
-               if (copy_from_user(&kvm_run, argp, sizeof kvm_run))
+       case KVM_RUN:
+               r = -EINVAL;
+               if (arg)
                        goto out;
-               r = kvm_vcpu_ioctl_run(vcpu, &kvm_run);
-               if (r < 0 &&  r != -EINTR)
-                       goto out;
-               if (copy_to_user(argp, &kvm_run, sizeof kvm_run)) {
-                       r = -EFAULT;
-                       goto out;
-               }
+               r = kvm_vcpu_ioctl_run(vcpu, vcpu->run);
                break;
-       }
        case KVM_GET_REGS: {
                struct kvm_regs kvm_regs;
 
@@ -2113,6 +2554,66 @@ static long kvm_vcpu_ioctl(struct file *filp,
        case KVM_SET_MSRS:
                r = msr_io(vcpu, argp, do_set_msr, 0);
                break;
+       case KVM_SET_CPUID: {
+               struct kvm_cpuid __user *cpuid_arg = argp;
+               struct kvm_cpuid cpuid;
+
+               r = -EFAULT;
+               if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
+                       goto out;
+               r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
+               if (r)
+                       goto out;
+               break;
+       }
+       case KVM_SET_SIGNAL_MASK: {
+               struct kvm_signal_mask __user *sigmask_arg = argp;
+               struct kvm_signal_mask kvm_sigmask;
+               sigset_t sigset, *p;
+
+               p = NULL;
+               if (argp) {
+                       r = -EFAULT;
+                       if (copy_from_user(&kvm_sigmask, argp,
+                                          sizeof kvm_sigmask))
+                               goto out;
+                       r = -EINVAL;
+                       if (kvm_sigmask.len != sizeof sigset)
+                               goto out;
+                       r = -EFAULT;
+                       if (copy_from_user(&sigset, sigmask_arg->sigset,
+                                          sizeof sigset))
+                               goto out;
+                       p = &sigset;
+               }
+               r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
+               break;
+       }
+       case KVM_GET_FPU: {
+               struct kvm_fpu fpu;
+
+               memset(&fpu, 0, sizeof fpu);
+               r = kvm_vcpu_ioctl_get_fpu(vcpu, &fpu);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user(argp, &fpu, sizeof fpu))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_SET_FPU: {
+               struct kvm_fpu fpu;
+
+               r = -EFAULT;
+               if (copy_from_user(&fpu, argp, sizeof fpu))
+                       goto out;
+               r = kvm_vcpu_ioctl_set_fpu(vcpu, &fpu);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
        default:
                ;
        }
@@ -2155,6 +2656,17 @@ static long kvm_vm_ioctl(struct file *filp,
                        goto out;
                break;
        }
+       case KVM_SET_MEMORY_ALIAS: {
+               struct kvm_memory_alias alias;
+
+               r = -EFAULT;
+               if (copy_from_user(&alias, argp, sizeof alias))
+                       goto out;
+               r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
+               if (r)
+                       goto out;
+               break;
+       }
        default:
                ;
        }
@@ -2168,15 +2680,11 @@ static struct page *kvm_vm_nopage(struct vm_area_struct *vma,
 {
        struct kvm *kvm = vma->vm_file->private_data;
        unsigned long pgoff;
-       struct kvm_memory_slot *slot;
        struct page *page;
 
        *type = VM_FAULT_MINOR;
        pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-       slot = gfn_to_memslot(kvm, pgoff);
-       if (!slot)
-               return NOPAGE_SIGBUS;
-       page = gfn_to_page(slot, pgoff);
+       page = gfn_to_page(kvm, pgoff);
        if (!page)
                return NOPAGE_SIGBUS;
        get_page(page);
@@ -2248,13 +2756,19 @@ static long kvm_dev_ioctl(struct file *filp,
                          unsigned int ioctl, unsigned long arg)
 {
        void __user *argp = (void __user *)arg;
-       int r = -EINVAL;
+       long r = -EINVAL;
 
        switch (ioctl) {
        case KVM_GET_API_VERSION:
+               r = -EINVAL;
+               if (arg)
+                       goto out;
                r = KVM_API_VERSION;
                break;
        case KVM_CREATE_VM:
+               r = -EINVAL;
+               if (arg)
+                       goto out;
                r = kvm_dev_ioctl_create_vm();
                break;
        case KVM_GET_MSR_INDEX_LIST: {
@@ -2284,6 +2798,18 @@ static long kvm_dev_ioctl(struct file *filp,
                r = 0;
                break;
        }
+       case KVM_CHECK_EXTENSION:
+               /*
+                * No extensions defined at present.
+                */
+               r = 0;
+               break;
+       case KVM_GET_VCPU_MMAP_SIZE:
+               r = -EINVAL;
+               if (arg)
+                       goto out;
+               r = 2 * PAGE_SIZE;
+               break;
        default:
                ;
        }
@@ -2299,7 +2825,7 @@ static struct file_operations kvm_chardev_ops = {
 };
 
 static struct miscdevice kvm_dev = {
-       MISC_DYNAMIC_MINOR,
+       KVM_MINOR,
        "kvm",
        &kvm_chardev_ops,
 };
@@ -2385,14 +2911,39 @@ static struct notifier_block kvm_cpu_notifier = {
        .priority = 20, /* must be > scheduler priority */
 };
 
+static u64 stat_get(void *_offset)
+{
+       unsigned offset = (long)_offset;
+       u64 total = 0;
+       struct kvm *kvm;
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       spin_lock(&kvm_lock);
+       list_for_each_entry(kvm, &vm_list, vm_list)
+               for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+                       vcpu = &kvm->vcpus[i];
+                       total += *(u32 *)((void *)vcpu + offset);
+               }
+       spin_unlock(&kvm_lock);
+       return total;
+}
+
+static void stat_set(void *offset, u64 val)
+{
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(stat_fops, stat_get, stat_set, "%llu\n");
+
 static __init void kvm_init_debug(void)
 {
        struct kvm_stats_debugfs_item *p;
 
        debugfs_dir = debugfs_create_dir("kvm", NULL);
        for (p = debugfs_entries; p->name; ++p)
-               p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
-                                              p->data);
+               p->dentry = debugfs_create_file(p->name, 0444, debugfs_dir,
+                                               (void *)(long)p->offset,
+                                               &stat_fops);
 }
 
 static void kvm_exit_debug(void)
@@ -2522,6 +3073,10 @@ static __init int kvm_init(void)
        static struct page *bad_page;
        int r;
 
+       r = kvm_mmu_module_init();
+       if (r)
+               goto out4;
+
        r = register_filesystem(&kvm_fs_type);
        if (r)
                goto out3;
@@ -2550,6 +3105,8 @@ out:
 out2:
        unregister_filesystem(&kvm_fs_type);
 out3:
+       kvm_mmu_module_exit();
+out4:
        return r;
 }
 
@@ -2559,6 +3116,7 @@ static __exit void kvm_exit(void)
        __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT));
        mntput(kvmfs_mnt);
        unregister_filesystem(&kvm_fs_type);
+       kvm_mmu_module_exit();
 }
 
 module_init(kvm_init)
index 624f1ca..a869983 100644 (file)
@@ -9,17 +9,15 @@
 #include "svm.h"
 #include "kvm.h"
 
-static const u32 host_save_msrs[] = {
+static const u32 host_save_user_msrs[] = {
 #ifdef CONFIG_X86_64
        MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
-       MSR_FS_BASE, MSR_GS_BASE,
+       MSR_FS_BASE,
 #endif
        MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
-       MSR_IA32_DEBUGCTLMSR, /*MSR_IA32_LASTBRANCHFROMIP,
-       MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/
 };
 
-#define NR_HOST_SAVE_MSRS ARRAY_SIZE(host_save_msrs)
+#define NR_HOST_SAVE_USER_MSRS ARRAY_SIZE(host_save_user_msrs)
 #define NUM_DB_REGS 4
 
 struct vcpu_svm {
@@ -28,13 +26,12 @@ struct vcpu_svm {
        struct svm_cpu_data *svm_data;
        uint64_t asid_generation;
 
-       unsigned long cr0;
-       unsigned long cr4;
        unsigned long db_regs[NUM_DB_REGS];
 
        u64 next_rip;
 
-       u64 host_msrs[NR_HOST_SAVE_MSRS];
+       u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
+       u64 host_gs_base;
        unsigned long host_cr2;
        unsigned long host_db_regs[NUM_DB_REGS];
        unsigned long host_dr6;
diff --git a/drivers/kvm/kvm_vmx.h b/drivers/kvm/kvm_vmx.h
deleted file mode 100644 (file)
index d139f73..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __KVM_VMX_H
-#define __KVM_VMX_H
-
-#ifdef CONFIG_X86_64
-/*
- * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
- * mechanism (cpu bug AA24)
- */
-#define NR_BAD_MSRS 2
-#else
-#define NR_BAD_MSRS 0
-#endif
-
-#endif
index cab26f3..e8e2281 100644 (file)
@@ -52,11 +52,15 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg) {}
 static int dbg = 1;
 #endif
 
+#ifndef MMU_DEBUG
+#define ASSERT(x) do { } while (0)
+#else
 #define ASSERT(x)                                                      \
        if (!(x)) {                                                     \
                printk(KERN_WARNING "assertion failed %s:%d: %s\n",     \
                       __FILE__, __LINE__, #x);                         \
        }
+#endif
 
 #define PT64_PT_BITS 9
 #define PT64_ENT_PER_PAGE (1 << PT64_PT_BITS)
@@ -159,6 +163,9 @@ struct kvm_rmap_desc {
        struct kvm_rmap_desc *more;
 };
 
+static struct kmem_cache *pte_chain_cache;
+static struct kmem_cache *rmap_desc_cache;
+
 static int is_write_protection(struct kvm_vcpu *vcpu)
 {
        return vcpu->cr0 & CR0_WP_MASK;
@@ -196,14 +203,15 @@ static int is_rmap_pte(u64 pte)
 }
 
 static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
-                                 size_t objsize, int min)
+                                 struct kmem_cache *base_cache, int min,
+                                 gfp_t gfp_flags)
 {
        void *obj;
 
        if (cache->nobjs >= min)
                return 0;
        while (cache->nobjs < ARRAY_SIZE(cache->objects)) {
-               obj = kzalloc(objsize, GFP_NOWAIT);
+               obj = kmem_cache_zalloc(base_cache, gfp_flags);
                if (!obj)
                        return -ENOMEM;
                cache->objects[cache->nobjs++] = obj;
@@ -217,20 +225,35 @@ static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc)
                kfree(mc->objects[--mc->nobjs]);
 }
 
-static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
+static int __mmu_topup_memory_caches(struct kvm_vcpu *vcpu, gfp_t gfp_flags)
 {
        int r;
 
        r = mmu_topup_memory_cache(&vcpu->mmu_pte_chain_cache,
-                                  sizeof(struct kvm_pte_chain), 4);
+                                  pte_chain_cache, 4, gfp_flags);
        if (r)
                goto out;
        r = mmu_topup_memory_cache(&vcpu->mmu_rmap_desc_cache,
-                                  sizeof(struct kvm_rmap_desc), 1);
+                                  rmap_desc_cache, 1, gfp_flags);
 out:
        return r;
 }
 
+static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
+{
+       int r;
+
+       r = __mmu_topup_memory_caches(vcpu, GFP_NOWAIT);
+       if (r < 0) {
+               spin_unlock(&vcpu->kvm->lock);
+               kvm_arch_ops->vcpu_put(vcpu);
+               r = __mmu_topup_memory_caches(vcpu, GFP_KERNEL);
+               kvm_arch_ops->vcpu_load(vcpu);
+               spin_lock(&vcpu->kvm->lock);
+       }
+       return r;
+}
+
 static void mmu_free_memory_caches(struct kvm_vcpu *vcpu)
 {
        mmu_free_memory_cache(&vcpu->mmu_pte_chain_cache);
@@ -390,13 +413,11 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
 {
        struct kvm *kvm = vcpu->kvm;
        struct page *page;
-       struct kvm_memory_slot *slot;
        struct kvm_rmap_desc *desc;
        u64 *spte;
 
-       slot = gfn_to_memslot(kvm, gfn);
-       BUG_ON(!slot);
-       page = gfn_to_page(slot, gfn);
+       page = gfn_to_page(kvm, gfn);
+       BUG_ON(!page);
 
        while (page_private(page)) {
                if (!(page_private(page) & 1))
@@ -417,6 +438,7 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
        }
 }
 
+#ifdef MMU_DEBUG
 static int is_empty_shadow_page(hpa_t page_hpa)
 {
        u64 *pos;
@@ -431,15 +453,15 @@ static int is_empty_shadow_page(hpa_t page_hpa)
                }
        return 1;
 }
+#endif
 
 static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa)
 {
        struct kvm_mmu_page *page_head = page_header(page_hpa);
 
        ASSERT(is_empty_shadow_page(page_hpa));
-       list_del(&page_head->link);
        page_head->page_hpa = page_hpa;
-       list_add(&page_head->link, &vcpu->free_pages);
+       list_move(&page_head->link, &vcpu->free_pages);
        ++vcpu->kvm->n_free_mmu_pages;
 }
 
@@ -457,11 +479,9 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
                return NULL;
 
        page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link);
-       list_del(&page->link);
-       list_add(&page->link, &vcpu->kvm->active_mmu_pages);
+       list_move(&page->link, &vcpu->kvm->active_mmu_pages);
        ASSERT(is_empty_shadow_page(page->page_hpa));
        page->slot_bitmap = 0;
-       page->global = 1;
        page->multimapped = 0;
        page->parent_pte = parent_pte;
        --vcpu->kvm->n_free_mmu_pages;
@@ -569,6 +589,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                                             gva_t gaddr,
                                             unsigned level,
                                             int metaphysical,
+                                            unsigned hugepage_access,
                                             u64 *parent_pte)
 {
        union kvm_mmu_page_role role;
@@ -582,6 +603,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
        role.glevels = vcpu->mmu.root_level;
        role.level = level;
        role.metaphysical = metaphysical;
+       role.hugepage_access = hugepage_access;
        if (vcpu->mmu.root_level <= PT32_ROOT_LEVEL) {
                quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level));
                quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
@@ -669,10 +691,8 @@ static void kvm_mmu_zap_page(struct kvm_vcpu *vcpu,
        if (!page->root_count) {
                hlist_del(&page->hash_link);
                kvm_mmu_free_page(vcpu, page->page_hpa);
-       } else {
-               list_del(&page->link);
-               list_add(&page->link, &vcpu->kvm->active_mmu_pages);
-       }
+       } else
+               list_move(&page->link, &vcpu->kvm->active_mmu_pages);
 }
 
 static int kvm_mmu_unprotect_page(struct kvm_vcpu *vcpu, gfn_t gfn)
@@ -714,14 +734,12 @@ hpa_t safe_gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
 
 hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
 {
-       struct kvm_memory_slot *slot;
        struct page *page;
 
        ASSERT((gpa & HPA_ERR_MASK) == 0);
-       slot = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
-       if (!slot)
+       page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
+       if (!page)
                return gpa | HPA_ERR_MASK;
-       page = gfn_to_page(slot, gpa >> PAGE_SHIFT);
        return ((hpa_t)page_to_pfn(page) << PAGE_SHIFT)
                | (gpa & (PAGE_SIZE-1));
 }
@@ -735,6 +753,15 @@ hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva)
        return gpa_to_hpa(vcpu, gpa);
 }
 
+struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
+{
+       gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
+
+       if (gpa == UNMAPPED_GVA)
+               return NULL;
+       return pfn_to_page(gpa_to_hpa(vcpu, gpa) >> PAGE_SHIFT);
+}
+
 static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
 {
 }
@@ -772,7 +799,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p)
                                >> PAGE_SHIFT;
                        new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
                                                     v, level - 1,
-                                                    1, &table[index]);
+                                                    1, 0, &table[index]);
                        if (!new_table) {
                                pgprintk("nonpaging_map: ENOMEM\n");
                                return -ENOMEM;
@@ -804,10 +831,12 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
        for (i = 0; i < 4; ++i) {
                hpa_t root = vcpu->mmu.pae_root[i];
 
-               ASSERT(VALID_PAGE(root));
-               root &= PT64_BASE_ADDR_MASK;
-               page = page_header(root);
-               --page->root_count;
+               if (root) {
+                       ASSERT(VALID_PAGE(root));
+                       root &= PT64_BASE_ADDR_MASK;
+                       page = page_header(root);
+                       --page->root_count;
+               }
                vcpu->mmu.pae_root[i] = INVALID_PAGE;
        }
        vcpu->mmu.root_hpa = INVALID_PAGE;
@@ -827,7 +856,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
 
                ASSERT(!VALID_PAGE(root));
                page = kvm_mmu_get_page(vcpu, root_gfn, 0,
-                                       PT64_ROOT_LEVEL, 0, NULL);
+                                       PT64_ROOT_LEVEL, 0, 0, NULL);
                root = page->page_hpa;
                ++page->root_count;
                vcpu->mmu.root_hpa = root;
@@ -838,13 +867,17 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
                hpa_t root = vcpu->mmu.pae_root[i];
 
                ASSERT(!VALID_PAGE(root));
-               if (vcpu->mmu.root_level == PT32E_ROOT_LEVEL)
+               if (vcpu->mmu.root_level == PT32E_ROOT_LEVEL) {
+                       if (!is_present_pte(vcpu->pdptrs[i])) {
+                               vcpu->mmu.pae_root[i] = 0;
+                               continue;
+                       }
                        root_gfn = vcpu->pdptrs[i] >> PAGE_SHIFT;
-               else if (vcpu->mmu.root_level == 0)
+               else if (vcpu->mmu.root_level == 0)
                        root_gfn = 0;
                page = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
                                        PT32_ROOT_LEVEL, !is_paging(vcpu),
-                                       NULL);
+                                       0, NULL);
                root = page->page_hpa;
                ++page->root_count;
                vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
@@ -903,7 +936,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu)
 
 static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu)
 {
-       ++kvm_stat.tlb_flush;
+       ++vcpu->stat.tlb_flush;
        kvm_arch_ops->tlb_flush(vcpu);
 }
 
@@ -918,11 +951,6 @@ static void paging_new_cr3(struct kvm_vcpu *vcpu)
        kvm_arch_ops->set_cr3(vcpu, vcpu->mmu.root_hpa);
 }
 
-static void mark_pagetable_nonglobal(void *shadow_pte)
-{
-       page_header(__pa(shadow_pte))->global = 0;
-}
-
 static inline void set_pte_common(struct kvm_vcpu *vcpu,
                             u64 *shadow_pte,
                             gpa_t gaddr,
@@ -940,9 +968,6 @@ static inline void set_pte_common(struct kvm_vcpu *vcpu,
 
        *shadow_pte |= access_bits;
 
-       if (!(*shadow_pte & PT_GLOBAL_MASK))
-               mark_pagetable_nonglobal(shadow_pte);
-
        if (is_error_hpa(paddr)) {
                *shadow_pte |= gaddr;
                *shadow_pte |= PT_SHADOW_IO_MARK;
@@ -1316,6 +1341,51 @@ void kvm_mmu_slot_remove_write_access(struct kvm_vcpu *vcpu, int slot)
        }
 }
 
+void kvm_mmu_zap_all(struct kvm_vcpu *vcpu)
+{
+       destroy_kvm_mmu(vcpu);
+
+       while (!list_empty(&vcpu->kvm->active_mmu_pages)) {
+               struct kvm_mmu_page *page;
+
+               page = container_of(vcpu->kvm->active_mmu_pages.next,
+                                   struct kvm_mmu_page, link);
+               kvm_mmu_zap_page(vcpu, page);
+       }
+
+       mmu_free_memory_caches(vcpu);
+       kvm_arch_ops->tlb_flush(vcpu);
+       init_kvm_mmu(vcpu);
+}
+
+void kvm_mmu_module_exit(void)
+{
+       if (pte_chain_cache)
+               kmem_cache_destroy(pte_chain_cache);
+       if (rmap_desc_cache)
+               kmem_cache_destroy(rmap_desc_cache);
+}
+
+int kvm_mmu_module_init(void)
+{
+       pte_chain_cache = kmem_cache_create("kvm_pte_chain",
+                                           sizeof(struct kvm_pte_chain),
+                                           0, 0, NULL, NULL);
+       if (!pte_chain_cache)
+               goto nomem;
+       rmap_desc_cache = kmem_cache_create("kvm_rmap_desc",
+                                           sizeof(struct kvm_rmap_desc),
+                                           0, 0, NULL, NULL);
+       if (!rmap_desc_cache)
+               goto nomem;
+
+       return 0;
+
+nomem:
+       kvm_mmu_module_exit();
+       return -ENOMEM;
+}
+
 #ifdef AUDIT
 
 static const char *audit_msg;
@@ -1338,7 +1408,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
        for (i = 0; i < PT64_ENT_PER_PAGE; ++i, va += va_delta) {
                u64 ent = pt[i];
 
-               if (!ent & PT_PRESENT_MASK)
+               if (!(ent & PT_PRESENT_MASK))
                        continue;
 
                va = canonicalize(va);
@@ -1360,7 +1430,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
 
 static void audit_mappings(struct kvm_vcpu *vcpu)
 {
-       int i;
+       unsigned i;
 
        if (vcpu->mmu.root_level == 4)
                audit_mappings_page(vcpu, vcpu->mmu.root_hpa, 0, 4);
index f3bcee9..73ffbff 100644 (file)
@@ -148,8 +148,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
                        break;
                }
 
-               if (walker->level != 3 || is_long_mode(vcpu))
-                       walker->inherited_ar &= walker->table[index];
+               walker->inherited_ar &= walker->table[index];
                table_gfn = (*ptep & PT_BASE_ADDR_MASK) >> PAGE_SHIFT;
                paddr = safe_gpa_to_hpa(vcpu, *ptep & PT_BASE_ADDR_MASK);
                kunmap_atomic(walker->table, KM_USER0);
@@ -248,6 +247,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                u64 shadow_pte;
                int metaphysical;
                gfn_t table_gfn;
+               unsigned hugepage_access = 0;
 
                if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
                        if (level == PT_PAGE_TABLE_LEVEL)
@@ -277,6 +277,9 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                if (level - 1 == PT_PAGE_TABLE_LEVEL
                    && walker->level == PT_DIRECTORY_LEVEL) {
                        metaphysical = 1;
+                       hugepage_access = *guest_ent;
+                       hugepage_access &= PT_USER_MASK | PT_WRITABLE_MASK;
+                       hugepage_access >>= PT_WRITABLE_SHIFT;
                        table_gfn = (*guest_ent & PT_BASE_ADDR_MASK)
                                >> PAGE_SHIFT;
                } else {
@@ -284,7 +287,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                        table_gfn = walker->table_gfn[level - 2];
                }
                shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
-                                              metaphysical, shadow_ent);
+                                              metaphysical, hugepage_access,
+                                              shadow_ent);
                shadow_addr = shadow_page->page_hpa;
                shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
                        | PT_WRITABLE_MASK | PT_USER_MASK;
@@ -444,7 +448,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
        if (is_io_pte(*shadow_pte))
                return 1;
 
-       ++kvm_stat.pf_fixed;
+       ++vcpu->stat.pf_fixed;
        kvm_mmu_audit(vcpu, "post page fault (fixed)");
 
        return write_pt;
index 3d8ea7a..9c15f32 100644 (file)
@@ -44,6 +44,10 @@ MODULE_LICENSE("GPL");
 #define KVM_EFER_LMA (1 << 10)
 #define KVM_EFER_LME (1 << 8)
 
+#define SVM_FEATURE_NPT  (1 << 0)
+#define SVM_FEATURE_LBRV (1 << 1)
+#define SVM_DEATURE_SVML (1 << 2)
+
 unsigned long iopm_base;
 unsigned long msrpm_base;
 
@@ -59,15 +63,16 @@ struct kvm_ldttss_desc {
 struct svm_cpu_data {
        int cpu;
 
-       uint64_t asid_generation;
-       uint32_t max_asid;
-       uint32_t next_asid;
+       u64 asid_generation;
+       u32 max_asid;
+       u32 next_asid;
        struct kvm_ldttss_desc *tss_desc;
 
        struct page *save_area;
 };
 
 static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
+static uint32_t svm_features;
 
 struct svm_init_data {
        int cpu;
@@ -82,6 +87,11 @@ static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
 
 #define MAX_INST_SIZE 15
 
+static inline u32 svm_has(u32 feat)
+{
+       return svm_features & feat;
+}
+
 static unsigned get_addr_size(struct kvm_vcpu *vcpu)
 {
        struct vmcb_save_area *sa = &vcpu->svm->vmcb->save;
@@ -203,13 +213,6 @@ static void inject_ud(struct kvm_vcpu *vcpu)
                                                UD_VECTOR;
 }
 
-static void inject_db(struct kvm_vcpu *vcpu)
-{
-       vcpu->svm->vmcb->control.event_inj =    SVM_EVTINJ_VALID |
-                                               SVM_EVTINJ_TYPE_EXEPT |
-                                               DB_VECTOR;
-}
-
 static int is_page_fault(uint32_t info)
 {
        info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
@@ -309,6 +312,7 @@ static void svm_hardware_enable(void *garbage)
        svm_data->asid_generation = 1;
        svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
        svm_data->next_asid = svm_data->max_asid + 1;
+       svm_features = cpuid_edx(SVM_CPUID_FUNC);
 
        asm volatile ( "sgdt %0" : "=m"(gdt_descr) );
        gdt = (struct desc_struct *)gdt_descr.address;
@@ -459,7 +463,6 @@ static void init_vmcb(struct vmcb *vmcb)
 {
        struct vmcb_control_area *control = &vmcb->control;
        struct vmcb_save_area *save = &vmcb->save;
-       u64 tsc;
 
        control->intercept_cr_read =    INTERCEPT_CR0_MASK |
                                        INTERCEPT_CR3_MASK |
@@ -511,12 +514,13 @@ static void init_vmcb(struct vmcb *vmcb)
                                (1ULL << INTERCEPT_VMSAVE) |
                                (1ULL << INTERCEPT_STGI) |
                                (1ULL << INTERCEPT_CLGI) |
-                               (1ULL << INTERCEPT_SKINIT);
+                               (1ULL << INTERCEPT_SKINIT) |
+                               (1ULL << INTERCEPT_MONITOR) |
+                               (1ULL << INTERCEPT_MWAIT);
 
        control->iopm_base_pa = iopm_base;
        control->msrpm_base_pa = msrpm_base;
-       rdtscll(tsc);
-       control->tsc_offset = -tsc;
+       control->tsc_offset = 0;
        control->int_ctl = V_INTR_MASKING_MASK;
 
        init_seg(&save->es);
@@ -576,12 +580,15 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)
        vcpu->svm->vmcb = page_address(page);
        memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
        vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
-       vcpu->svm->cr0 = 0x00000010;
        vcpu->svm->asid_generation = 0;
        memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs));
        init_vmcb(vcpu->svm->vmcb);
 
        fx_init(vcpu);
+       vcpu->fpu_active = 1;
+       vcpu->apic_base = 0xfee00000 |
+                       /*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
+                       MSR_IA32_APICBASE_ENABLE;
 
        return 0;
 
@@ -602,11 +609,34 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
 
 static void svm_vcpu_load(struct kvm_vcpu *vcpu)
 {
-       get_cpu();
+       int cpu, i;
+
+       cpu = get_cpu();
+       if (unlikely(cpu != vcpu->cpu)) {
+               u64 tsc_this, delta;
+
+               /*
+                * Make sure that the guest sees a monotonically
+                * increasing TSC.
+                */
+               rdtscll(tsc_this);
+               delta = vcpu->host_tsc - tsc_this;
+               vcpu->svm->vmcb->control.tsc_offset += delta;
+               vcpu->cpu = cpu;
+       }
+
+       for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
+               rdmsrl(host_save_user_msrs[i], vcpu->svm->host_user_msrs[i]);
 }
 
 static void svm_vcpu_put(struct kvm_vcpu *vcpu)
 {
+       int i;
+
+       for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
+               wrmsrl(host_save_user_msrs[i], vcpu->svm->host_user_msrs[i]);
+
+       rdtscll(vcpu->host_tsc);
        put_cpu();
 }
 
@@ -714,7 +744,7 @@ static void svm_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
        vcpu->svm->vmcb->save.gdtr.base = dt->base ;
 }
 
-static void svm_decache_cr0_cr4_guest_bits(struct kvm_vcpu *vcpu)
+static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
 }
 
@@ -733,9 +763,15 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
                }
        }
 #endif
-       vcpu->svm->cr0 = cr0;
-       vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK | CR0_WP_MASK;
+       if ((vcpu->cr0 & CR0_TS_MASK) && !(cr0 & CR0_TS_MASK)) {
+               vcpu->svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
+               vcpu->fpu_active = 1;
+       }
+
        vcpu->cr0 = cr0;
+       cr0 |= CR0_PG_MASK | CR0_WP_MASK;
+       cr0 &= ~(CR0_CD_MASK | CR0_NW_MASK);
+       vcpu->svm->vmcb->save.cr0 = cr0;
 }
 
 static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -785,18 +821,16 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
 
 static void load_host_msrs(struct kvm_vcpu *vcpu)
 {
-       int i;
-
-       for ( i = 0; i < NR_HOST_SAVE_MSRS; i++)
-               wrmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]);
+#ifdef CONFIG_X86_64
+       wrmsrl(MSR_GS_BASE, vcpu->svm->host_gs_base);
+#endif
 }
 
 static void save_host_msrs(struct kvm_vcpu *vcpu)
 {
-       int i;
-
-       for ( i = 0; i < NR_HOST_SAVE_MSRS; i++)
-               rdmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]);
+#ifdef CONFIG_X86_64
+       rdmsrl(MSR_GS_BASE, vcpu->svm->host_gs_base);
+#endif
 }
 
 static void new_asid(struct kvm_vcpu *vcpu, struct svm_cpu_data *svm_data)
@@ -890,7 +924,7 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        case EMULATE_DONE:
                return 1;
        case EMULATE_DO_MMIO:
-               ++kvm_stat.mmio_exits;
+               ++vcpu->stat.mmio_exits;
                kvm_run->exit_reason = KVM_EXIT_MMIO;
                return 0;
        case EMULATE_FAIL:
@@ -904,6 +938,16 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 0;
 }
 
+static int nm_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vcpu->svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
+       if (!(vcpu->cr0 & CR0_TS_MASK))
+               vcpu->svm->vmcb->save.cr0 &= ~CR0_TS_MASK;
+       vcpu->fpu_active = 1;
+
+       return 1;
+}
+
 static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        /*
@@ -981,7 +1025,7 @@ static int io_get_override(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address)
+static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, gva_t *address)
 {
        unsigned long addr_mask;
        unsigned long *reg;
@@ -1025,38 +1069,38 @@ static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address)
 static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug?
-       int _in = io_info & SVM_IOIO_TYPE_MASK;
+       int size, down, in, string, rep;
+       unsigned port;
+       unsigned long count;
+       gva_t address = 0;
 
-       ++kvm_stat.io_exits;
+       ++vcpu->stat.io_exits;
 
        vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2;
 
-       kvm_run->exit_reason = KVM_EXIT_IO;
-       kvm_run->io.port = io_info >> 16;
-       kvm_run->io.direction = (_in) ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
-       kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT);
-       kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0;
-       kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0;
+       in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
+       port = io_info >> 16;
+       size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
+       string = (io_info & SVM_IOIO_STR_MASK) != 0;
+       rep = (io_info & SVM_IOIO_REP_MASK) != 0;
+       count = 1;
+       down = (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0;
 
-       if (kvm_run->io.string) {
+       if (string) {
                unsigned addr_mask;
 
-               addr_mask = io_adress(vcpu, _in, &kvm_run->io.address);
+               addr_mask = io_adress(vcpu, in, &address);
                if (!addr_mask) {
                        printk(KERN_DEBUG "%s: get io address failed\n",
                               __FUNCTION__);
                        return 1;
                }
 
-               if (kvm_run->io.rep) {
-                       kvm_run->io.count
-                               = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
-                       kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags
-                                                  & X86_EFLAGS_DF) != 0;
-               }
-       } else
-               kvm_run->io.value = vcpu->svm->vmcb->save.rax;
-       return 0;
+               if (rep)
+                       count = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
+       }
+       return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
+                            address, rep, port);
 }
 
 static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1072,13 +1116,14 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                return 1;
 
        kvm_run->exit_reason = KVM_EXIT_HLT;
-       ++kvm_stat.halt_exits;
+       ++vcpu->stat.halt_exits;
        return 0;
 }
 
 static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       vcpu->svm->vmcb->save.rip += 3;
+       vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 3;
+       skip_emulated_instruction(vcpu);
        return kvm_hypercall(vcpu, kvm_run);
 }
 
@@ -1098,8 +1143,8 @@ static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_r
 static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
-       kvm_run->exit_reason = KVM_EXIT_CPUID;
-       return 0;
+       kvm_emulate_cpuid(vcpu);
+       return 1;
 }
 
 static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1239,7 +1284,7 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu,
         */
        if (kvm_run->request_interrupt_window &&
            !vcpu->irq_summary) {
-               ++kvm_stat.irq_window_exits;
+               ++vcpu->stat.irq_window_exits;
                kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
                return 0;
        }
@@ -1267,6 +1312,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
        [SVM_EXIT_WRITE_DR5]                    = emulate_on_interception,
        [SVM_EXIT_WRITE_DR7]                    = emulate_on_interception,
        [SVM_EXIT_EXCP_BASE + PF_VECTOR]        = pf_interception,
+       [SVM_EXIT_EXCP_BASE + NM_VECTOR]        = nm_interception,
        [SVM_EXIT_INTR]                         = nop_on_interception,
        [SVM_EXIT_NMI]                          = nop_on_interception,
        [SVM_EXIT_SMI]                          = nop_on_interception,
@@ -1288,6 +1334,8 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
        [SVM_EXIT_STGI]                         = invalid_op_interception,
        [SVM_EXIT_CLGI]                         = invalid_op_interception,
        [SVM_EXIT_SKINIT]                       = invalid_op_interception,
+       [SVM_EXIT_MONITOR]                      = invalid_op_interception,
+       [SVM_EXIT_MWAIT]                        = invalid_op_interception,
 };
 
 
@@ -1295,8 +1343,6 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        u32 exit_code = vcpu->svm->vmcb->control.exit_code;
 
-       kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
-
        if (is_external_interrupt(vcpu->svm->vmcb->control.exit_int_info) &&
            exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
                printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
@@ -1307,12 +1353,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
            || svm_exit_handlers[exit_code] == 0) {
                kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
-               printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n",
-                      __FUNCTION__,
-                      exit_code,
-                      vcpu->svm->vmcb->save.rip,
-                      vcpu->cr0,
-                      vcpu->svm->vmcb->save.rflags);
+               kvm_run->hw.hardware_exit_reason = exit_code;
                return 0;
        }
 
@@ -1461,8 +1502,10 @@ again:
                load_db_regs(vcpu->svm->db_regs);
        }
 
-       fx_save(vcpu->host_fx_image);
-       fx_restore(vcpu->guest_fx_image);
+       if (vcpu->fpu_active) {
+               fx_save(vcpu->host_fx_image);
+               fx_restore(vcpu->guest_fx_image);
+       }
 
        asm volatile (
 #ifdef CONFIG_X86_64
@@ -1573,8 +1616,10 @@ again:
 #endif
                : "cc", "memory" );
 
-       fx_save(vcpu->guest_fx_image);
-       fx_restore(vcpu->host_fx_image);
+       if (vcpu->fpu_active) {
+               fx_save(vcpu->guest_fx_image);
+               fx_restore(vcpu->host_fx_image);
+       }
 
        if ((vcpu->svm->vmcb->save.dr7 & 0xff))
                load_db_regs(vcpu->svm->host_db_regs);
@@ -1606,8 +1651,9 @@ again:
        vcpu->svm->next_rip = 0;
 
        if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
-               kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
-               kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code;
+               kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+               kvm_run->fail_entry.hardware_entry_failure_reason
+                       = vcpu->svm->vmcb->control.exit_code;
                post_kvm_run_save(vcpu, kvm_run);
                return 0;
        }
@@ -1615,14 +1661,16 @@ again:
        r = handle_exit(vcpu, kvm_run);
        if (r > 0) {
                if (signal_pending(current)) {
-                       ++kvm_stat.signal_exits;
+                       ++vcpu->stat.signal_exits;
                        post_kvm_run_save(vcpu, kvm_run);
+                       kvm_run->exit_reason = KVM_EXIT_INTR;
                        return -EINTR;
                }
 
                if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-                       ++kvm_stat.request_irq_exits;
+                       ++vcpu->stat.request_irq_exits;
                        post_kvm_run_save(vcpu, kvm_run);
+                       kvm_run->exit_reason = KVM_EXIT_INTR;
                        return -EINTR;
                }
                kvm_resched(vcpu);
@@ -1641,6 +1689,12 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
 {
        vcpu->svm->vmcb->save.cr3 = root;
        force_new_asid(vcpu);
+
+       if (vcpu->fpu_active) {
+               vcpu->svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
+               vcpu->svm->vmcb->save.cr0 |= CR0_TS_MASK;
+               vcpu->fpu_active = 0;
+       }
 }
 
 static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
@@ -1649,7 +1703,7 @@ static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
 {
        uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info;
 
-       ++kvm_stat.pf_guest;
+       ++vcpu->stat.pf_guest;
 
        if (is_page_fault(exit_int_info)) {
 
@@ -1709,9 +1763,8 @@ static struct kvm_arch_ops svm_arch_ops = {
        .get_segment = svm_get_segment,
        .set_segment = svm_set_segment,
        .get_cs_db_l_bits = svm_get_cs_db_l_bits,
-       .decache_cr0_cr4_guest_bits = svm_decache_cr0_cr4_guest_bits,
+       .decache_cr4_guest_bits = svm_decache_cr4_guest_bits,
        .set_cr0 = svm_set_cr0,
-       .set_cr0_no_modeswitch = svm_set_cr0,
        .set_cr3 = svm_set_cr3,
        .set_cr4 = svm_set_cr4,
        .set_efer = svm_set_efer,
index df731c3..5e93814 100644 (file)
@@ -44,6 +44,9 @@ enum {
        INTERCEPT_RDTSCP,
        INTERCEPT_ICEBP,
        INTERCEPT_WBINVD,
+       INTERCEPT_MONITOR,
+       INTERCEPT_MWAIT,
+       INTERCEPT_MWAIT_COND,
 };
 
 
@@ -298,6 +301,9 @@ struct __attribute__ ((__packed__)) vmcb {
 #define SVM_EXIT_RDTSCP                0x087
 #define SVM_EXIT_ICEBP         0x088
 #define SVM_EXIT_WBINVD                0x089
+#define SVM_EXIT_MONITOR       0x08a
+#define SVM_EXIT_MWAIT         0x08b
+#define SVM_EXIT_MWAIT_COND    0x08c
 #define SVM_EXIT_NPF           0x400
 
 #define SVM_EXIT_ERR           -1
index fbbf9d6..724db00 100644 (file)
@@ -17,7 +17,6 @@
 
 #include "kvm.h"
 #include "vmx.h"
-#include "kvm_vmx.h"
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -70,6 +69,10 @@ static struct kvm_vmx_segment_field {
        VMX_SEGMENT_FIELD(LDTR),
 };
 
+/*
+ * Keep MSR_K6_STAR at the end, as setup_msrs() will try to optimize it
+ * away by decrementing the array size.
+ */
 static const u32 vmx_msr_index[] = {
 #ifdef CONFIG_X86_64
        MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE,
@@ -78,6 +81,19 @@ static const u32 vmx_msr_index[] = {
 };
 #define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
 
+#ifdef CONFIG_X86_64
+static unsigned msr_offset_kernel_gs_base;
+#define NR_64BIT_MSRS 4
+/*
+ * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
+ * mechanism (cpu bug AA24)
+ */
+#define NR_BAD_MSRS 2
+#else
+#define NR_64BIT_MSRS 0
+#define NR_BAD_MSRS 0
+#endif
+
 static inline int is_page_fault(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
@@ -85,6 +101,13 @@ static inline int is_page_fault(u32 intr_info)
                (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
 }
 
+static inline int is_no_device(u32 intr_info)
+{
+       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
+                            INTR_INFO_VALID_MASK)) ==
+               (INTR_TYPE_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
+}
+
 static inline int is_external_interrupt(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
@@ -200,6 +223,16 @@ static void vmcs_write64(unsigned long field, u64 value)
 #endif
 }
 
+static void vmcs_clear_bits(unsigned long field, u32 mask)
+{
+       vmcs_writel(field, vmcs_readl(field) & ~mask);
+}
+
+static void vmcs_set_bits(unsigned long field, u32 mask)
+{
+       vmcs_writel(field, vmcs_readl(field) | mask);
+}
+
 /*
  * Switches to specified vcpu, until a matching vcpu_put(), but assumes
  * vcpu mutex is already taken.
@@ -296,6 +329,44 @@ static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
                     INTR_INFO_VALID_MASK);
 }
 
+/*
+ * Set up the vmcs to automatically save and restore system
+ * msrs.  Don't touch the 64-bit msrs if the guest is in legacy
+ * mode, as fiddling with msrs is very expensive.
+ */
+static void setup_msrs(struct kvm_vcpu *vcpu)
+{
+       int nr_skip, nr_good_msrs;
+
+       if (is_long_mode(vcpu))
+               nr_skip = NR_BAD_MSRS;
+       else
+               nr_skip = NR_64BIT_MSRS;
+       nr_good_msrs = vcpu->nmsrs - nr_skip;
+
+       /*
+        * MSR_K6_STAR is only needed on long mode guests, and only
+        * if efer.sce is enabled.
+        */
+       if (find_msr_entry(vcpu, MSR_K6_STAR)) {
+               --nr_good_msrs;
+#ifdef CONFIG_X86_64
+               if (is_long_mode(vcpu) && (vcpu->shadow_efer & EFER_SCE))
+                       ++nr_good_msrs;
+#endif
+       }
+
+       vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
+                   virt_to_phys(vcpu->guest_msrs + nr_skip));
+       vmcs_writel(VM_EXIT_MSR_STORE_ADDR,
+                   virt_to_phys(vcpu->guest_msrs + nr_skip));
+       vmcs_writel(VM_EXIT_MSR_LOAD_ADDR,
+                   virt_to_phys(vcpu->host_msrs + nr_skip));
+       vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */
+       vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs);  /* 22.2.2 */
+       vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
+}
+
 /*
  * reads and returns guest's timestamp counter "register"
  * guest_tsc = host_tsc + tsc_offset    -- 21.3
@@ -712,6 +783,8 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 
        vmcs_write32(GUEST_CS_AR_BYTES, 0xf3);
        vmcs_write32(GUEST_CS_LIMIT, 0xffff);
+       if (vmcs_readl(GUEST_CS_BASE) == 0xffff0000)
+               vmcs_writel(GUEST_CS_BASE, 0xf0000);
        vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4);
 
        fix_rmode_seg(VCPU_SREG_ES, &vcpu->rmode.es);
@@ -754,11 +827,8 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
 
 #endif
 
-static void vmx_decache_cr0_cr4_guest_bits(struct kvm_vcpu *vcpu)
+static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
-       vcpu->cr0 &= KVM_GUEST_CR0_MASK;
-       vcpu->cr0 |= vmcs_readl(GUEST_CR0) & ~KVM_GUEST_CR0_MASK;
-
        vcpu->cr4 &= KVM_GUEST_CR4_MASK;
        vcpu->cr4 |= vmcs_readl(GUEST_CR4) & ~KVM_GUEST_CR4_MASK;
 }
@@ -780,22 +850,11 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        }
 #endif
 
-       vmcs_writel(CR0_READ_SHADOW, cr0);
-       vmcs_writel(GUEST_CR0,
-                   (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
-       vcpu->cr0 = cr0;
-}
-
-/*
- * Used when restoring the VM to avoid corrupting segment registers
- */
-static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0)
-{
-       if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
-               enter_rmode(vcpu);
+       if (!(cr0 & CR0_TS_MASK)) {
+               vcpu->fpu_active = 1;
+               vmcs_clear_bits(EXCEPTION_BITMAP, CR0_TS_MASK);
+       }
 
-       vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0);
-       update_exception_bitmap(vcpu);
        vmcs_writel(CR0_READ_SHADOW, cr0);
        vmcs_writel(GUEST_CR0,
                    (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
@@ -805,6 +864,12 @@ static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0)
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
        vmcs_writel(GUEST_CR3, cr3);
+
+       if (!(vcpu->cr0 & CR0_TS_MASK)) {
+               vcpu->fpu_active = 0;
+               vmcs_set_bits(GUEST_CR0, CR0_TS_MASK);
+               vmcs_set_bits(EXCEPTION_BITMAP, 1 << NM_VECTOR);
+       }
 }
 
 static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -835,6 +900,7 @@ static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
 
                msr->data = efer & ~EFER_LME;
        }
+       setup_msrs(vcpu);
 }
 
 #endif
@@ -878,7 +944,14 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
        vmcs_writel(sf->base, var->base);
        vmcs_write32(sf->limit, var->limit);
        vmcs_write16(sf->selector, var->selector);
-       if (var->unusable)
+       if (vcpu->rmode.active && var->s) {
+               /*
+                * Hack real-mode segments into vm86 compatibility.
+                */
+               if (var->base == 0xffff0000 && var->selector == 0xf000)
+                       vmcs_writel(sf->base, 0xf0000);
+               ar = 0xf3;
+       } else if (var->unusable)
                ar = 1 << 16;
        else {
                ar = var->type & 15;
@@ -933,9 +1006,9 @@ static int init_rmode_tss(struct kvm* kvm)
        gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
        char *page;
 
-       p1 = _gfn_to_page(kvm, fn++);
-       p2 = _gfn_to_page(kvm, fn++);
-       p3 = _gfn_to_page(kvm, fn);
+       p1 = gfn_to_page(kvm, fn++);
+       p2 = gfn_to_page(kvm, fn++);
+       p3 = gfn_to_page(kvm, fn);
 
        if (!p1 || !p2 || !p3) {
                kvm_printf(kvm,"%s: gfn_to_page failed\n", __FUNCTION__);
@@ -991,7 +1064,6 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
        struct descriptor_table dt;
        int i;
        int ret = 0;
-       int nr_good_msrs;
        extern asmlinkage void kvm_vmx_return(void);
 
        if (!init_rmode_tss(vcpu->kvm)) {
@@ -1136,23 +1208,17 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
                vcpu->host_msrs[j].reserved = 0;
                vcpu->host_msrs[j].data = data;
                vcpu->guest_msrs[j] = vcpu->host_msrs[j];
+#ifdef CONFIG_X86_64
+               if (index == MSR_KERNEL_GS_BASE)
+                       msr_offset_kernel_gs_base = j;
+#endif
                ++vcpu->nmsrs;
        }
-       printk(KERN_DEBUG "kvm: msrs: %d\n", vcpu->nmsrs);
 
-       nr_good_msrs = vcpu->nmsrs - NR_BAD_MSRS;
-       vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
-                   virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
-       vmcs_writel(VM_EXIT_MSR_STORE_ADDR,
-                   virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
-       vmcs_writel(VM_EXIT_MSR_LOAD_ADDR,
-                   virt_to_phys(vcpu->host_msrs + NR_BAD_MSRS));
+       setup_msrs(vcpu);
+
        vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS, VM_EXIT_CONTROLS,
                               (HOST_IS_64 << 9));  /* 22.2,1, 20.7.1 */
-       vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */
-       vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs);  /* 22.2.2 */
-       vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
-
 
        /* 22.2.1, 20.8.1 */
        vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS,
@@ -1164,7 +1230,7 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
        vmcs_writel(TPR_THRESHOLD, 0);
 #endif
 
-       vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK);
+       vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
        vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
 
        vcpu->cr0 = 0x60000010;
@@ -1190,7 +1256,7 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq)
        u16 sp =  vmcs_readl(GUEST_RSP);
        u32 ss_limit = vmcs_read32(GUEST_SS_LIMIT);
 
-       if (sp > ss_limit || sp - 6 > sp) {
+       if (sp > ss_limit || sp < 6 ) {
                vcpu_printf(vcpu, "%s: #SS, rsp 0x%lx ss 0x%lx limit 0x%x\n",
                            __FUNCTION__,
                            vmcs_readl(GUEST_RSP),
@@ -1330,6 +1396,15 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                asm ("int $2");
                return 1;
        }
+
+       if (is_no_device(intr_info)) {
+               vcpu->fpu_active = 1;
+               vmcs_clear_bits(EXCEPTION_BITMAP, 1 << NM_VECTOR);
+               if (!(vcpu->cr0 & CR0_TS_MASK))
+                       vmcs_clear_bits(GUEST_CR0, CR0_TS_MASK);
+               return 1;
+       }
+
        error_code = 0;
        rip = vmcs_readl(GUEST_RIP);
        if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
@@ -1355,7 +1430,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                case EMULATE_DONE:
                        return 1;
                case EMULATE_DO_MMIO:
-                       ++kvm_stat.mmio_exits;
+                       ++vcpu->stat.mmio_exits;
                        kvm_run->exit_reason = KVM_EXIT_MMIO;
                        return 0;
                 case EMULATE_FAIL:
@@ -1384,7 +1459,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 static int handle_external_interrupt(struct kvm_vcpu *vcpu,
                                     struct kvm_run *kvm_run)
 {
-       ++kvm_stat.irq_exits;
+       ++vcpu->stat.irq_exits;
        return 1;
 }
 
@@ -1394,7 +1469,7 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 0;
 }
 
-static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
+static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)
 {
        u64 inst;
        gva_t rip;
@@ -1439,33 +1514,35 @@ static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
 done:
        countr_size *= 8;
        *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
+       //printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]);
        return 1;
 }
 
 static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        u64 exit_qualification;
+       int size, down, in, string, rep;
+       unsigned port;
+       unsigned long count;
+       gva_t address;
 
-       ++kvm_stat.io_exits;
+       ++vcpu->stat.io_exits;
        exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
-       kvm_run->exit_reason = KVM_EXIT_IO;
-       if (exit_qualification & 8)
-               kvm_run->io.direction = KVM_EXIT_IO_IN;
-       else
-               kvm_run->io.direction = KVM_EXIT_IO_OUT;
-       kvm_run->io.size = (exit_qualification & 7) + 1;
-       kvm_run->io.string = (exit_qualification & 16) != 0;
-       kvm_run->io.string_down
-               = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
-       kvm_run->io.rep = (exit_qualification & 32) != 0;
-       kvm_run->io.port = exit_qualification >> 16;
-       if (kvm_run->io.string) {
-               if (!get_io_count(vcpu, &kvm_run->io.count))
+       in = (exit_qualification & 8) != 0;
+       size = (exit_qualification & 7) + 1;
+       string = (exit_qualification & 16) != 0;
+       down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
+       count = 1;
+       rep = (exit_qualification & 32) != 0;
+       port = exit_qualification >> 16;
+       address = 0;
+       if (string) {
+               if (rep && !get_io_count(vcpu, &count))
                        return 1;
-               kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS);
-       } else
-               kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */
-       return 0;
+               address = vmcs_readl(GUEST_LINEAR_ADDRESS);
+       }
+       return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
+                            address, rep, port);
 }
 
 static void
@@ -1514,6 +1591,15 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                        return 1;
                };
                break;
+       case 2: /* clts */
+               vcpu_load_rsp_rip(vcpu);
+               vcpu->fpu_active = 1;
+               vmcs_clear_bits(EXCEPTION_BITMAP, 1 << NM_VECTOR);
+               vmcs_clear_bits(GUEST_CR0, CR0_TS_MASK);
+               vcpu->cr0 &= ~CR0_TS_MASK;
+               vmcs_writel(CR0_READ_SHADOW, vcpu->cr0);
+               skip_emulated_instruction(vcpu);
+               return 1;
        case 1: /*mov from cr*/
                switch (cr) {
                case 3:
@@ -1523,8 +1609,6 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 8:
-                       printk(KERN_DEBUG "handle_cr: read CR8 "
-                              "cpu erratum AA15\n");
                        vcpu_load_rsp_rip(vcpu);
                        vcpu->regs[reg] = vcpu->cr8;
                        vcpu_put_rsp_rip(vcpu);
@@ -1583,8 +1667,8 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       kvm_run->exit_reason = KVM_EXIT_CPUID;
-       return 0;
+       kvm_emulate_cpuid(vcpu);
+       return 1;
 }
 
 static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1639,7 +1723,7 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
        if (kvm_run->request_interrupt_window &&
            !vcpu->irq_summary) {
                kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
-               ++kvm_stat.irq_window_exits;
+               ++vcpu->stat.irq_window_exits;
                return 0;
        }
        return 1;
@@ -1652,13 +1736,13 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                return 1;
 
        kvm_run->exit_reason = KVM_EXIT_HLT;
-       ++kvm_stat.halt_exits;
+       ++vcpu->stat.halt_exits;
        return 0;
 }
 
 static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP)+3);
+       skip_emulated_instruction(vcpu);
        return kvm_hypercall(vcpu, kvm_run);
 }
 
@@ -1699,7 +1783,6 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                                exit_reason != EXIT_REASON_EXCEPTION_NMI )
                printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
                       "exit reason is 0x%x\n", __FUNCTION__, exit_reason);
-       kvm_run->instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
        if (exit_reason < kvm_vmx_max_exit_handlers
            && kvm_vmx_exit_handlers[exit_reason])
                return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
@@ -1763,11 +1846,21 @@ again:
        if (vcpu->guest_debug.enabled)
                kvm_guest_debug_pre(vcpu);
 
-       fx_save(vcpu->host_fx_image);
-       fx_restore(vcpu->guest_fx_image);
+       if (vcpu->fpu_active) {
+               fx_save(vcpu->host_fx_image);
+               fx_restore(vcpu->guest_fx_image);
+       }
+       /*
+        * Loading guest fpu may have cleared host cr0.ts
+        */
+       vmcs_writel(HOST_CR0, read_cr0());
 
-       save_msrs(vcpu->host_msrs, vcpu->nmsrs);
-       load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+#ifdef CONFIG_X86_64
+       if (is_long_mode(vcpu)) {
+               save_msrs(vcpu->host_msrs + msr_offset_kernel_gs_base, 1);
+               load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+       }
+#endif
 
        asm (
                /* Store host registers */
@@ -1909,21 +2002,28 @@ again:
 
                reload_tss();
        }
-       ++kvm_stat.exits;
+       ++vcpu->stat.exits;
 
-       save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
-       load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
+#ifdef CONFIG_X86_64
+       if (is_long_mode(vcpu)) {
+               save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+               load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
+       }
+#endif
+
+       if (vcpu->fpu_active) {
+               fx_save(vcpu->guest_fx_image);
+               fx_restore(vcpu->host_fx_image);
+       }
 
-       fx_save(vcpu->guest_fx_image);
-       fx_restore(vcpu->host_fx_image);
        vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
 
        asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 
-       kvm_run->exit_type = 0;
        if (fail) {
-               kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
-               kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR);
+               kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+               kvm_run->fail_entry.hardware_entry_failure_reason
+                       = vmcs_read32(VM_INSTRUCTION_ERROR);
                r = 0;
        } else {
                /*
@@ -1933,19 +2033,20 @@ again:
                        profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
 
                vcpu->launched = 1;
-               kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
                r = kvm_handle_exit(kvm_run, vcpu);
                if (r > 0) {
                        /* Give scheduler a change to reschedule. */
                        if (signal_pending(current)) {
-                               ++kvm_stat.signal_exits;
+                               ++vcpu->stat.signal_exits;
                                post_kvm_run_save(vcpu, kvm_run);
+                               kvm_run->exit_reason = KVM_EXIT_INTR;
                                return -EINTR;
                        }
 
                        if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-                               ++kvm_stat.request_irq_exits;
+                               ++vcpu->stat.request_irq_exits;
                                post_kvm_run_save(vcpu, kvm_run);
+                               kvm_run->exit_reason = KVM_EXIT_INTR;
                                return -EINTR;
                        }
 
@@ -1969,7 +2070,7 @@ static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
 {
        u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
 
-       ++kvm_stat.pf_guest;
+       ++vcpu->stat.pf_guest;
 
        if (is_page_fault(vect_info)) {
                printk(KERN_DEBUG "inject_page_fault: "
@@ -2026,6 +2127,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
        vmcs_clear(vmcs);
        vcpu->vmcs = vmcs;
        vcpu->launched = 0;
+       vcpu->fpu_active = 1;
 
        return 0;
 
@@ -2062,9 +2164,8 @@ static struct kvm_arch_ops vmx_arch_ops = {
        .get_segment = vmx_get_segment,
        .set_segment = vmx_set_segment,
        .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
-       .decache_cr0_cr4_guest_bits = vmx_decache_cr0_cr4_guest_bits,
+       .decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
        .set_cr0 = vmx_set_cr0,
-       .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch,
        .set_cr3 = vmx_set_cr3,
        .set_cr4 = vmx_set_cr4,
 #ifdef CONFIG_X86_64
index 7513cdd..7ade090 100644 (file)
@@ -833,8 +833,9 @@ done_prefixes:
                dst.ptr = (unsigned long *)cr2;
                dst.bytes = (d & ByteOp) ? 1 : op_bytes;
                if (d & BitOp) {
-                       dst.ptr += src.val / BITS_PER_LONG;
-                       dst.bytes = sizeof(long);
+                       unsigned long mask = ~(dst.bytes * 8 - 1);
+
+                       dst.ptr = (void *)dst.ptr + (src.val & mask) / 8;
                }
                if (!(d & Mov) && /* optimisation - avoid slow emulated read */
                    ((rc = ops->read_emulated((unsigned long)dst.ptr,
@@ -1044,7 +1045,7 @@ done_prefixes:
                        if ((rc = ops->write_std(
                                     register_address(ctxt->ss_base,
                                                      _regs[VCPU_REGS_RSP]),
-                                    dst.val, dst.bytes, ctxt)) != 0)
+                                    &dst.val, dst.bytes, ctxt)) != 0)
                                goto done;
                        dst.val = dst.orig_val; /* skanky: disable writeback */
                        break;
@@ -1077,12 +1078,12 @@ writeback:
                case OP_MEM:
                        if (lock_prefix)
                                rc = ops->cmpxchg_emulated((unsigned long)dst.
-                                                          ptr, dst.orig_val,
-                                                          dst.val, dst.bytes,
+                                                          ptr, &dst.orig_val,
+                                                          &dst.val, dst.bytes,
                                                           ctxt);
                        else
                                rc = ops->write_emulated((unsigned long)dst.ptr,
-                                                        dst.val, dst.bytes,
+                                                        &dst.val, dst.bytes,
                                                         ctxt);
                        if (rc != 0)
                                goto done;
@@ -1320,36 +1321,8 @@ twobyte_special_insn:
                realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
                break;
        case 0xc7:              /* Grp9 (cmpxchg8b) */
-#if defined(__i386__)
-               {
-                       unsigned long old_lo, old_hi;
-                       if (((rc = ops->read_emulated(cr2 + 0, &old_lo, 4,
-                                                     ctxt)) != 0)
-                           || ((rc = ops->read_emulated(cr2 + 4, &old_hi, 4,
-                                                        ctxt)) != 0))
-                               goto done;
-                       if ((old_lo != _regs[VCPU_REGS_RAX])
-                           || (old_hi != _regs[VCPU_REGS_RDX])) {
-                               _regs[VCPU_REGS_RAX] = old_lo;
-                               _regs[VCPU_REGS_RDX] = old_hi;
-                               _eflags &= ~EFLG_ZF;
-                       } else if (ops->cmpxchg8b_emulated == NULL) {
-                               rc = X86EMUL_UNHANDLEABLE;
-                               goto done;
-                       } else {
-                               if ((rc = ops->cmpxchg8b_emulated(cr2, old_lo,
-                                                         old_hi,
-                                                         _regs[VCPU_REGS_RBX],
-                                                         _regs[VCPU_REGS_RCX],
-                                                         ctxt)) != 0)
-                                       goto done;
-                               _eflags |= EFLG_ZF;
-                       }
-                       break;
-               }
-#elif defined(CONFIG_X86_64)
                {
-                       unsigned long old, new;
+                       u64 old, new;
                        if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0)
                                goto done;
                        if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) ||
@@ -1358,15 +1331,15 @@ twobyte_special_insn:
                                _regs[VCPU_REGS_RDX] = (u32) (old >> 32);
                                _eflags &= ~EFLG_ZF;
                        } else {
-                               new = (_regs[VCPU_REGS_RCX] << 32) | (u32) _regs[VCPU_REGS_RBX];
-                               if ((rc = ops->cmpxchg_emulated(cr2, old,
-                                                         new, 8, ctxt)) != 0)
+                               new = ((u64)_regs[VCPU_REGS_RCX] << 32)
+                                       | (u32) _regs[VCPU_REGS_RBX];
+                               if ((rc = ops->cmpxchg_emulated(cr2, &old,
+                                                         &new, 8, ctxt)) != 0)
                                        goto done;
                                _eflags |= EFLG_ZF;
                        }
                        break;
                }
-#endif
        }
        goto writeback;
 
index 5d41bd5..ea3407d 100644 (file)
@@ -59,8 +59,7 @@ struct x86_emulate_ops {
         *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
         *  @bytes: [IN ] Number of bytes to read from memory.
         */
-       int (*read_std)(unsigned long addr,
-                       unsigned long *val,
+       int (*read_std)(unsigned long addr, void *val,
                        unsigned int bytes, struct x86_emulate_ctxt * ctxt);
 
        /*
@@ -71,8 +70,7 @@ struct x86_emulate_ops {
         *                required).
         *  @bytes: [IN ] Number of bytes to write to memory.
         */
-       int (*write_std)(unsigned long addr,
-                        unsigned long val,
+       int (*write_std)(unsigned long addr, const void *val,
                         unsigned int bytes, struct x86_emulate_ctxt * ctxt);
 
        /*
@@ -82,7 +80,7 @@ struct x86_emulate_ops {
         *  @bytes: [IN ] Number of bytes to read from memory.
         */
        int (*read_emulated) (unsigned long addr,
-                             unsigned long *val,
+                             void *val,
                              unsigned int bytes,
                              struct x86_emulate_ctxt * ctxt);
 
@@ -94,7 +92,7 @@ struct x86_emulate_ops {
         *  @bytes: [IN ] Number of bytes to write to memory.
         */
        int (*write_emulated) (unsigned long addr,
-                              unsigned long val,
+                              const void *val,
                               unsigned int bytes,
                               struct x86_emulate_ctxt * ctxt);
 
@@ -107,29 +105,11 @@ struct x86_emulate_ops {
         *  @bytes: [IN ] Number of bytes to access using CMPXCHG.
         */
        int (*cmpxchg_emulated) (unsigned long addr,
-                                unsigned long old,
-                                unsigned long new,
+                                const void *old,
+                                const void *new,
                                 unsigned int bytes,
                                 struct x86_emulate_ctxt * ctxt);
 
-       /*
-        * cmpxchg8b_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an
-        *                     emulated/special memory area.
-        *  @addr:  [IN ] Linear address to access.
-        *  @old:   [IN ] Value expected to be current at @addr.
-        *  @new:   [IN ] Value to write to @addr.
-        * NOTES:
-        *  1. This function is only ever called when emulating a real CMPXCHG8B.
-        *  2. This function is *never* called on x86/64 systems.
-        *  2. Not defining this function (i.e., specifying NULL) is equivalent
-        *     to defining a function that always returns X86EMUL_UNHANDLEABLE.
-        */
-       int (*cmpxchg8b_emulated) (unsigned long addr,
-                                  unsigned long old_lo,
-                                  unsigned long old_hi,
-                                  unsigned long new_lo,
-                                  unsigned long new_hi,
-                                  struct x86_emulate_ctxt * ctxt);
 };
 
 struct cpu_user_regs;
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/at91_mci.c b/drivers/mmc/at91_mci.c
deleted file mode 100644 (file)
index 459f4b4..0000000
+++ /dev/null
@@ -1,1002 +0,0 @@
-/*
- *  linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver
- *
- *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
- *
- *  Copyright (C) 2006 Malcolm Noyes
- *
- * 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.
- */
-
-/*
-   This is the AT91 MCI driver that has been tested with both MMC cards
-   and SD-cards.  Boards that support write protect are now supported.
-   The CCAT91SBC001 board does not support SD cards.
-
-   The three entry points are at91_mci_request, at91_mci_set_ios
-   and at91_mci_get_ro.
-
-   SET IOS
-     This configures the device to put it into the correct mode and clock speed
-     required.
-
-   MCI REQUEST
-     MCI request processes the commands sent in the mmc_request structure. This
-     can consist of a processing command and a stop command in the case of
-     multiple block transfers.
-
-     There are three main types of request, commands, reads and writes.
-
-     Commands are straight forward. The command is submitted to the controller and
-     the request function returns. When the controller generates an interrupt to indicate
-     the command is finished, the response to the command are read and the mmc_request_done
-     function called to end the request.
-
-     Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
-     controller to manage the transfers.
-
-     A read is done from the controller directly to the scatterlist passed in from the request.
-     Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
-     swapped in the scatterlist buffers.  AT91SAM926x are not affected by this bug.
-
-     The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
-
-     A write is slightly different in that the bytes to write are read from the scatterlist
-     into a dma memory buffer (this is in case the source buffer should be read only). The
-     entire write buffer is then done from this single dma memory buffer.
-
-     The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
-
-   GET RO
-     Gets the status of the write protect pin, if available.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach/mmc.h>
-#include <asm/arch/board.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91_mci.h>
-
-#define DRIVER_NAME "at91_mci"
-
-#undef SUPPORT_4WIRE
-
-#define FL_SENT_COMMAND        (1 << 0)
-#define FL_SENT_STOP   (1 << 1)
-
-#define AT91_MCI_ERRORS        (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE       \
-               | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE               \
-               | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)                        
-
-#define at91_mci_read(host, reg)       __raw_readl((host)->baseaddr + (reg))
-#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
-
-
-/*
- * Low level type for this driver
- */
-struct at91mci_host
-{
-       struct mmc_host *mmc;
-       struct mmc_command *cmd;
-       struct mmc_request *request;
-
-       void __iomem *baseaddr;
-       int irq;
-
-       struct at91_mmc_data *board;
-       int present;
-
-       struct clk *mci_clk;
-
-       /*
-        * Flag indicating when the command has been sent. This is used to
-        * work out whether or not to send the stop
-        */
-       unsigned int flags;
-       /* flag for current bus settings */
-       u32 bus_mode;
-
-       /* DMA buffer used for transmitting */
-       unsigned int* buffer;
-       dma_addr_t physical_address;
-       unsigned int total_length;
-
-       /* Latest in the scatterlist that has been enabled for transfer, but not freed */
-       int in_use_index;
-
-       /* Latest in the scatterlist that has been enabled for transfer */
-       int transfer_index;
-};
-
-/*
- * Copy from sg to a dma block - used for transfers
- */
-static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
-{
-       unsigned int len, i, size;
-       unsigned *dmabuf = host->buffer;
-
-       size = host->total_length;
-       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++) {
-               struct scatterlist *sg;
-               int amount;
-               unsigned int *sgbuffer;
-
-               sg = &data->sg[i];
-
-               sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
-               amount = min(size, sg->length);
-               size -= amount;
-
-               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
-                       int index;
-
-                       for (index = 0; index < (amount / 4); index++)
-                               *dmabuf++ = swab32(sgbuffer[index]);
-               }
-               else
-                       memcpy(dmabuf, sgbuffer, amount);
-
-               kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
-
-               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);
-}
-
-/*
- * Prepare a dma read
- */
-static void at91mci_pre_dma_read(struct at91mci_host *host)
-{
-       int i;
-       struct scatterlist *sg;
-       struct mmc_command *cmd;
-       struct mmc_data *data;
-
-       pr_debug("pre dma read\n");
-
-       cmd = host->cmd;
-       if (!cmd) {
-               pr_debug("no command\n");
-               return;
-       }
-
-       data = cmd->data;
-       if (!data) {
-               pr_debug("no data\n");
-               return;
-       }
-
-       for (i = 0; i < 2; i++) {
-               /* nothing left to transfer */
-               if (host->transfer_index >= data->sg_len) {
-                       pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
-                       break;
-               }
-
-               /* Check to see if this needs filling */
-               if (i == 0) {
-                       if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
-                               pr_debug("Transfer active in current\n");
-                               continue;
-                       }
-               }
-               else {
-                       if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
-                               pr_debug("Transfer active in next\n");
-                               continue;
-                       }
-               }
-
-               /* Setup the next transfer */
-               pr_debug("Using transfer index %d\n", host->transfer_index);
-
-               sg = &data->sg[host->transfer_index++];
-               pr_debug("sg = %p\n", sg);
-
-               sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
-
-               pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
-
-               if (i == 0) {
-                       at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
-                       at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4);
-               }
-               else {
-                       at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
-                       at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4);
-               }
-       }
-
-       pr_debug("pre dma read done\n");
-}
-
-/*
- * Handle after a dma read
- */
-static void at91mci_post_dma_read(struct at91mci_host *host)
-{
-       struct mmc_command *cmd;
-       struct mmc_data *data;
-
-       pr_debug("post dma read\n");
-
-       cmd = host->cmd;
-       if (!cmd) {
-               pr_debug("no command\n");
-               return;
-       }
-
-       data = cmd->data;
-       if (!data) {
-               pr_debug("no data\n");
-               return;
-       }
-
-       while (host->in_use_index < host->transfer_index) {
-               unsigned int *buffer;
-
-               struct scatterlist *sg;
-
-               pr_debug("finishing index %d\n", host->in_use_index);
-
-               sg = &data->sg[host->in_use_index++];
-
-               pr_debug("Unmapping page %08X\n", sg->dma_address);
-
-               dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
-
-               /* Swap the contents of the buffer */
-               buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
-               pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
-               data->bytes_xfered += sg->length;
-
-               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
-                       int index;
-
-                       for (index = 0; index < (sg->length / 4); index++)
-                               buffer[index] = swab32(buffer[index]);
-               }
-
-               kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
-               flush_dcache_page(sg->page);
-       }
-
-       /* Is there another transfer to trigger? */
-       if (host->transfer_index < data->sg_len)
-               at91mci_pre_dma_read(host);
-       else {
-               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-       }
-
-       pr_debug("post dma read done\n");
-}
-
-/*
- * Handle transmitted data
- */
-static void at91_mci_handle_transmitted(struct at91mci_host *host)
-{
-       struct mmc_command *cmd;
-       struct mmc_data *data;
-
-       pr_debug("Handling the transmit\n");
-
-       /* Disable the transfer */
-       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
-       /* Now wait for cmd ready */
-       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
-       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-
-       cmd = host->cmd;
-       if (!cmd) return;
-
-       data = cmd->data;
-       if (!data) return;
-
-       data->bytes_xfered = host->total_length;
-}
-
-/*
- * Enable the controller
- */
-static void at91_mci_enable(struct at91mci_host *host)
-{
-       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-       at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-       at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
-
-       /* use Slot A or B (only one at same time) */
-       at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
-}
-
-/*
- * Disable the controller
- */
-static void at91_mci_disable(struct at91mci_host *host)
-{
-       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-}
-
-/*
- * Send a command
- * return the interrupts to enable
- */
-static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
-       unsigned int cmdr, mr;
-       unsigned int block_length;
-       struct mmc_data *data = cmd->data;
-
-       unsigned int blocks;
-       unsigned int ier = 0;
-
-       host->cmd = cmd;
-
-       /* Not sure if this is needed */
-#if 0
-       if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
-               pr_debug("Clearing timeout\n");
-               at91_mci_write(host, AT91_MCI_ARGR, 0);
-               at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
-               while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
-                       /* spin */
-                       pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
-               }
-       }
-#endif
-       cmdr = cmd->opcode;
-
-       if (mmc_resp_type(cmd) == MMC_RSP_NONE)
-               cmdr |= AT91_MCI_RSPTYP_NONE;
-       else {
-               /* if a response is expected then allow maximum response latancy */
-               cmdr |= AT91_MCI_MAXLAT;
-               /* set 136 bit response for R2, 48 bit response otherwise */
-               if (mmc_resp_type(cmd) == MMC_RSP_R2)
-                       cmdr |= AT91_MCI_RSPTYP_136;
-               else
-                       cmdr |= AT91_MCI_RSPTYP_48;
-       }
-
-       if (data) {
-               block_length = data->blksz;
-               blocks = data->blocks;
-
-               /* always set data start - also set direction flag for read */
-               if (data->flags & MMC_DATA_READ)
-                       cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
-               else if (data->flags & MMC_DATA_WRITE)
-                       cmdr |= AT91_MCI_TRCMD_START;
-
-               if (data->flags & MMC_DATA_STREAM)
-                       cmdr |= AT91_MCI_TRTYP_STREAM;
-               if (data->flags & MMC_DATA_MULTI)
-                       cmdr |= AT91_MCI_TRTYP_MULTIPLE;
-       }
-       else {
-               block_length = 0;
-               blocks = 0;
-       }
-
-       if (cmd->opcode == MMC_STOP_TRANSMISSION)
-               cmdr |= AT91_MCI_TRCMD_STOP;
-
-       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
-               cmdr |= AT91_MCI_OPDCMD;
-
-       /*
-        * Set the arguments and send the command
-        */
-       pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
-               cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
-
-       if (!data) {
-               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
-               at91_mci_write(host, ATMEL_PDC_RPR, 0);
-               at91_mci_write(host, ATMEL_PDC_RCR, 0);
-               at91_mci_write(host, ATMEL_PDC_RNPR, 0);
-               at91_mci_write(host, ATMEL_PDC_RNCR, 0);
-               at91_mci_write(host, ATMEL_PDC_TPR, 0);
-               at91_mci_write(host, ATMEL_PDC_TCR, 0);
-               at91_mci_write(host, ATMEL_PDC_TNPR, 0);
-               at91_mci_write(host, ATMEL_PDC_TNCR, 0);
-
-               at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
-               at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-               return AT91_MCI_CMDRDY;
-       }
-
-       mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
-       at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
-
-       /*
-        * Disable the PDC controller
-        */
-       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
-       if (cmdr & AT91_MCI_TRCMD_START) {
-               data->bytes_xfered = 0;
-               host->transfer_index = 0;
-               host->in_use_index = 0;
-               if (cmdr & AT91_MCI_TRDIR) {
-                       /*
-                        * Handle a read
-                        */
-                       host->buffer = NULL;
-                       host->total_length = 0;
-
-                       at91mci_pre_dma_read(host);
-                       ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
-               }
-               else {
-                       /*
-                        * Handle a write
-                        */
-                       host->total_length = block_length * blocks;
-                       host->buffer = dma_alloc_coherent(NULL,
-                                                 host->total_length,
-                                                 &host->physical_address, GFP_KERNEL);
-
-                       at91mci_sg_to_dma(host, data);
-
-                       pr_debug("Transmitting %d bytes\n", host->total_length);
-
-                       at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
-                       at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
-                       ier = AT91_MCI_TXBUFE;
-               }
-       }
-
-       /*
-        * Send the command and then enable the PDC - not the other way round as
-        * the data sheet says
-        */
-
-       at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
-       at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-
-       if (cmdr & AT91_MCI_TRCMD_START) {
-               if (cmdr & AT91_MCI_TRDIR)
-                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
-               else
-                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
-       }
-       return ier;
-}
-
-/*
- * Wait for a command to complete
- */
-static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
-       unsigned int ier;
-
-       ier = at91_mci_send_command(host, cmd);
-
-       pr_debug("setting ier to %08X\n", ier);
-
-       /* Stop on errors or the required value */
-       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
-}
-
-/*
- * Process the next step in the request
- */
-static void at91mci_process_next(struct at91mci_host *host)
-{
-       if (!(host->flags & FL_SENT_COMMAND)) {
-               host->flags |= FL_SENT_COMMAND;
-               at91mci_process_command(host, host->request->cmd);
-       }
-       else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
-               host->flags |= FL_SENT_STOP;
-               at91mci_process_command(host, host->request->stop);
-       }
-       else
-               mmc_request_done(host->mmc, host->request);
-}
-
-/*
- * Handle a command that has been completed
- */
-static void at91mci_completed_command(struct at91mci_host *host)
-{
-       struct mmc_command *cmd = host->cmd;
-       unsigned int status;
-
-       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-
-       cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
-       cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
-       cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
-       cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
-
-       if (host->buffer) {
-               dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
-               host->buffer = NULL;
-       }
-
-       status = at91_mci_read(host, AT91_MCI_SR);
-
-       pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
-                status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
-       if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
-                       AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
-                       AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
-               if ((status & AT91_MCI_RCRCE) &&
-                       ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
-                       cmd->error = MMC_ERR_NONE;
-               }
-               else {
-                       if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
-                               cmd->error = MMC_ERR_TIMEOUT;
-                       else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
-                               cmd->error = MMC_ERR_BADCRC;
-                       else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
-                               cmd->error = MMC_ERR_FIFO;
-                       else
-                               cmd->error = MMC_ERR_FAILED;
-
-                       pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
-                                cmd->error, cmd->opcode, cmd->retries);
-               }
-       }
-       else
-               cmd->error = MMC_ERR_NONE;
-
-       at91mci_process_next(host);
-}
-
-/*
- * Handle an MMC request
- */
-static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct at91mci_host *host = mmc_priv(mmc);
-       host->request = mrq;
-       host->flags = 0;
-
-       at91mci_process_next(host);
-}
-
-/*
- * Set the IOS
- */
-static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       int clkdiv;
-       struct at91mci_host *host = mmc_priv(mmc);
-       unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
-
-       host->bus_mode = ios->bus_mode;
-
-       if (ios->clock == 0) {
-               /* Disable the MCI controller */
-               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
-               clkdiv = 0;
-       }
-       else {
-               /* Enable the MCI controller */
-               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-
-               if ((at91_master_clock % (ios->clock * 2)) == 0)
-                       clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
-               else
-                       clkdiv = (at91_master_clock / ios->clock) / 2;
-
-               pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
-                       at91_master_clock / (2 * (clkdiv + 1)));
-       }
-       if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
-               pr_debug("MMC: Setting controller bus width to 4\n");
-               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
-       }
-       else {
-               pr_debug("MMC: Setting controller bus width to 1\n");
-               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
-       }
-
-       /* Set the clock divider */
-       at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
-
-       /* maybe switch power to the card */
-       if (host->board->vcc_pin) {
-               switch (ios->power_mode) {
-                       case MMC_POWER_OFF:
-                               at91_set_gpio_value(host->board->vcc_pin, 0);
-                               break;
-                       case MMC_POWER_UP:
-                       case MMC_POWER_ON:
-                               at91_set_gpio_value(host->board->vcc_pin, 1);
-                               break;
-               }
-       }
-}
-
-/*
- * Handle an interrupt
- */
-static irqreturn_t at91_mci_irq(int irq, void *devid)
-{
-       struct at91mci_host *host = devid;
-       int completed = 0;
-       unsigned int int_status, int_mask;
-
-       int_status = at91_mci_read(host, AT91_MCI_SR);
-       int_mask = at91_mci_read(host, AT91_MCI_IMR);
-       
-       pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
-               int_status & int_mask);
-       
-       int_status = int_status & int_mask;
-
-       if (int_status & AT91_MCI_ERRORS) {
-               completed = 1;
-               
-               if (int_status & AT91_MCI_UNRE)
-                       pr_debug("MMC: Underrun error\n");
-               if (int_status & AT91_MCI_OVRE)
-                       pr_debug("MMC: Overrun error\n");
-               if (int_status & AT91_MCI_DTOE)
-                       pr_debug("MMC: Data timeout\n");
-               if (int_status & AT91_MCI_DCRCE)
-                       pr_debug("MMC: CRC error in data\n");
-               if (int_status & AT91_MCI_RTOE)
-                       pr_debug("MMC: Response timeout\n");
-               if (int_status & AT91_MCI_RENDE)
-                       pr_debug("MMC: Response end bit error\n");
-               if (int_status & AT91_MCI_RCRCE)
-                       pr_debug("MMC: Response CRC error\n");
-               if (int_status & AT91_MCI_RDIRE)
-                       pr_debug("MMC: Response direction error\n");
-               if (int_status & AT91_MCI_RINDE)
-                       pr_debug("MMC: Response index error\n");
-       } else {
-               /* Only continue processing if no errors */
-
-               if (int_status & AT91_MCI_TXBUFE) {
-                       pr_debug("TX buffer empty\n");
-                       at91_mci_handle_transmitted(host);
-               }
-
-               if (int_status & AT91_MCI_RXBUFF) {
-                       pr_debug("RX buffer full\n");
-                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
-               }
-
-               if (int_status & AT91_MCI_ENDTX)
-                       pr_debug("Transmit has ended\n");
-
-               if (int_status & AT91_MCI_ENDRX) {
-                       pr_debug("Receive has ended\n");
-                       at91mci_post_dma_read(host);
-               }
-
-               if (int_status & AT91_MCI_NOTBUSY) {
-                       pr_debug("Card is ready\n");
-                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
-               }
-
-               if (int_status & AT91_MCI_DTIP)
-                       pr_debug("Data transfer in progress\n");
-
-               if (int_status & AT91_MCI_BLKE)
-                       pr_debug("Block transfer has ended\n");
-
-               if (int_status & AT91_MCI_TXRDY)
-                       pr_debug("Ready to transmit\n");
-
-               if (int_status & AT91_MCI_RXRDY)
-                       pr_debug("Ready to receive\n");
-
-               if (int_status & AT91_MCI_CMDRDY) {
-                       pr_debug("Command ready\n");
-                       completed = 1;
-               }
-       }
-
-       if (completed) {
-               pr_debug("Completed command\n");
-               at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-               at91mci_completed_command(host);
-       } else
-               at91_mci_write(host, AT91_MCI_IDR, int_status);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
-{
-       struct at91mci_host *host = _host;
-       int present = !at91_get_gpio_value(irq);
-
-       /*
-        * we expect this irq on both insert and remove,
-        * and use a short delay to debounce.
-        */
-       if (present != host->present) {
-               host->present = present;
-               pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
-                       present ? "insert" : "remove");
-               if (!present) {
-                       pr_debug("****** Resetting SD-card bus width ******\n");
-                       at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
-               }
-               mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-       }
-       return IRQ_HANDLED;
-}
-
-static int at91_mci_get_ro(struct mmc_host *mmc)
-{
-       int read_only = 0;
-       struct at91mci_host *host = mmc_priv(mmc);
-
-       if (host->board->wp_pin) {
-               read_only = at91_get_gpio_value(host->board->wp_pin);
-               printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
-                               (read_only ? "read-only" : "read-write") );
-       }
-       else {
-               printk(KERN_WARNING "%s: host does not support reading read-only "
-                               "switch.  Assuming write-enable.\n", mmc_hostname(mmc));
-       }
-       return read_only;
-}
-
-static const struct mmc_host_ops at91_mci_ops = {
-       .request        = at91_mci_request,
-       .set_ios        = at91_mci_set_ios,
-       .get_ro         = at91_mci_get_ro,
-};
-
-/*
- * Probe for the device
- */
-static int __init at91_mci_probe(struct platform_device *pdev)
-{
-       struct mmc_host *mmc;
-       struct at91mci_host *host;
-       struct resource *res;
-       int ret;
-
-       pr_debug("Probe MCI devices\n");
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENXIO;
-
-       if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
-               return -EBUSY;
-
-       mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
-       if (!mmc) {
-               pr_debug("Failed to allocate mmc host\n");
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENOMEM;
-       }
-
-       mmc->ops = &at91_mci_ops;
-       mmc->f_min = 375000;
-       mmc->f_max = 25000000;
-       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_BYTEBLOCK;
-
-       mmc->max_blk_size = 4095;
-       mmc->max_blk_count = mmc->max_req_size;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-       host->buffer = NULL;
-       host->bus_mode = 0;
-       host->board = pdev->dev.platform_data;
-       if (host->board->wire4) {
-#ifdef SUPPORT_4WIRE
-               mmc->caps |= MMC_CAP_4_BIT_DATA;
-#else
-               printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
-#endif
-       }
-
-       /*
-        * Get Clock
-        */
-       host->mci_clk = clk_get(&pdev->dev, "mci_clk");
-       if (IS_ERR(host->mci_clk)) {
-               printk(KERN_ERR "AT91 MMC: no clock defined.\n");
-               mmc_free_host(mmc);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENODEV;
-       }
-
-       /*
-        * Map I/O region
-        */
-       host->baseaddr = ioremap(res->start, res->end - res->start + 1);
-       if (!host->baseaddr) {
-               clk_put(host->mci_clk);
-               mmc_free_host(mmc);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENOMEM;
-       }
-
-       /*
-        * Reset hardware
-        */
-       clk_enable(host->mci_clk);              /* Enable the peripheral clock */
-       at91_mci_disable(host);
-       at91_mci_enable(host);
-
-       /*
-        * Allocate the MCI interrupt
-        */
-       host->irq = platform_get_irq(pdev, 0);
-       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
-       if (ret) {
-               printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
-               clk_disable(host->mci_clk);
-               clk_put(host->mci_clk);
-               mmc_free_host(mmc);
-               iounmap(host->baseaddr);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return ret;
-       }
-
-       platform_set_drvdata(pdev, mmc);
-
-       /*
-        * Add host to MMC layer
-        */
-       if (host->board->det_pin)
-               host->present = !at91_get_gpio_value(host->board->det_pin);
-       else
-               host->present = -1;
-
-       mmc_add_host(mmc);
-
-       /*
-        * monitor card insertion/removal if we can
-        */
-       if (host->board->det_pin) {
-               ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
-                               0, DRIVER_NAME, host);
-               if (ret)
-                       printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
-       }
-
-       pr_debug("Added MCI driver\n");
-
-       return 0;
-}
-
-/*
- * Remove a device
- */
-static int __exit at91_mci_remove(struct platform_device *pdev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-       struct at91mci_host *host;
-       struct resource *res;
-
-       if (!mmc)
-               return -1;
-
-       host = mmc_priv(mmc);
-
-       if (host->present != -1) {
-               free_irq(host->board->det_pin, host);
-               cancel_delayed_work(&host->mmc->detect);
-       }
-
-       at91_mci_disable(host);
-       mmc_remove_host(mmc);
-       free_irq(host->irq, host);
-
-       clk_disable(host->mci_clk);                     /* Disable the peripheral clock */
-       clk_put(host->mci_clk);
-
-       iounmap(host->baseaddr);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, res->end - res->start + 1);
-
-       mmc_free_host(mmc);
-       platform_set_drvdata(pdev, NULL);
-       pr_debug("MCI Removed\n");
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-       int ret = 0;
-
-       if (mmc)
-               ret = mmc_suspend_host(mmc, state);
-
-       return ret;
-}
-
-static int at91_mci_resume(struct platform_device *pdev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-       int ret = 0;
-
-       if (mmc)
-               ret = mmc_resume_host(mmc);
-
-       return ret;
-}
-#else
-#define at91_mci_suspend       NULL
-#define at91_mci_resume                NULL
-#endif
-
-static struct platform_driver at91_mci_driver = {
-       .remove         = __exit_p(at91_mci_remove),
-       .suspend        = at91_mci_suspend,
-       .resume         = at91_mci_resume,
-       .driver         = {
-               .name   = DRIVER_NAME,
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init at91_mci_init(void)
-{
-       return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
-}
-
-static void __exit at91_mci_exit(void)
-{
-       platform_driver_unregister(&at91_mci_driver);
-}
-
-module_init(at91_mci_init);
-module_exit(at91_mci_exit);
-
-MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
-MODULE_AUTHOR("Nick Randell");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
deleted file mode 100644 (file)
index b834be2..0000000
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver
- *
- *  Copyright (c) 2005, Advanced Micro Devices, Inc.
- *
- *  Developed with help from the 2.4.30 MMC AU1XXX controller including
- *  the following copyright notices:
- *     Copyright (c) 2003-2004 Embedded Edge, LLC.
- *     Portions Copyright (C) 2002 Embedix, Inc
- *     Copyright 2002 Hewlett-Packard Company
-
- *  2.6 version of this driver inspired by:
- *     (drivers/mmc/wbsd.c) Copyright (C) 2004-2005 Pierre Ossman,
- *     All Rights Reserved.
- *     (drivers/mmc/pxa.c) Copyright (C) 2003 Russell King,
- *     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.
- */
-
-/* Why is a timer used to detect insert events?
- *
- * From the AU1100 MMC application guide:
- * If the Au1100-based design is intended to support both MultiMediaCards
- * and 1- or 4-data bit SecureDigital cards, then the solution is to
- * connect a weak (560KOhm) pull-up resistor to connector pin 1.
- * In doing so, a MMC card never enters SPI-mode communications,
- * but now the SecureDigital card-detect feature of CD/DAT3 is ineffective
- * (the low to high transition will not occur).
- *
- * So we use the timer to check the status manually.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#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>
-#include <asm/mach-au1x00/au1100_mmc.h>
-#include <asm/scatterlist.h>
-
-#include <au1xxx.h>
-#include "au1xmmc.h"
-
-#define DRIVER_NAME "au1xxx-mmc"
-
-/* Set this to enable special debugging macros */
-
-#ifdef DEBUG
-#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
-#else
-#define DBG(fmt, idx, args...)
-#endif
-
-const struct {
-       u32 iobase;
-       u32 tx_devid, rx_devid;
-       u16 bcsrpwr;
-       u16 bcsrstatus;
-       u16 wpstatus;
-} au1xmmc_card_table[] = {
-       { SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
-         BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
-#ifndef CONFIG_MIPS_DB1200
-       { SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
-         BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
-#endif
-};
-
-#define AU1XMMC_CONTROLLER_COUNT \
-       (sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
-
-/* This array stores pointers for the hosts (used by the IRQ handler) */
-struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
-static int dma = 1;
-
-#ifdef MODULE
-module_param(dma, bool, 0);
-MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
-#endif
-
-static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
-{
-       u32 val = au_readl(HOST_CONFIG(host));
-       val |= mask;
-       au_writel(val, HOST_CONFIG(host));
-       au_sync();
-}
-
-static inline void FLUSH_FIFO(struct au1xmmc_host *host)
-{
-       u32 val = au_readl(HOST_CONFIG2(host));
-
-       au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
-       au_sync_delay(1);
-
-       /* SEND_STOP will turn off clock control - this re-enables it */
-       val &= ~SD_CONFIG2_DF;
-
-       au_writel(val, HOST_CONFIG2(host));
-       au_sync();
-}
-
-static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
-{
-       u32 val = au_readl(HOST_CONFIG(host));
-       val &= ~mask;
-       au_writel(val, HOST_CONFIG(host));
-       au_sync();
-}
-
-static inline void SEND_STOP(struct au1xmmc_host *host)
-{
-
-       /* We know the value of CONFIG2, so avoid a read we don't need */
-       u32 mask = SD_CONFIG2_EN;
-
-       WARN_ON(host->status != HOST_S_DATA);
-       host->status = HOST_S_STOP;
-
-       au_writel(mask | SD_CONFIG2_DF, HOST_CONFIG2(host));
-       au_sync();
-
-       /* Send the stop commmand */
-       au_writel(STOP_CMD, HOST_CMD(host));
-}
-
-static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
-{
-
-       u32 val = au1xmmc_card_table[host->id].bcsrpwr;
-
-       bcsr->board &= ~val;
-       if (state) bcsr->board |= val;
-
-       au_sync_delay(1);
-}
-
-static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
-{
-       return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
-               ? 1 : 0;
-}
-
-static int au1xmmc_card_readonly(struct mmc_host *mmc)
-{
-       struct au1xmmc_host *host = mmc_priv(mmc);
-       return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
-               ? 1 : 0;
-}
-
-static void au1xmmc_finish_request(struct au1xmmc_host *host)
-{
-
-       struct mmc_request *mrq = host->mrq;
-
-       host->mrq = NULL;
-       host->flags &= HOST_F_ACTIVE;
-
-       host->dma.len = 0;
-       host->dma.dir = 0;
-
-       host->pio.index  = 0;
-       host->pio.offset = 0;
-       host->pio.len = 0;
-
-       host->status = HOST_S_IDLE;
-
-       bcsr->disk_leds |= (1 << 8);
-
-       mmc_request_done(host->mmc, mrq);
-}
-
-static void au1xmmc_tasklet_finish(unsigned long param)
-{
-       struct au1xmmc_host *host = (struct au1xmmc_host *) param;
-       au1xmmc_finish_request(host);
-}
-
-static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
-                               struct mmc_command *cmd)
-{
-
-       u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
-
-       switch (mmc_resp_type(cmd)) {
-       case MMC_RSP_NONE:
-               break;
-       case MMC_RSP_R1:
-               mmccmd |= SD_CMD_RT_1;
-               break;
-       case MMC_RSP_R1B:
-               mmccmd |= SD_CMD_RT_1B;
-               break;
-       case MMC_RSP_R2:
-               mmccmd |= SD_CMD_RT_2;
-               break;
-       case MMC_RSP_R3:
-               mmccmd |= SD_CMD_RT_3;
-               break;
-       default:
-               printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
-                       mmc_resp_type(cmd));
-               return MMC_ERR_INVALID;
-       }
-
-       switch(cmd->opcode) {
-       case MMC_READ_SINGLE_BLOCK:
-       case SD_APP_SEND_SCR:
-               mmccmd |= SD_CMD_CT_2;
-               break;
-       case MMC_READ_MULTIPLE_BLOCK:
-               mmccmd |= SD_CMD_CT_4;
-               break;
-       case MMC_WRITE_BLOCK:
-               mmccmd |= SD_CMD_CT_1;
-               break;
-
-       case MMC_WRITE_MULTIPLE_BLOCK:
-               mmccmd |= SD_CMD_CT_3;
-               break;
-       case MMC_STOP_TRANSMISSION:
-               mmccmd |= SD_CMD_CT_7;
-               break;
-       }
-
-       au_writel(cmd->arg, HOST_CMDARG(host));
-       au_sync();
-
-       if (wait)
-               IRQ_OFF(host, SD_CONFIG_CR);
-
-       au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
-       au_sync();
-
-       /* Wait for the command to go on the line */
-
-       while(1) {
-               if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO))
-                       break;
-       }
-
-       /* Wait for the command to come back */
-
-       if (wait) {
-               u32 status = au_readl(HOST_STATUS(host));
-
-               while(!(status & SD_STATUS_CR))
-                       status = au_readl(HOST_STATUS(host));
-
-               /* Clear the CR status */
-               au_writel(SD_STATUS_CR, HOST_STATUS(host));
-
-               IRQ_ON(host, SD_CONFIG_CR);
-       }
-
-       return MMC_ERR_NONE;
-}
-
-static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
-{
-
-       struct mmc_request *mrq = host->mrq;
-       struct mmc_data *data;
-       u32 crc;
-
-       WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP);
-
-       if (host->mrq == NULL)
-               return;
-
-       data = mrq->cmd->data;
-
-       if (status == 0)
-               status = au_readl(HOST_STATUS(host));
-
-       /* The transaction is really over when the SD_STATUS_DB bit is clear */
-
-       while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
-               status = au_readl(HOST_STATUS(host));
-
-       data->error = MMC_ERR_NONE;
-       dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
-
-        /* Process any errors */
-
-       crc = (status & (SD_STATUS_WC | SD_STATUS_RC));
-       if (host->flags & HOST_F_XMIT)
-               crc |= ((status & 0x07) == 0x02) ? 0 : 1;
-
-       if (crc)
-               data->error = MMC_ERR_BADCRC;
-
-       /* Clear the CRC bits */
-       au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
-
-       data->bytes_xfered = 0;
-
-       if (data->error == MMC_ERR_NONE) {
-               if (host->flags & HOST_F_DMA) {
-                       u32 chan = DMA_CHANNEL(host);
-
-                       chan_tab_t *c = *((chan_tab_t **) chan);
-                       au1x_dma_chan_t *cp = c->chan_ptr;
-                       data->bytes_xfered = cp->ddma_bytecnt;
-               }
-               else
-                       data->bytes_xfered =
-                               (data->blocks * data->blksz) -
-                               host->pio.len;
-       }
-
-       au1xmmc_finish_request(host);
-}
-
-static void au1xmmc_tasklet_data(unsigned long param)
-{
-       struct au1xmmc_host *host = (struct au1xmmc_host *) param;
-
-       u32 status = au_readl(HOST_STATUS(host));
-       au1xmmc_data_complete(host, status);
-}
-
-#define AU1XMMC_MAX_TRANSFER 8
-
-static void au1xmmc_send_pio(struct au1xmmc_host *host)
-{
-
-       struct mmc_data *data = 0;
-       int sg_len, max, count = 0;
-       unsigned char *sg_ptr;
-       u32 status = 0;
-       struct scatterlist *sg;
-
-       data = host->mrq->data;
-
-       if (!(host->flags & HOST_F_XMIT))
-               return;
-
-       /* This is the pointer to the data buffer */
-       sg = &data->sg[host->pio.index];
-       sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
-
-       /* This is the space left inside the buffer */
-       sg_len = data->sg[host->pio.index].length - host->pio.offset;
-
-       /* Check to if we need less then the size of the sg_buffer */
-
-       max = (sg_len > host->pio.len) ? host->pio.len : sg_len;
-       if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER;
-
-       for(count = 0; count < max; count++ ) {
-               unsigned char val;
-
-               status = au_readl(HOST_STATUS(host));
-
-               if (!(status & SD_STATUS_TH))
-                       break;
-
-               val = *sg_ptr++;
-
-               au_writel((unsigned long) val, HOST_TXPORT(host));
-               au_sync();
-       }
-
-       host->pio.len -= count;
-       host->pio.offset += count;
-
-       if (count == sg_len) {
-               host->pio.index++;
-               host->pio.offset = 0;
-       }
-
-       if (host->pio.len == 0) {
-               IRQ_OFF(host, SD_CONFIG_TH);
-
-               if (host->flags & HOST_F_STOP)
-                       SEND_STOP(host);
-
-               tasklet_schedule(&host->data_task);
-       }
-}
-
-static void au1xmmc_receive_pio(struct au1xmmc_host *host)
-{
-
-       struct mmc_data *data = 0;
-       int sg_len = 0, max = 0, count = 0;
-       unsigned char *sg_ptr = 0;
-       u32 status = 0;
-       struct scatterlist *sg;
-
-       data = host->mrq->data;
-
-       if (!(host->flags & HOST_F_RECV))
-               return;
-
-       max = host->pio.len;
-
-       if (host->pio.index < host->dma.len) {
-               sg = &data->sg[host->pio.index];
-               sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
-
-               /* This is the space left inside the buffer */
-               sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
-
-               /* Check to if we need less then the size of the sg_buffer */
-               if (sg_len < max) max = sg_len;
-       }
-
-       if (max > AU1XMMC_MAX_TRANSFER)
-               max = AU1XMMC_MAX_TRANSFER;
-
-       for(count = 0; count < max; count++ ) {
-               u32 val;
-               status = au_readl(HOST_STATUS(host));
-
-               if (!(status & SD_STATUS_NE))
-                       break;
-
-               if (status & SD_STATUS_RC) {
-                       DBG("RX CRC Error [%d + %d].\n", host->id,
-                                       host->pio.len, count);
-                       break;
-               }
-
-               if (status & SD_STATUS_RO) {
-                       DBG("RX Overrun [%d + %d]\n", host->id,
-                                       host->pio.len, count);
-                       break;
-               }
-               else if (status & SD_STATUS_RU) {
-                       DBG("RX Underrun [%d + %d]\n", host->id,
-                                       host->pio.len,  count);
-                       break;
-               }
-
-               val = au_readl(HOST_RXPORT(host));
-
-               if (sg_ptr)
-                       *sg_ptr++ = (unsigned char) (val & 0xFF);
-       }
-
-       host->pio.len -= count;
-       host->pio.offset += count;
-
-       if (sg_len && count == sg_len) {
-               host->pio.index++;
-               host->pio.offset = 0;
-       }
-
-       if (host->pio.len == 0) {
-               //IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF);
-               IRQ_OFF(host, SD_CONFIG_NE);
-
-               if (host->flags & HOST_F_STOP)
-                       SEND_STOP(host);
-
-               tasklet_schedule(&host->data_task);
-       }
-}
-
-/* static void au1xmmc_cmd_complete
-   This is called when a command has been completed - grab the response
-   and check for errors.  Then start the data transfer if it is indicated.
-*/
-
-static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
-{
-
-       struct mmc_request *mrq = host->mrq;
-       struct mmc_command *cmd;
-       int trans;
-
-       if (!host->mrq)
-               return;
-
-       cmd = mrq->cmd;
-       cmd->error = MMC_ERR_NONE;
-
-       if (cmd->flags & MMC_RSP_PRESENT) {
-               if (cmd->flags & MMC_RSP_136) {
-                       u32 r[4];
-                       int i;
-
-                       r[0] = au_readl(host->iobase + SD_RESP3);
-                       r[1] = au_readl(host->iobase + SD_RESP2);
-                       r[2] = au_readl(host->iobase + SD_RESP1);
-                       r[3] = au_readl(host->iobase + SD_RESP0);
-
-                       /* The CRC is omitted from the response, so really
-                        * we only got 120 bytes, but the engine expects
-                        * 128 bits, so we have to shift things up
-                        */
-
-                       for(i = 0; i < 4; i++) {
-                               cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
-                               if (i != 3)
-                                       cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
-                       }
-               } else {
-                       /* Techincally, we should be getting all 48 bits of
-                        * the response (SD_RESP1 + SD_RESP2), but because
-                        * our response omits the CRC, our data ends up
-                        * being shifted 8 bits to the right.  In this case,
-                        * that means that the OSR data starts at bit 31,
-                        * so we can just read RESP0 and return that
-                        */
-                       cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
-               }
-       }
-
-        /* Figure out errors */
-
-       if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC))
-               cmd->error = MMC_ERR_BADCRC;
-
-       trans = host->flags & (HOST_F_XMIT | HOST_F_RECV);
-
-       if (!trans || cmd->error != MMC_ERR_NONE) {
-
-               IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF);
-               tasklet_schedule(&host->finish_task);
-               return;
-       }
-
-       host->status = HOST_S_DATA;
-
-       if (host->flags & HOST_F_DMA) {
-               u32 channel = DMA_CHANNEL(host);
-
-               /* Start the DMA as soon as the buffer gets something in it */
-
-               if (host->flags & HOST_F_RECV) {
-                       u32 mask = SD_STATUS_DB | SD_STATUS_NE;
-
-                       while((status & mask) != mask)
-                               status = au_readl(HOST_STATUS(host));
-               }
-
-               au1xxx_dbdma_start(channel);
-       }
-}
-
-static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
-{
-
-       unsigned int pbus = get_au1x00_speed();
-       unsigned int divisor;
-       u32 config;
-
-       /* From databook:
-          divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
-       */
-
-       pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
-       pbus /= 2;
-
-       divisor = ((pbus / rate) / 2) - 1;
-
-       config = au_readl(HOST_CONFIG(host));
-
-       config &= ~(SD_CONFIG_DIV);
-       config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
-
-       au_writel(config, HOST_CONFIG(host));
-       au_sync();
-}
-
-static int
-au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
-{
-
-       int datalen = data->blocks * data->blksz;
-
-       if (dma != 0)
-               host->flags |= HOST_F_DMA;
-
-       if (data->flags & MMC_DATA_READ)
-               host->flags |= HOST_F_RECV;
-       else
-               host->flags |= HOST_F_XMIT;
-
-       if (host->mrq->stop)
-               host->flags |= HOST_F_STOP;
-
-       host->dma.dir = DMA_BIDIRECTIONAL;
-
-       host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                                  data->sg_len, host->dma.dir);
-
-       if (host->dma.len == 0)
-               return MMC_ERR_TIMEOUT;
-
-       au_writel(data->blksz - 1, HOST_BLKSIZE(host));
-
-       if (host->flags & HOST_F_DMA) {
-               int i;
-               u32 channel = DMA_CHANNEL(host);
-
-               au1xxx_dbdma_stop(channel);
-
-               for(i = 0; i < host->dma.len; i++) {
-                       u32 ret = 0, flags = DDMA_FLAGS_NOIE;
-                       struct scatterlist *sg = &data->sg[i];
-                       int sg_len = sg->length;
-
-                       int len = (datalen > sg_len) ? sg_len : datalen;
-
-                       if (i == host->dma.len - 1)
-                               flags = DDMA_FLAGS_IE;
-
-                       if (host->flags & HOST_F_XMIT){
-                               ret = au1xxx_dbdma_put_source_flags(channel,
-                                       (void *) (page_address(sg->page) +
-                                                 sg->offset),
-                                       len, flags);
-                       }
-                       else {
-                               ret = au1xxx_dbdma_put_dest_flags(channel,
-                                       (void *) (page_address(sg->page) +
-                                                 sg->offset),
-                                       len, flags);
-                       }
-
-                       if (!ret)
-                               goto dataerr;
-
-                       datalen -= len;
-               }
-       }
-       else {
-               host->pio.index = 0;
-               host->pio.offset = 0;
-               host->pio.len = datalen;
-
-               if (host->flags & HOST_F_XMIT)
-                       IRQ_ON(host, SD_CONFIG_TH);
-               else
-                       IRQ_ON(host, SD_CONFIG_NE);
-                       //IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);
-       }
-
-       return MMC_ERR_NONE;
-
- dataerr:
-       dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir);
-       return MMC_ERR_TIMEOUT;
-}
-
-/* static void au1xmmc_request
-   This actually starts a command or data transaction
-*/
-
-static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
-{
-
-       struct au1xmmc_host *host = mmc_priv(mmc);
-       int ret = MMC_ERR_NONE;
-
-       WARN_ON(irqs_disabled());
-       WARN_ON(host->status != HOST_S_IDLE);
-
-       host->mrq = mrq;
-       host->status = HOST_S_CMD;
-
-       bcsr->disk_leds &= ~(1 << 8);
-
-       if (mrq->data) {
-               FLUSH_FIFO(host);
-               ret = au1xmmc_prepare_data(host, mrq->data);
-       }
-
-       if (ret == MMC_ERR_NONE)
-               ret = au1xmmc_send_command(host, 0, mrq->cmd);
-
-       if (ret != MMC_ERR_NONE) {
-               mrq->cmd->error = ret;
-               au1xmmc_finish_request(host);
-       }
-}
-
-static void au1xmmc_reset_controller(struct au1xmmc_host *host)
-{
-
-       /* Apply the clock */
-       au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
-        au_sync_delay(1);
-
-       au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
-       au_sync_delay(5);
-
-       au_writel(~0, HOST_STATUS(host));
-       au_sync();
-
-       au_writel(0, HOST_BLKSIZE(host));
-       au_writel(0x001fffff, HOST_TIMEOUT(host));
-       au_sync();
-
-       au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-        au_sync();
-
-       au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
-       au_sync_delay(1);
-
-       au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-       au_sync();
-
-       /* Configure interrupts */
-       au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
-       au_sync();
-}
-
-
-static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
-{
-       struct au1xmmc_host *host = mmc_priv(mmc);
-
-       if (ios->power_mode == MMC_POWER_OFF)
-               au1xmmc_set_power(host, 0);
-       else if (ios->power_mode == MMC_POWER_ON) {
-               au1xmmc_set_power(host, 1);
-       }
-
-       if (ios->clock && ios->clock != host->clock) {
-               au1xmmc_set_clock(host, ios->clock);
-               host->clock = ios->clock;
-       }
-}
-
-static void au1xmmc_dma_callback(int irq, void *dev_id)
-{
-       struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
-
-       /* Avoid spurious interrupts */
-
-       if (!host->mrq)
-               return;
-
-       if (host->flags & HOST_F_STOP)
-               SEND_STOP(host);
-
-       tasklet_schedule(&host->data_task);
-}
-
-#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
-#define STATUS_DATA_IN  (SD_STATUS_NE)
-#define STATUS_DATA_OUT (SD_STATUS_TH)
-
-static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
-{
-
-       u32 status;
-       int i, ret = 0;
-
-       disable_irq(AU1100_SD_IRQ);
-
-       for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-               struct au1xmmc_host * host = au1xmmc_hosts[i];
-               u32 handled = 1;
-
-               status = au_readl(HOST_STATUS(host));
-
-               if (host->mrq && (status & STATUS_TIMEOUT)) {
-                       if (status & SD_STATUS_RAT)
-                               host->mrq->cmd->error = MMC_ERR_TIMEOUT;
-
-                       else if (status & SD_STATUS_DT)
-                               host->mrq->data->error = MMC_ERR_TIMEOUT;
-
-                       /* In PIO mode, interrupts might still be enabled */
-                       IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
-
-                       //IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
-                       tasklet_schedule(&host->finish_task);
-               }
-#if 0
-               else if (status & SD_STATUS_DD) {
-
-                       /* Sometimes we get a DD before a NE in PIO mode */
-
-                       if (!(host->flags & HOST_F_DMA) &&
-                                       (status & SD_STATUS_NE))
-                               au1xmmc_receive_pio(host);
-                       else {
-                               au1xmmc_data_complete(host, status);
-                               //tasklet_schedule(&host->data_task);
-                       }
-               }
-#endif
-               else if (status & (SD_STATUS_CR)) {
-                       if (host->status == HOST_S_CMD)
-                               au1xmmc_cmd_complete(host,status);
-               }
-               else if (!(host->flags & HOST_F_DMA)) {
-                       if ((host->flags & HOST_F_XMIT) &&
-                           (status & STATUS_DATA_OUT))
-                               au1xmmc_send_pio(host);
-                       else if ((host->flags & HOST_F_RECV) &&
-                           (status & STATUS_DATA_IN))
-                               au1xmmc_receive_pio(host);
-               }
-               else if (status & 0x203FBC70) {
-                       DBG("Unhandled status %8.8x\n", host->id, status);
-                       handled = 0;
-               }
-
-               au_writel(status, HOST_STATUS(host));
-               au_sync();
-
-               ret |= handled;
-       }
-
-       enable_irq(AU1100_SD_IRQ);
-       return ret;
-}
-
-static void au1xmmc_poll_event(unsigned long arg)
-{
-       struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
-
-       int card = au1xmmc_card_inserted(host);
-        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
-
-       if (card != controller) {
-               host->flags &= ~HOST_F_ACTIVE;
-               if (card) host->flags |= HOST_F_ACTIVE;
-               mmc_detect_change(host->mmc, 0);
-       }
-
-       if (host->mrq != NULL) {
-               u32 status = au_readl(HOST_STATUS(host));
-               DBG("PENDING - %8.8x\n", host->id, status);
-       }
-
-       mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
-}
-
-static dbdev_tab_t au1xmmc_mem_dbdev =
-{
-       DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
-};
-
-static void au1xmmc_init_dma(struct au1xmmc_host *host)
-{
-
-       u32 rxchan, txchan;
-
-       int txid = au1xmmc_card_table[host->id].tx_devid;
-       int rxid = au1xmmc_card_table[host->id].rx_devid;
-
-       /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
-          of 8 bits.  And since devices are shared, we need to create
-          our own to avoid freaking out other devices
-       */
-
-       int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
-
-       txchan = au1xxx_dbdma_chan_alloc(memid, txid,
-                                        au1xmmc_dma_callback, (void *) host);
-
-       rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
-                                        au1xmmc_dma_callback, (void *) host);
-
-       au1xxx_dbdma_set_devwidth(txchan, 8);
-       au1xxx_dbdma_set_devwidth(rxchan, 8);
-
-       au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
-       au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
-
-       host->tx_chan = txchan;
-       host->rx_chan = rxchan;
-}
-
-static const struct mmc_host_ops au1xmmc_ops = {
-       .request        = au1xmmc_request,
-       .set_ios        = au1xmmc_set_ios,
-       .get_ro         = au1xmmc_card_readonly,
-};
-
-static int __devinit au1xmmc_probe(struct platform_device *pdev)
-{
-
-       int i, ret = 0;
-
-       /* THe interrupt is shared among all controllers */
-       ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, IRQF_DISABLED, "MMC", 0);
-
-       if (ret) {
-               printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
-                               AU1100_SD_IRQ, ret);
-               return -ENXIO;
-       }
-
-       disable_irq(AU1100_SD_IRQ);
-
-       for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-               struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
-               struct au1xmmc_host *host = 0;
-
-               if (!mmc) {
-                       printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
-                       au1xmmc_hosts[i] = 0;
-                       continue;
-               }
-
-               mmc->ops = &au1xmmc_ops;
-
-               mmc->f_min =   450000;
-               mmc->f_max = 24000000;
-
-               mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
-               mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
-
-               mmc->max_blk_size = 2048;
-               mmc->max_blk_count = 512;
-
-               mmc->ocr_avail = AU1XMMC_OCR;
-
-               host = mmc_priv(mmc);
-               host->mmc = mmc;
-
-               host->id = i;
-               host->iobase = au1xmmc_card_table[host->id].iobase;
-               host->clock = 0;
-               host->power_mode = MMC_POWER_OFF;
-
-               host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
-               host->status = HOST_S_IDLE;
-
-               init_timer(&host->timer);
-
-               host->timer.function = au1xmmc_poll_event;
-               host->timer.data = (unsigned long) host;
-               host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
-
-               tasklet_init(&host->data_task, au1xmmc_tasklet_data,
-                               (unsigned long) host);
-
-               tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
-                               (unsigned long) host);
-
-               spin_lock_init(&host->lock);
-
-               if (dma != 0)
-                       au1xmmc_init_dma(host);
-
-               au1xmmc_reset_controller(host);
-
-               mmc_add_host(mmc);
-               au1xmmc_hosts[i] = host;
-
-               add_timer(&host->timer);
-
-               printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
-                      host->id, host->iobase, dma ? "dma" : "pio");
-       }
-
-       enable_irq(AU1100_SD_IRQ);
-
-       return 0;
-}
-
-static int __devexit au1xmmc_remove(struct platform_device *pdev)
-{
-
-       int i;
-
-       disable_irq(AU1100_SD_IRQ);
-
-       for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
-               struct au1xmmc_host *host = au1xmmc_hosts[i];
-               if (!host) continue;
-
-               tasklet_kill(&host->data_task);
-               tasklet_kill(&host->finish_task);
-
-               del_timer_sync(&host->timer);
-               au1xmmc_set_power(host, 0);
-
-               mmc_remove_host(host->mmc);
-
-               au1xxx_dbdma_chan_free(host->tx_chan);
-               au1xxx_dbdma_chan_free(host->rx_chan);
-
-               au_writel(0x0, HOST_ENABLE(host));
-               au_sync();
-       }
-
-       free_irq(AU1100_SD_IRQ, 0);
-       return 0;
-}
-
-static struct platform_driver au1xmmc_driver = {
-       .probe         = au1xmmc_probe,
-       .remove        = au1xmmc_remove,
-       .suspend       = NULL,
-       .resume        = NULL,
-       .driver        = {
-               .name  = DRIVER_NAME,
-       },
-};
-
-static int __init au1xmmc_init(void)
-{
-       return platform_driver_register(&au1xmmc_driver);
-}
-
-static void __exit au1xmmc_exit(void)
-{
-       platform_driver_unregister(&au1xmmc_driver);
-}
-
-module_init(au1xmmc_init);
-module_exit(au1xmmc_exit);
-
-#ifdef MODULE
-MODULE_AUTHOR("Advanced Micro Devices, Inc");
-MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
-MODULE_LICENSE("GPL");
-#endif
-
diff --git a/drivers/mmc/au1xmmc.h b/drivers/mmc/au1xmmc.h
deleted file mode 100644 (file)
index 341cbdf..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifndef _AU1XMMC_H_
-#define _AU1XMMC_H_
-
-/* Hardware definitions */
-
-#define AU1XMMC_DESCRIPTOR_COUNT 1
-#define AU1XMMC_DESCRIPTOR_SIZE  2048
-
-#define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30  | \
-                     MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33  | \
-                     MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)
-
-/* Easy access macros */
-
-#define HOST_STATUS(h) ((h)->iobase + SD_STATUS)
-#define HOST_CONFIG(h) ((h)->iobase + SD_CONFIG)
-#define HOST_ENABLE(h) ((h)->iobase + SD_ENABLE)
-#define HOST_TXPORT(h) ((h)->iobase + SD_TXPORT)
-#define HOST_RXPORT(h) ((h)->iobase + SD_RXPORT)
-#define HOST_CMDARG(h) ((h)->iobase + SD_CMDARG)
-#define HOST_BLKSIZE(h)        ((h)->iobase + SD_BLKSIZE)
-#define HOST_CMD(h)    ((h)->iobase + SD_CMD)
-#define HOST_CONFIG2(h)        ((h)->iobase + SD_CONFIG2)
-#define HOST_TIMEOUT(h)        ((h)->iobase + SD_TIMEOUT)
-#define HOST_DEBUG(h)  ((h)->iobase + SD_DEBUG)
-
-#define DMA_CHANNEL(h) \
-       ( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
-
-/* This gives us a hard value for the stop command that we can write directly
- * to the command register
- */
-
-#define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO)
-
-/* This is the set of interrupts that we configure by default */
-
-#if 0
-#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \
-               SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
-#endif
-
-#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \
-               SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
-/* The poll event (looking for insert/remove events runs twice a second */
-#define AU1XMMC_DETECT_TIMEOUT (HZ/2)
-
-struct au1xmmc_host {
-  struct mmc_host *mmc;
-  struct mmc_request *mrq;
-
-  u32 id;
-
-  u32 flags;
-  u32 iobase;
-  u32 clock;
-  u32 bus_width;
-  u32 power_mode;
-
-  int status;
-
-   struct {
-          int len;
-          int dir;
-  } dma;
-
-   struct {
-          int index;
-          int offset;
-          int len;
-  } pio;
-
-  u32 tx_chan;
-  u32 rx_chan;
-
-  struct timer_list timer;
-  struct tasklet_struct finish_task;
-  struct tasklet_struct data_task;
-
-  spinlock_t lock;
-};
-
-/* Status flags used by the host structure */
-
-#define HOST_F_XMIT   0x0001
-#define HOST_F_RECV   0x0002
-#define HOST_F_DMA    0x0010
-#define HOST_F_ACTIVE 0x0100
-#define HOST_F_STOP   0x1000
-
-#define HOST_S_IDLE   0x0001
-#define HOST_S_CMD    0x0002
-#define HOST_S_DATA   0x0003
-#define HOST_S_STOP   0x0004
-
-#endif
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
+
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
new file mode 100644 (file)
index 0000000..d24ab23
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ * 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
+ * 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!
+ *
+ * Author:  Andrew Christian
+ *          28 May 2002
+ */
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/hdreg.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/mutex.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 <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "queue.h"
+
+/*
+ * max 8 partitions per card
+ */
+#define MMC_SHIFT      3
+
+static int major;
+
+/*
+ * There is one mmc_blk_data per slot.
+ */
+struct mmc_blk_data {
+       spinlock_t      lock;
+       struct gendisk  *disk;
+       struct mmc_queue queue;
+
+       unsigned int    usage;
+       unsigned int    block_bits;
+       unsigned int    read_only;
+};
+
+static DEFINE_MUTEX(open_lock);
+
+static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
+{
+       struct mmc_blk_data *md;
+
+       mutex_lock(&open_lock);
+       md = disk->private_data;
+       if (md && md->usage == 0)
+               md = NULL;
+       if (md)
+               md->usage++;
+       mutex_unlock(&open_lock);
+
+       return md;
+}
+
+static void mmc_blk_put(struct mmc_blk_data *md)
+{
+       mutex_lock(&open_lock);
+       md->usage--;
+       if (md->usage == 0) {
+               put_disk(md->disk);
+               kfree(md);
+       }
+       mutex_unlock(&open_lock);
+}
+
+static int mmc_blk_open(struct inode *inode, struct file *filp)
+{
+       struct mmc_blk_data *md;
+       int ret = -ENXIO;
+
+       md = mmc_blk_get(inode->i_bdev->bd_disk);
+       if (md) {
+               if (md->usage == 2)
+                       check_disk_change(inode->i_bdev);
+               ret = 0;
+
+               if ((filp->f_mode & FMODE_WRITE) && md->read_only)
+                       ret = -EROFS;
+       }
+
+       return ret;
+}
+
+static int mmc_blk_release(struct inode *inode, struct file *filp)
+{
+       struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data;
+
+       mmc_blk_put(md);
+       return 0;
+}
+
+static int
+mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
+       geo->heads = 4;
+       geo->sectors = 16;
+       return 0;
+}
+
+static struct block_device_operations mmc_bdops = {
+       .open                   = mmc_blk_open,
+       .release                = mmc_blk_release,
+       .getgeo                 = mmc_blk_getgeo,
+       .owner                  = THIS_MODULE,
+};
+
+struct mmc_blk_request {
+       struct mmc_request      mrq;
+       struct mmc_command      cmd;
+       struct mmc_command      stop;
+       struct mmc_data         data;
+};
+
+static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
+{
+       struct mmc_blk_data *md = mq->data;
+       int stat = BLKPREP_OK;
+
+       /*
+        * If we have no device, we haven't finished initialising.
+        */
+       if (!md || !mq->card) {
+               printk(KERN_ERR "%s: killing request - no device/host\n",
+                      req->rq_disk->disk_name);
+               stat = BLKPREP_KILL;
+       }
+
+       return stat;
+}
+
+static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
+{
+       int err;
+       u32 blocks;
+
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       unsigned int timeout_us;
+
+       struct scatterlist sg;
+
+       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(card->host, &cmd, 0);
+       if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD))
+               return (u32)-1;
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       data.timeout_ns = card->csd.tacc_ns * 100;
+       data.timeout_clks = card->csd.tacc_clks * 100;
+
+       timeout_us = data.timeout_ns / 1000;
+       timeout_us += data.timeout_clks * 1000 /
+               (card->host->ios.clock / 1000);
+
+       if (timeout_us > 100000) {
+               data.timeout_ns = 100000000;
+               data.timeout_clks = 0;
+       }
+
+       data.blksz = 4;
+       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, &blocks, 4);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE)
+               return (u32)-1;
+
+       blocks = ntohl(blocks);
+
+       return blocks;
+}
+
+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, sg_pos, data_size;
+
+       mmc_claim_host(card->host);
+
+       do {
+               struct mmc_command cmd;
+               u32 readcmd, writecmd;
+
+               memset(&brq, 0, sizeof(struct mmc_blk_request));
+               brq.mrq.cmd = &brq.cmd;
+               brq.mrq.data = &brq.data;
+
+               brq.cmd.arg = req->sector;
+               if (!mmc_card_blockaddr(card))
+                       brq.cmd.arg <<= 9;
+               brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+               brq.data.blksz = 1 << md->block_bits;
+               brq.stop.opcode = MMC_STOP_TRANSMISSION;
+               brq.stop.arg = 0;
+               brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+               brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+               if (brq.data.blocks > card->host->max_blk_count)
+                       brq.data.blocks = card->host->max_blk_count;
+
+               mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
+
+               /*
+                * If the host doesn't support multiple block writes, force
+                * block writes to single block. SD cards are excepted from
+                * this rule as they support querying the number of
+                * successfully written sectors.
+                */
+               if (rq_data_dir(req) != READ &&
+                   !(card->host->caps & MMC_CAP_MULTIWRITE) &&
+                   !mmc_card_sd(card))
+                       brq.data.blocks = 1;
+
+               if (brq.data.blocks > 1) {
+                       brq.data.flags |= MMC_DATA_MULTI;
+                       brq.mrq.stop = &brq.stop;
+                       readcmd = MMC_READ_MULTIPLE_BLOCK;
+                       writecmd = MMC_WRITE_MULTIPLE_BLOCK;
+               } else {
+                       brq.mrq.stop = NULL;
+                       readcmd = MMC_READ_SINGLE_BLOCK;
+                       writecmd = MMC_WRITE_BLOCK;
+               }
+
+               if (rq_data_dir(req) == READ) {
+                       brq.cmd.opcode = readcmd;
+                       brq.data.flags |= MMC_DATA_READ;
+               } else {
+                       brq.cmd.opcode = writecmd;
+                       brq.data.flags |= MMC_DATA_WRITE;
+               }
+
+               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",
+                              req->rq_disk->disk_name, brq.cmd.error);
+                       goto cmd_err;
+               }
+
+               if (brq.data.error) {
+                       printk(KERN_ERR "%s: error %d transferring data\n",
+                              req->rq_disk->disk_name, brq.data.error);
+                       goto cmd_err;
+               }
+
+               if (brq.stop.error) {
+                       printk(KERN_ERR "%s: error %d sending stop command\n",
+                              req->rq_disk->disk_name, brq.stop.error);
+                       goto cmd_err;
+               }
+
+               if (rq_data_dir(req) != READ) {
+                       do {
+                               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(card->host, &cmd, 5);
+                               if (err) {
+                                       printk(KERN_ERR "%s: error %d requesting status\n",
+                                              req->rq_disk->disk_name, err);
+                                       goto cmd_err;
+                               }
+                       } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+
+#if 0
+                       if (cmd.resp[0] & ~0x00000900)
+                               printk(KERN_ERR "%s: status = %08x\n",
+                                      req->rq_disk->disk_name, cmd.resp[0]);
+                       if (mmc_decode_status(cmd.resp))
+                               goto cmd_err;
+#endif
+               }
+
+               /*
+                * A block was successfully transferred.
+                */
+               spin_lock_irq(&md->lock);
+               ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
+               if (!ret) {
+                       /*
+                        * The whole request completed successfully.
+                        */
+                       add_disk_randomness(req->rq_disk);
+                       blkdev_dequeue_request(req);
+                       end_that_request_last(req, 1);
+               }
+               spin_unlock_irq(&md->lock);
+       } while (ret);
+
+       mmc_release_host(card->host);
+
+       return 1;
+
+ cmd_err:
+       /*
+        * If this is an SD card and we're writing, we can first
+        * mark the known good sectors as ok.
+        *
+        * If the card is not SD, we can still ok written sectors
+        * if the controller can do proper error reporting.
+        *
+        * For reads we just fail the entire chunk as that should
+        * be safe in all cases.
+        */
+       if (rq_data_dir(req) != READ && mmc_card_sd(card)) {
+               u32 blocks;
+               unsigned int bytes;
+
+               blocks = mmc_sd_num_wr_blocks(card);
+               if (blocks != (u32)-1) {
+                       if (card->csd.write_partial)
+                               bytes = blocks << md->block_bits;
+                       else
+                               bytes = blocks << 9;
+                       spin_lock_irq(&md->lock);
+                       ret = end_that_request_chunk(req, 1, bytes);
+                       spin_unlock_irq(&md->lock);
+               }
+       } else if (rq_data_dir(req) != READ &&
+                  (card->host->caps & MMC_CAP_MULTIWRITE)) {
+               spin_lock_irq(&md->lock);
+               ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
+               spin_unlock_irq(&md->lock);
+       }
+
+       mmc_release_host(card->host);
+
+       spin_lock_irq(&md->lock);
+       while (ret) {
+               ret = end_that_request_chunk(req, 0,
+                               req->current_nr_sectors << 9);
+       }
+
+       add_disk_randomness(req->rq_disk);
+       blkdev_dequeue_request(req);
+       end_that_request_last(req, 0);
+       spin_unlock_irq(&md->lock);
+
+       return 0;
+}
+
+#define MMC_NUM_MINORS (256 >> MMC_SHIFT)
+
+static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
+
+static inline int mmc_blk_readonly(struct mmc_card *card)
+{
+       return mmc_card_readonly(card) ||
+              !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+}
+
+static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
+{
+       struct mmc_blk_data *md;
+       int devidx, ret;
+
+       devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);
+       if (devidx >= MMC_NUM_MINORS)
+               return ERR_PTR(-ENOSPC);
+       __set_bit(devidx, dev_use);
+
+       md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
+       if (!md) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       memset(md, 0, sizeof(struct mmc_blk_data));
+
+       /*
+        * Set the read-only status based on the supported commands
+        * and the write protect switch.
+        */
+       md->read_only = mmc_blk_readonly(card);
+
+       /*
+        * Both SD and MMC specifications state (although a bit
+        * unclearly in the MMC case) that a block size of 512
+        * bytes must always be supported by the card.
+        */
+       md->block_bits = 9;
+
+       md->disk = alloc_disk(1 << MMC_SHIFT);
+       if (md->disk == NULL) {
+               ret = -ENOMEM;
+               goto err_kfree;
+       }
+
+       spin_lock_init(&md->lock);
+       md->usage = 1;
+
+       ret = mmc_init_queue(&md->queue, card, &md->lock);
+       if (ret)
+               goto err_putdisk;
+
+       md->queue.prep_fn = mmc_blk_prep_rq;
+       md->queue.issue_fn = mmc_blk_issue_rq;
+       md->queue.data = md;
+
+       md->disk->major = major;
+       md->disk->first_minor = devidx << MMC_SHIFT;
+       md->disk->fops = &mmc_bdops;
+       md->disk->private_data = md;
+       md->disk->queue = md->queue.queue;
+       md->disk->driverfs_dev = &card->dev;
+
+       /*
+        * As discussed on lkml, GENHD_FL_REMOVABLE should:
+        *
+        * - be set for removable media with permanent block devices
+        * - be unset for removable block devices with permanent media
+        *
+        * Since MMC block devices clearly fall under the second
+        * case, we do not set GENHD_FL_REMOVABLE.  Userspace
+        * should use the block device creation/destruction hotplug
+        * messages to tell when the card is present.
+        */
+
+       sprintf(md->disk->disk_name, "mmcblk%d", devidx);
+
+       blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+
+       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:
+       put_disk(md->disk);
+ err_kfree:
+       kfree(md);
+ out:
+       return ERR_PTR(ret);
+}
+
+static int
+mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
+{
+       struct mmc_command cmd;
+       int err;
+
+       /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
+       if (mmc_card_blockaddr(card))
+               return 0;
+
+       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_release_host(card->host);
+
+       if (err) {
+               printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
+                       md->disk->disk_name, cmd.arg, err);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mmc_blk_probe(struct mmc_card *card)
+{
+       struct mmc_blk_data *md;
+       int err;
+
+       /*
+        * Check that the card supports the command class(es) we need.
+        */
+       if (!(card->csd.cmdclass & CCC_BLOCK_READ))
+               return -ENODEV;
+
+       md = mmc_blk_alloc(card);
+       if (IS_ERR(md))
+               return PTR_ERR(md);
+
+       err = mmc_blk_set_blksize(md, card);
+       if (err)
+               goto out;
+
+       printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
+               md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
+               (unsigned long long)(get_capacity(md->disk) >> 1),
+               md->read_only ? "(ro)" : "");
+
+       mmc_set_drvdata(card, md);
+       add_disk(md->disk);
+       return 0;
+
+ out:
+       mmc_blk_put(md);
+
+       return err;
+}
+
+static void mmc_blk_remove(struct mmc_card *card)
+{
+       struct mmc_blk_data *md = mmc_get_drvdata(card);
+
+       if (md) {
+               int devidx;
+
+               /* Stop new requests from getting into the queue */
+               del_gendisk(md->disk);
+
+               /* Then flush out any already in there */
+               mmc_cleanup_queue(&md->queue);
+
+               devidx = md->disk->first_minor >> MMC_SHIFT;
+               __clear_bit(devidx, dev_use);
+
+               mmc_blk_put(md);
+       }
+       mmc_set_drvdata(card, NULL);
+}
+
+#ifdef CONFIG_PM
+static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+{
+       struct mmc_blk_data *md = mmc_get_drvdata(card);
+
+       if (md) {
+               mmc_queue_suspend(&md->queue);
+       }
+       return 0;
+}
+
+static int mmc_blk_resume(struct mmc_card *card)
+{
+       struct mmc_blk_data *md = mmc_get_drvdata(card);
+
+       if (md) {
+               mmc_blk_set_blksize(md, card);
+               mmc_queue_resume(&md->queue);
+       }
+       return 0;
+}
+#else
+#define        mmc_blk_suspend NULL
+#define mmc_blk_resume NULL
+#endif
+
+static struct mmc_driver mmc_driver = {
+       .drv            = {
+               .name   = "mmcblk",
+       },
+       .probe          = mmc_blk_probe,
+       .remove         = mmc_blk_remove,
+       .suspend        = mmc_blk_suspend,
+       .resume         = mmc_blk_resume,
+};
+
+static int __init mmc_blk_init(void)
+{
+       int res = -ENOMEM;
+
+       res = register_blkdev(major, "mmc");
+       if (res < 0) {
+               printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",
+                      major, res);
+               goto out;
+       }
+       if (major == 0)
+               major = res;
+
+       return mmc_register_driver(&mmc_driver);
+
+ out:
+       return res;
+}
+
+static void __exit mmc_blk_exit(void)
+{
+       mmc_unregister_driver(&mmc_driver);
+       unregister_blkdev(major, "mmc");
+}
+
+module_init(mmc_blk_init);
+module_exit(mmc_blk_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
+
+module_param(major, int, 0444);
+MODULE_PARM_DESC(major, "specify the major device number for MMC block driver");
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
new file mode 100644 (file)
index 0000000..2e77963
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ *  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
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include "queue.h"
+
+#define MMC_QUEUE_SUSPENDED    (1 << 0)
+
+/*
+ * Prepare a MMC request.  Essentially, this means passing the
+ * preparation off to the media driver.  The media driver will
+ * create a mmc_io_request in req->special.
+ */
+static int mmc_prep_request(struct request_queue *q, struct request *req)
+{
+       struct mmc_queue *mq = q->queuedata;
+       int ret = BLKPREP_KILL;
+
+       if (blk_special_request(req)) {
+               /*
+                * Special commands already have the command
+                * blocks already setup in req->special.
+                */
+               BUG_ON(!req->special);
+
+               ret = BLKPREP_OK;
+       } else if (blk_fs_request(req) || blk_pc_request(req)) {
+               /*
+                * Block I/O requests need translating according
+                * to the protocol.
+                */
+               ret = mq->prep_fn(mq, req);
+       } else {
+               /*
+                * Everything else is invalid.
+                */
+               blk_dump_rq_flags(req, "MMC bad request");
+       }
+
+       if (ret == BLKPREP_OK)
+               req->cmd_flags |= REQ_DONTPREP;
+
+       return ret;
+}
+
+static int mmc_queue_thread(void *d)
+{
+       struct mmc_queue *mq = d;
+       struct request_queue *q = mq->queue;
+
+       /*
+        * Set iothread to ensure that we aren't put to sleep by
+        * the process freezing.  We handle suspension ourselves.
+        */
+       current->flags |= PF_MEMALLOC|PF_NOFREEZE;
+
+       down(&mq->thread_sem);
+       do {
+               struct request *req = NULL;
+
+               spin_lock_irq(q->queue_lock);
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (!blk_queue_plugged(q))
+                       req = elv_next_request(q);
+               mq->req = req;
+               spin_unlock_irq(q->queue_lock);
+
+               if (!req) {
+                       if (kthread_should_stop()) {
+                               set_current_state(TASK_RUNNING);
+                               break;
+                       }
+                       up(&mq->thread_sem);
+                       schedule();
+                       down(&mq->thread_sem);
+                       continue;
+               }
+               set_current_state(TASK_RUNNING);
+
+               mq->issue_fn(mq, req);
+       } while (1);
+       up(&mq->thread_sem);
+
+       return 0;
+}
+
+/*
+ * Generic MMC request handler.  This is called for any queue on a
+ * particular host.  When the host is not busy, we look for a request
+ * on any queue on this host, and attempt to issue it.  This may
+ * not be the queue we were asked to process.
+ */
+static void mmc_request(request_queue_t *q)
+{
+       struct mmc_queue *mq = q->queuedata;
+       struct request *req;
+       int ret;
+
+       if (!mq) {
+               printk(KERN_ERR "MMC: killing requests for dead queue\n");
+               while ((req = elv_next_request(q)) != NULL) {
+                       do {
+                               ret = end_that_request_chunk(req, 0,
+                                       req->current_nr_sectors << 9);
+                       } while (ret);
+               }
+               return;
+       }
+
+       if (!mq->req)
+               wake_up_process(mq->thread);
+}
+
+/**
+ * mmc_init_queue - initialise a queue structure.
+ * @mq: mmc queue
+ * @card: mmc card to attach this queue
+ * @lock: queue lock
+ *
+ * Initialise a MMC card request queue.
+ */
+int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)
+{
+       struct mmc_host *host = card->host;
+       u64 limit = BLK_BOUNCE_HIGH;
+       int ret;
+
+       if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
+               limit = *mmc_dev(host)->dma_mask;
+
+       mq->card = card;
+       mq->queue = blk_init_queue(mmc_request, lock);
+       if (!mq->queue)
+               return -ENOMEM;
+
+       blk_queue_prep_rq(mq->queue, mmc_prep_request);
+       blk_queue_bounce_limit(mq->queue, limit);
+       blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+       blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+       blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+       blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+       mq->queue->queuedata = mq;
+       mq->req = NULL;
+
+       mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
+                        GFP_KERNEL);
+       if (!mq->sg) {
+               ret = -ENOMEM;
+               goto cleanup_queue;
+       }
+
+       init_MUTEX(&mq->thread_sem);
+
+       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
+       if (IS_ERR(mq->thread)) {
+               ret = PTR_ERR(mq->thread);
+               goto free_sg;
+       }
+
+       return 0;
+
+ free_sg:
+       kfree(mq->sg);
+       mq->sg = NULL;
+ cleanup_queue:
+       blk_cleanup_queue(mq->queue);
+       return ret;
+}
+
+void mmc_cleanup_queue(struct mmc_queue *mq)
+{
+       request_queue_t *q = mq->queue;
+       unsigned long flags;
+
+       /* Mark that we should start throwing out stragglers */
+       spin_lock_irqsave(q->queue_lock, flags);
+       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);
+
+       kfree(mq->sg);
+       mq->sg = NULL;
+
+       blk_cleanup_queue(mq->queue);
+
+       mq->card = NULL;
+}
+EXPORT_SYMBOL(mmc_cleanup_queue);
+
+/**
+ * mmc_queue_suspend - suspend a MMC request queue
+ * @mq: MMC queue to suspend
+ *
+ * Stop the block request queue, and wait for our thread to
+ * complete any outstanding requests.  This ensures that we
+ * won't suspend while a request is being processed.
+ */
+void mmc_queue_suspend(struct mmc_queue *mq)
+{
+       request_queue_t *q = mq->queue;
+       unsigned long flags;
+
+       if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
+               mq->flags |= MMC_QUEUE_SUSPENDED;
+
+               spin_lock_irqsave(q->queue_lock, flags);
+               blk_stop_queue(q);
+               spin_unlock_irqrestore(q->queue_lock, flags);
+
+               down(&mq->thread_sem);
+       }
+}
+
+/**
+ * mmc_queue_resume - resume a previously suspended MMC request queue
+ * @mq: MMC queue to resume
+ */
+void mmc_queue_resume(struct mmc_queue *mq)
+{
+       request_queue_t *q = mq->queue;
+       unsigned long flags;
+
+       if (mq->flags & MMC_QUEUE_SUSPENDED) {
+               mq->flags &= ~MMC_QUEUE_SUSPENDED;
+
+               up(&mq->thread_sem);
+
+               spin_lock_irqsave(q->queue_lock, flags);
+               blk_start_queue(q);
+               spin_unlock_irqrestore(q->queue_lock, flags);
+       }
+}
+
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
new file mode 100644 (file)
index 0000000..c9f139e
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef MMC_QUEUE_H
+#define MMC_QUEUE_H
+
+struct request;
+struct task_struct;
+
+struct mmc_queue {
+       struct mmc_card         *card;
+       struct task_struct      *thread;
+       struct semaphore        thread_sem;
+       unsigned int            flags;
+       struct request          *req;
+       int                     (*prep_fn)(struct mmc_queue *, struct request *);
+       int                     (*issue_fn)(struct mmc_queue *, struct request *);
+       void                    *data;
+       struct request_queue    *queue;
+       struct scatterlist      *sg;
+};
+
+struct mmc_io_request {
+       struct request          *rq;
+       int                     num;
+       struct mmc_command      selcmd;         /* mmc_queue private */
+       struct mmc_command      cmd[4];         /* max 4 commands */
+};
+
+extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
+extern void mmc_cleanup_queue(struct mmc_queue *);
+extern void mmc_queue_suspend(struct mmc_queue *);
+extern void mmc_queue_resume(struct mmc_queue *);
+
+#endif
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
+
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c
new file mode 100644 (file)
index 0000000..843b1fb
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *  linux/drivers/mmc/core/sysfs.c
+ *
+ *  Copyright (C) 2003 Russell King, 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.
+ *
+ *  MMC sysfs/driver model support.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/workqueue.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.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)
+#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
+
+#define MMC_ATTR(name, fmt, args...)                                   \
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)        \
+{                                                                      \
+       struct mmc_card *card = dev_to_mmc_card(dev);                   \
+       return sprintf(buf, fmt, args);                                 \
+}
+
+MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+       card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+       card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR(name, "%s\n", card->cid.prod_name);
+MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
+
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
+
+static struct device_attribute mmc_dev_attrs[] = {
+       MMC_ATTR_RO(cid),
+       MMC_ATTR_RO(csd),
+       MMC_ATTR_RO(date),
+       MMC_ATTR_RO(fwrev),
+       MMC_ATTR_RO(hwrev),
+       MMC_ATTR_RO(manfid),
+       MMC_ATTR_RO(name),
+       MMC_ATTR_RO(oemid),
+       MMC_ATTR_RO(serial),
+       __ATTR_NULL
+};
+
+static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
+
+
+static void mmc_release_card(struct device *dev)
+{
+       struct mmc_card *card = dev_to_mmc_card(dev);
+
+       kfree(card);
+}
+
+/*
+ * This currently matches any MMC driver to any MMC card - drivers
+ * themselves make the decision whether to drive this card in their
+ * probe method.
+ */
+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+{
+       return 1;
+}
+
+static int
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
+               int buf_size)
+{
+       struct mmc_card *card = dev_to_mmc_card(dev);
+       char ccc[13];
+       int retval = 0, i = 0, length = 0;
+
+#define add_env(fmt,val) do {                                  \
+       retval = add_uevent_var(envp, num_envp, &i,             \
+                               buf, buf_size, &length,         \
+                               fmt, val);                      \
+       if (retval)                                             \
+               return retval;                                  \
+} while (0);
+
+       for (i = 0; i < 12; i++)
+               ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
+       ccc[12] = '\0';
+
+       add_env("MMC_CCC=%s", ccc);
+       add_env("MMC_MANFID=%06x", card->cid.manfid);
+       add_env("MMC_NAME=%s", mmc_card_name(card));
+       add_env("MMC_OEMID=%04x", card->cid.oemid);
+#undef add_env
+       envp[i] = NULL;
+
+       return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+{
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
+       struct mmc_card *card = dev_to_mmc_card(dev);
+       int ret = 0;
+
+       if (dev->driver && drv->suspend)
+               ret = drv->suspend(card, state);
+       return ret;
+}
+
+static int mmc_bus_resume(struct device *dev)
+{
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
+       struct mmc_card *card = dev_to_mmc_card(dev);
+       int ret = 0;
+
+       if (dev->driver && drv->resume)
+               ret = drv->resume(card);
+       return ret;
+}
+
+static int mmc_bus_probe(struct device *dev)
+{
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
+       struct mmc_card *card = dev_to_mmc_card(dev);
+
+       return drv->probe(card);
+}
+
+static int mmc_bus_remove(struct device *dev)
+{
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
+       struct mmc_card *card = dev_to_mmc_card(dev);
+
+       drv->remove(card);
+
+       return 0;
+}
+
+static struct bus_type mmc_bus_type = {
+       .name           = "mmc",
+       .dev_attrs      = mmc_dev_attrs,
+       .match          = mmc_bus_match,
+       .uevent         = mmc_bus_uevent,
+       .probe          = mmc_bus_probe,
+       .remove         = mmc_bus_remove,
+       .suspend        = mmc_bus_suspend,
+       .resume         = mmc_bus_resume,
+};
+
+/**
+ *     mmc_register_driver - register a media driver
+ *     @drv: MMC media driver
+ */
+int mmc_register_driver(struct mmc_driver *drv)
+{
+       drv->drv.bus = &mmc_bus_type;
+       return driver_register(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_register_driver);
+
+/**
+ *     mmc_unregister_driver - unregister a media driver
+ *     @drv: MMC media driver
+ */
+void mmc_unregister_driver(struct mmc_driver *drv)
+{
+       drv->drv.bus = &mmc_bus_type;
+       driver_unregister(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_unregister_driver);
+
+
+/*
+ * Internal function.  Initialise a MMC card structure.
+ */
+void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
+{
+       memset(card, 0, sizeof(struct mmc_card));
+       card->host = host;
+       device_initialize(&card->dev);
+       card->dev.parent = mmc_classdev(host);
+       card->dev.bus = &mmc_bus_type;
+       card->dev.release = mmc_release_card;
+}
+
+/*
+ * Internal function.  Register a new MMC card with the driver model.
+ */
+int mmc_register_card(struct mmc_card *card)
+{
+       int ret;
+
+       snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+                "%s:%04x", mmc_hostname(card->host), card->rca);
+
+       ret = device_add(&card->dev);
+       if (ret == 0) {
+               if (mmc_card_sd(card)) {
+                       ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
+                       if (ret)
+                               device_del(&card->dev);
+               }
+       }
+       if (ret == 0)
+               mmc_card_set_present(card);
+       return ret;
+}
+
+/*
+ * Internal function.  Unregister a new MMC card with the
+ * driver model, and (eventually) free it.
+ */
+void mmc_remove_card(struct mmc_card *card)
+{
+       if (mmc_card_present(card)) {
+               if (mmc_card_sd(card))
+                       device_remove_file(&card->dev, &mmc_dev_attr_scr);
+
+               device_del(&card->dev);
+       }
+
+       put_device(&card->dev);
+}
+
+
+static void mmc_host_classdev_release(struct device *dev)
+{
+       struct mmc_host *host = cls_dev_to_mmc_host(dev);
+       kfree(host);
+}
+
+static struct class mmc_host_class = {
+       .name           = "mmc_host",
+       .dev_release    = mmc_host_classdev_release,
+};
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/*
+ * Internal function. Allocate a new MMC host.
+ */
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
+{
+       struct mmc_host *host;
+
+       host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+       if (host) {
+               memset(host, 0, sizeof(struct mmc_host) + extra);
+
+               host->parent = dev;
+               host->class_dev.parent = dev;
+               host->class_dev.class = &mmc_host_class;
+               device_initialize(&host->class_dev);
+       }
+
+       return host;
+}
+
+/*
+ * Internal function. Register a new MMC host with the MMC class.
+ */
+int mmc_add_host_sysfs(struct mmc_host *host)
+{
+       int err;
+
+       if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+               return -ENOMEM;
+
+       spin_lock(&mmc_host_lock);
+       err = idr_get_new(&mmc_host_idr, host, &host->index);
+       spin_unlock(&mmc_host_lock);
+       if (err)
+               return err;
+
+       snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+                "mmc%d", host->index);
+
+       return device_add(&host->class_dev);
+}
+
+/*
+ * Internal function. Unregister a MMC host with the MMC class.
+ */
+void mmc_remove_host_sysfs(struct mmc_host *host)
+{
+       device_del(&host->class_dev);
+
+       spin_lock(&mmc_host_lock);
+       idr_remove(&mmc_host_idr, host->index);
+       spin_unlock(&mmc_host_lock);
+}
+
+/*
+ * Internal function. Free a MMC host.
+ */
+void mmc_free_host_sysfs(struct mmc_host *host)
+{
+       put_device(&host->class_dev);
+}
+
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
+{
+       return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+void mmc_flush_scheduled_work(void)
+{
+       flush_workqueue(workqueue);
+}
+
+static int __init mmc_init(void)
+{
+       int ret;
+
+       workqueue = create_singlethread_workqueue("kmmcd");
+       if (!workqueue)
+               return -ENOMEM;
+
+       ret = bus_register(&mmc_bus_type);
+       if (ret == 0) {
+               ret = class_register(&mmc_host_class);
+               if (ret)
+                       bus_unregister(&mmc_bus_type);
+       }
+       return ret;
+}
+
+static void __exit mmc_exit(void)
+{
+       class_unregister(&mmc_host_class);
+       bus_unregister(&mmc_bus_type);
+       destroy_workqueue(workqueue);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
new file mode 100644 (file)
index 0000000..80e29b3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  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_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);
+
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
+int mmc_add_host_sysfs(struct mmc_host *host);
+void mmc_remove_host_sysfs(struct mmc_host *host);
+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
+
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
new file mode 100644 (file)
index 0000000..e37943c
--- /dev/null
@@ -0,0 +1,1001 @@
+/*
+ *  linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver
+ *
+ *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
+ *
+ *  Copyright (C) 2006 Malcolm Noyes
+ *
+ * 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.
+ */
+
+/*
+   This is the AT91 MCI driver that has been tested with both MMC cards
+   and SD-cards.  Boards that support write protect are now supported.
+   The CCAT91SBC001 board does not support SD cards.
+
+   The three entry points are at91_mci_request, at91_mci_set_ios
+   and at91_mci_get_ro.
+
+   SET IOS
+     This configures the device to put it into the correct mode and clock speed
+     required.
+
+   MCI REQUEST
+     MCI request processes the commands sent in the mmc_request structure. This
+     can consist of a processing command and a stop command in the case of
+     multiple block transfers.
+
+     There are three main types of request, commands, reads and writes.
+
+     Commands are straight forward. The command is submitted to the controller and
+     the request function returns. When the controller generates an interrupt to indicate
+     the command is finished, the response to the command are read and the mmc_request_done
+     function called to end the request.
+
+     Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
+     controller to manage the transfers.
+
+     A read is done from the controller directly to the scatterlist passed in from the request.
+     Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
+     swapped in the scatterlist buffers.  AT91SAM926x are not affected by this bug.
+
+     The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
+
+     A write is slightly different in that the bytes to write are read from the scatterlist
+     into a dma memory buffer (this is in case the source buffer should be read only). The
+     entire write buffer is then done from this single dma memory buffer.
+
+     The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
+
+   GET RO
+     Gets the status of the write protect pin, if available.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/atmel_pdc.h>
+
+#include <linux/mmc/host.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/mmc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91_mci.h>
+
+#define DRIVER_NAME "at91_mci"
+
+#undef SUPPORT_4WIRE
+
+#define FL_SENT_COMMAND        (1 << 0)
+#define FL_SENT_STOP   (1 << 1)
+
+#define AT91_MCI_ERRORS        (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE       \
+               | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE               \
+               | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)                        
+
+#define at91_mci_read(host, reg)       __raw_readl((host)->baseaddr + (reg))
+#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
+
+
+/*
+ * Low level type for this driver
+ */
+struct at91mci_host
+{
+       struct mmc_host *mmc;
+       struct mmc_command *cmd;
+       struct mmc_request *request;
+
+       void __iomem *baseaddr;
+       int irq;
+
+       struct at91_mmc_data *board;
+       int present;
+
+       struct clk *mci_clk;
+
+       /*
+        * Flag indicating when the command has been sent. This is used to
+        * work out whether or not to send the stop
+        */
+       unsigned int flags;
+       /* flag for current bus settings */
+       u32 bus_mode;
+
+       /* DMA buffer used for transmitting */
+       unsigned int* buffer;
+       dma_addr_t physical_address;
+       unsigned int total_length;
+
+       /* Latest in the scatterlist that has been enabled for transfer, but not freed */
+       int in_use_index;
+
+       /* Latest in the scatterlist that has been enabled for transfer */
+       int transfer_index;
+};
+
+/*
+ * Copy from sg to a dma block - used for transfers
+ */
+static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+{
+       unsigned int len, i, size;
+       unsigned *dmabuf = host->buffer;
+
+       size = host->total_length;
+       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++) {
+               struct scatterlist *sg;
+               int amount;
+               unsigned int *sgbuffer;
+
+               sg = &data->sg[i];
+
+               sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+               amount = min(size, sg->length);
+               size -= amount;
+
+               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
+                       int index;
+
+                       for (index = 0; index < (amount / 4); index++)
+                               *dmabuf++ = swab32(sgbuffer[index]);
+               }
+               else
+                       memcpy(dmabuf, sgbuffer, amount);
+
+               kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+
+               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);
+}
+
+/*
+ * Prepare a dma read
+ */
+static void at91mci_pre_dma_read(struct at91mci_host *host)
+{
+       int i;
+       struct scatterlist *sg;
+       struct mmc_command *cmd;
+       struct mmc_data *data;
+
+       pr_debug("pre dma read\n");
+
+       cmd = host->cmd;
+       if (!cmd) {
+               pr_debug("no command\n");
+               return;
+       }
+
+       data = cmd->data;
+       if (!data) {
+               pr_debug("no data\n");
+               return;
+       }
+
+       for (i = 0; i < 2; i++) {
+               /* nothing left to transfer */
+               if (host->transfer_index >= data->sg_len) {
+                       pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
+                       break;
+               }
+
+               /* Check to see if this needs filling */
+               if (i == 0) {
+                       if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
+                               pr_debug("Transfer active in current\n");
+                               continue;
+                       }
+               }
+               else {
+                       if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
+                               pr_debug("Transfer active in next\n");
+                               continue;
+                       }
+               }
+
+               /* Setup the next transfer */
+               pr_debug("Using transfer index %d\n", host->transfer_index);
+
+               sg = &data->sg[host->transfer_index++];
+               pr_debug("sg = %p\n", sg);
+
+               sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
+
+               pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
+
+               if (i == 0) {
+                       at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
+                       at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4);
+               }
+               else {
+                       at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
+                       at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4);
+               }
+       }
+
+       pr_debug("pre dma read done\n");
+}
+
+/*
+ * Handle after a dma read
+ */
+static void at91mci_post_dma_read(struct at91mci_host *host)
+{
+       struct mmc_command *cmd;
+       struct mmc_data *data;
+
+       pr_debug("post dma read\n");
+
+       cmd = host->cmd;
+       if (!cmd) {
+               pr_debug("no command\n");
+               return;
+       }
+
+       data = cmd->data;
+       if (!data) {
+               pr_debug("no data\n");
+               return;
+       }
+
+       while (host->in_use_index < host->transfer_index) {
+               unsigned int *buffer;
+
+               struct scatterlist *sg;
+
+               pr_debug("finishing index %d\n", host->in_use_index);
+
+               sg = &data->sg[host->in_use_index++];
+
+               pr_debug("Unmapping page %08X\n", sg->dma_address);
+
+               dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
+
+               /* Swap the contents of the buffer */
+               buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+               pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
+
+               data->bytes_xfered += sg->length;
+
+               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
+                       int index;
+
+                       for (index = 0; index < (sg->length / 4); index++)
+                               buffer[index] = swab32(buffer[index]);
+               }
+
+               kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+               flush_dcache_page(sg->page);
+       }
+
+       /* Is there another transfer to trigger? */
+       if (host->transfer_index < data->sg_len)
+               at91mci_pre_dma_read(host);
+       else {
+               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+       }
+
+       pr_debug("post dma read done\n");
+}
+
+/*
+ * Handle transmitted data
+ */
+static void at91_mci_handle_transmitted(struct at91mci_host *host)
+{
+       struct mmc_command *cmd;
+       struct mmc_data *data;
+
+       pr_debug("Handling the transmit\n");
+
+       /* Disable the transfer */
+       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+
+       /* Now wait for cmd ready */
+       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
+       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
+       cmd = host->cmd;
+       if (!cmd) return;
+
+       data = cmd->data;
+       if (!data) return;
+
+       data->bytes_xfered = host->total_length;
+}
+
+/*
+ * Enable the controller
+ */
+static void at91_mci_enable(struct at91mci_host *host)
+{
+       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
+       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+       at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+       at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+
+       /* use Slot A or B (only one at same time) */
+       at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
+}
+
+/*
+ * Disable the controller
+ */
+static void at91_mci_disable(struct at91mci_host *host)
+{
+       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+}
+
+/*
+ * Send a command
+ * return the interrupts to enable
+ */
+static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+       unsigned int cmdr, mr;
+       unsigned int block_length;
+       struct mmc_data *data = cmd->data;
+
+       unsigned int blocks;
+       unsigned int ier = 0;
+
+       host->cmd = cmd;
+
+       /* Not sure if this is needed */
+#if 0
+       if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+               pr_debug("Clearing timeout\n");
+               at91_mci_write(host, AT91_MCI_ARGR, 0);
+               at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+               while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+                       /* spin */
+                       pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
+               }
+       }
+#endif
+       cmdr = cmd->opcode;
+
+       if (mmc_resp_type(cmd) == MMC_RSP_NONE)
+               cmdr |= AT91_MCI_RSPTYP_NONE;
+       else {
+               /* if a response is expected then allow maximum response latancy */
+               cmdr |= AT91_MCI_MAXLAT;
+               /* set 136 bit response for R2, 48 bit response otherwise */
+               if (mmc_resp_type(cmd) == MMC_RSP_R2)
+                       cmdr |= AT91_MCI_RSPTYP_136;
+               else
+                       cmdr |= AT91_MCI_RSPTYP_48;
+       }
+
+       if (data) {
+               block_length = data->blksz;
+               blocks = data->blocks;
+
+               /* always set data start - also set direction flag for read */
+               if (data->flags & MMC_DATA_READ)
+                       cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
+               else if (data->flags & MMC_DATA_WRITE)
+                       cmdr |= AT91_MCI_TRCMD_START;
+
+               if (data->flags & MMC_DATA_STREAM)
+                       cmdr |= AT91_MCI_TRTYP_STREAM;
+               if (data->flags & MMC_DATA_MULTI)
+                       cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+       }
+       else {
+               block_length = 0;
+               blocks = 0;
+       }
+
+       if (cmd->opcode == MMC_STOP_TRANSMISSION)
+               cmdr |= AT91_MCI_TRCMD_STOP;
+
+       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               cmdr |= AT91_MCI_OPDCMD;
+
+       /*
+        * Set the arguments and send the command
+        */
+       pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
+               cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
+
+       if (!data) {
+               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
+               at91_mci_write(host, ATMEL_PDC_RPR, 0);
+               at91_mci_write(host, ATMEL_PDC_RCR, 0);
+               at91_mci_write(host, ATMEL_PDC_RNPR, 0);
+               at91_mci_write(host, ATMEL_PDC_RNCR, 0);
+               at91_mci_write(host, ATMEL_PDC_TPR, 0);
+               at91_mci_write(host, ATMEL_PDC_TCR, 0);
+               at91_mci_write(host, ATMEL_PDC_TNPR, 0);
+               at91_mci_write(host, ATMEL_PDC_TNCR, 0);
+
+               at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+               at91_mci_write(host, AT91_MCI_CMDR, cmdr);
+               return AT91_MCI_CMDRDY;
+       }
+
+       mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
+       at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+
+       /*
+        * Disable the PDC controller
+        */
+       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+
+       if (cmdr & AT91_MCI_TRCMD_START) {
+               data->bytes_xfered = 0;
+               host->transfer_index = 0;
+               host->in_use_index = 0;
+               if (cmdr & AT91_MCI_TRDIR) {
+                       /*
+                        * Handle a read
+                        */
+                       host->buffer = NULL;
+                       host->total_length = 0;
+
+                       at91mci_pre_dma_read(host);
+                       ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+               }
+               else {
+                       /*
+                        * Handle a write
+                        */
+                       host->total_length = block_length * blocks;
+                       host->buffer = dma_alloc_coherent(NULL,
+                                                 host->total_length,
+                                                 &host->physical_address, GFP_KERNEL);
+
+                       at91mci_sg_to_dma(host, data);
+
+                       pr_debug("Transmitting %d bytes\n", host->total_length);
+
+                       at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+                       at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
+                       ier = AT91_MCI_TXBUFE;
+               }
+       }
+
+       /*
+        * Send the command and then enable the PDC - not the other way round as
+        * the data sheet says
+        */
+
+       at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+       at91_mci_write(host, AT91_MCI_CMDR, cmdr);
+
+       if (cmdr & AT91_MCI_TRCMD_START) {
+               if (cmdr & AT91_MCI_TRDIR)
+                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
+               else
+                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+       }
+       return ier;
+}
+
+/*
+ * Wait for a command to complete
+ */
+static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+       unsigned int ier;
+
+       ier = at91_mci_send_command(host, cmd);
+
+       pr_debug("setting ier to %08X\n", ier);
+
+       /* Stop on errors or the required value */
+       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
+}
+
+/*
+ * Process the next step in the request
+ */
+static void at91mci_process_next(struct at91mci_host *host)
+{
+       if (!(host->flags & FL_SENT_COMMAND)) {
+               host->flags |= FL_SENT_COMMAND;
+               at91mci_process_command(host, host->request->cmd);
+       }
+       else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
+               host->flags |= FL_SENT_STOP;
+               at91mci_process_command(host, host->request->stop);
+       }
+       else
+               mmc_request_done(host->mmc, host->request);
+}
+
+/*
+ * Handle a command that has been completed
+ */
+static void at91mci_completed_command(struct at91mci_host *host)
+{
+       struct mmc_command *cmd = host->cmd;
+       unsigned int status;
+
+       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+
+       cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
+       cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
+       cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
+       cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
+
+       if (host->buffer) {
+               dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+               host->buffer = NULL;
+       }
+
+       status = at91_mci_read(host, AT91_MCI_SR);
+
+       pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
+                status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+       if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
+                       AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
+                       AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
+               if ((status & AT91_MCI_RCRCE) &&
+                       ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+                       cmd->error = MMC_ERR_NONE;
+               }
+               else {
+                       if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
+                               cmd->error = MMC_ERR_TIMEOUT;
+                       else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
+                               cmd->error = MMC_ERR_BADCRC;
+                       else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
+                               cmd->error = MMC_ERR_FIFO;
+                       else
+                               cmd->error = MMC_ERR_FAILED;
+
+                       pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
+                                cmd->error, cmd->opcode, cmd->retries);
+               }
+       }
+       else
+               cmd->error = MMC_ERR_NONE;
+
+       at91mci_process_next(host);
+}
+
+/*
+ * Handle an MMC request
+ */
+static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct at91mci_host *host = mmc_priv(mmc);
+       host->request = mrq;
+       host->flags = 0;
+
+       at91mci_process_next(host);
+}
+
+/*
+ * Set the IOS
+ */
+static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       int clkdiv;
+       struct at91mci_host *host = mmc_priv(mmc);
+       unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
+
+       host->bus_mode = ios->bus_mode;
+
+       if (ios->clock == 0) {
+               /* Disable the MCI controller */
+               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
+               clkdiv = 0;
+       }
+       else {
+               /* Enable the MCI controller */
+               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
+
+               if ((at91_master_clock % (ios->clock * 2)) == 0)
+                       clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
+               else
+                       clkdiv = (at91_master_clock / ios->clock) / 2;
+
+               pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
+                       at91_master_clock / (2 * (clkdiv + 1)));
+       }
+       if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
+               pr_debug("MMC: Setting controller bus width to 4\n");
+               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+       }
+       else {
+               pr_debug("MMC: Setting controller bus width to 1\n");
+               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+       }
+
+       /* Set the clock divider */
+       at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+
+       /* maybe switch power to the card */
+       if (host->board->vcc_pin) {
+               switch (ios->power_mode) {
+                       case MMC_POWER_OFF:
+                               at91_set_gpio_value(host->board->vcc_pin, 0);
+                               break;
+                       case MMC_POWER_UP:
+                       case MMC_POWER_ON:
+                               at91_set_gpio_value(host->board->vcc_pin, 1);
+                               break;
+               }
+       }
+}
+
+/*
+ * Handle an interrupt
+ */
+static irqreturn_t at91_mci_irq(int irq, void *devid)
+{
+       struct at91mci_host *host = devid;
+       int completed = 0;
+       unsigned int int_status, int_mask;
+
+       int_status = at91_mci_read(host, AT91_MCI_SR);
+       int_mask = at91_mci_read(host, AT91_MCI_IMR);
+       
+       pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
+               int_status & int_mask);
+       
+       int_status = int_status & int_mask;
+
+       if (int_status & AT91_MCI_ERRORS) {
+               completed = 1;
+               
+               if (int_status & AT91_MCI_UNRE)
+                       pr_debug("MMC: Underrun error\n");
+               if (int_status & AT91_MCI_OVRE)
+                       pr_debug("MMC: Overrun error\n");
+               if (int_status & AT91_MCI_DTOE)
+                       pr_debug("MMC: Data timeout\n");
+               if (int_status & AT91_MCI_DCRCE)
+                       pr_debug("MMC: CRC error in data\n");
+               if (int_status & AT91_MCI_RTOE)
+                       pr_debug("MMC: Response timeout\n");
+               if (int_status & AT91_MCI_RENDE)
+                       pr_debug("MMC: Response end bit error\n");
+               if (int_status & AT91_MCI_RCRCE)
+                       pr_debug("MMC: Response CRC error\n");
+               if (int_status & AT91_MCI_RDIRE)
+                       pr_debug("MMC: Response direction error\n");
+               if (int_status & AT91_MCI_RINDE)
+                       pr_debug("MMC: Response index error\n");
+       } else {
+               /* Only continue processing if no errors */
+
+               if (int_status & AT91_MCI_TXBUFE) {
+                       pr_debug("TX buffer empty\n");
+                       at91_mci_handle_transmitted(host);
+               }
+
+               if (int_status & AT91_MCI_RXBUFF) {
+                       pr_debug("RX buffer full\n");
+                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+               }
+
+               if (int_status & AT91_MCI_ENDTX)
+                       pr_debug("Transmit has ended\n");
+
+               if (int_status & AT91_MCI_ENDRX) {
+                       pr_debug("Receive has ended\n");
+                       at91mci_post_dma_read(host);
+               }
+
+               if (int_status & AT91_MCI_NOTBUSY) {
+                       pr_debug("Card is ready\n");
+                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+               }
+
+               if (int_status & AT91_MCI_DTIP)
+                       pr_debug("Data transfer in progress\n");
+
+               if (int_status & AT91_MCI_BLKE)
+                       pr_debug("Block transfer has ended\n");
+
+               if (int_status & AT91_MCI_TXRDY)
+                       pr_debug("Ready to transmit\n");
+
+               if (int_status & AT91_MCI_RXRDY)
+                       pr_debug("Ready to receive\n");
+
+               if (int_status & AT91_MCI_CMDRDY) {
+                       pr_debug("Command ready\n");
+                       completed = 1;
+               }
+       }
+
+       if (completed) {
+               pr_debug("Completed command\n");
+               at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+               at91mci_completed_command(host);
+       } else
+               at91_mci_write(host, AT91_MCI_IDR, int_status);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
+{
+       struct at91mci_host *host = _host;
+       int present = !at91_get_gpio_value(irq);
+
+       /*
+        * we expect this irq on both insert and remove,
+        * and use a short delay to debounce.
+        */
+       if (present != host->present) {
+               host->present = present;
+               pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
+                       present ? "insert" : "remove");
+               if (!present) {
+                       pr_debug("****** Resetting SD-card bus width ******\n");
+                       at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+               }
+               mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+       }
+       return IRQ_HANDLED;
+}
+
+static int at91_mci_get_ro(struct mmc_host *mmc)
+{
+       int read_only = 0;
+       struct at91mci_host *host = mmc_priv(mmc);
+
+       if (host->board->wp_pin) {
+               read_only = at91_get_gpio_value(host->board->wp_pin);
+               printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
+                               (read_only ? "read-only" : "read-write") );
+       }
+       else {
+               printk(KERN_WARNING "%s: host does not support reading read-only "
+                               "switch.  Assuming write-enable.\n", mmc_hostname(mmc));
+       }
+       return read_only;
+}
+
+static const struct mmc_host_ops at91_mci_ops = {
+       .request        = at91_mci_request,
+       .set_ios        = at91_mci_set_ios,
+       .get_ro         = at91_mci_get_ro,
+};
+
+/*
+ * Probe for the device
+ */
+static int __init at91_mci_probe(struct platform_device *pdev)
+{
+       struct mmc_host *mmc;
+       struct at91mci_host *host;
+       struct resource *res;
+       int ret;
+
+       pr_debug("Probe MCI devices\n");
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENXIO;
+
+       if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
+               return -EBUSY;
+
+       mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
+       if (!mmc) {
+               pr_debug("Failed to allocate mmc host\n");
+               release_mem_region(res->start, res->end - res->start + 1);
+               return -ENOMEM;
+       }
+
+       mmc->ops = &at91_mci_ops;
+       mmc->f_min = 375000;
+       mmc->f_max = 25000000;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_BYTEBLOCK;
+
+       mmc->max_blk_size = 4095;
+       mmc->max_blk_count = mmc->max_req_size;
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+       host->buffer = NULL;
+       host->bus_mode = 0;
+       host->board = pdev->dev.platform_data;
+       if (host->board->wire4) {
+#ifdef SUPPORT_4WIRE
+               mmc->caps |= MMC_CAP_4_BIT_DATA;
+#else
+               printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+#endif
+       }
+
+       /*
+        * Get Clock
+        */
+       host->mci_clk = clk_get(&pdev->dev, "mci_clk");
+       if (IS_ERR(host->mci_clk)) {
+               printk(KERN_ERR "AT91 MMC: no clock defined.\n");
+               mmc_free_host(mmc);
+               release_mem_region(res->start, res->end - res->start + 1);
+               return -ENODEV;
+       }
+
+       /*
+        * Map I/O region
+        */
+       host->baseaddr = ioremap(res->start, res->end - res->start + 1);
+       if (!host->baseaddr) {
+               clk_put(host->mci_clk);
+               mmc_free_host(mmc);
+               release_mem_region(res->start, res->end - res->start + 1);
+               return -ENOMEM;
+       }
+
+       /*
+        * Reset hardware
+        */
+       clk_enable(host->mci_clk);              /* Enable the peripheral clock */
+       at91_mci_disable(host);
+       at91_mci_enable(host);
+
+       /*
+        * Allocate the MCI interrupt
+        */
+       host->irq = platform_get_irq(pdev, 0);
+       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+       if (ret) {
+               printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
+               clk_disable(host->mci_clk);
+               clk_put(host->mci_clk);
+               mmc_free_host(mmc);
+               iounmap(host->baseaddr);
+               release_mem_region(res->start, res->end - res->start + 1);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, mmc);
+
+       /*
+        * Add host to MMC layer
+        */
+       if (host->board->det_pin)
+               host->present = !at91_get_gpio_value(host->board->det_pin);
+       else
+               host->present = -1;
+
+       mmc_add_host(mmc);
+
+       /*
+        * monitor card insertion/removal if we can
+        */
+       if (host->board->det_pin) {
+               ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
+                               0, DRIVER_NAME, host);
+               if (ret)
+                       printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
+       }
+
+       pr_debug("Added MCI driver\n");
+
+       return 0;
+}
+
+/*
+ * Remove a device
+ */
+static int __exit at91_mci_remove(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       struct at91mci_host *host;
+       struct resource *res;
+
+       if (!mmc)
+               return -1;
+
+       host = mmc_priv(mmc);
+
+       if (host->present != -1) {
+               free_irq(host->board->det_pin, host);
+               cancel_delayed_work(&host->mmc->detect);
+       }
+
+       at91_mci_disable(host);
+       mmc_remove_host(mmc);
+       free_irq(host->irq, host);
+
+       clk_disable(host->mci_clk);                     /* Disable the peripheral clock */
+       clk_put(host->mci_clk);
+
+       iounmap(host->baseaddr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       mmc_free_host(mmc);
+       platform_set_drvdata(pdev, NULL);
+       pr_debug("MCI Removed\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       if (mmc)
+               ret = mmc_suspend_host(mmc, state);
+
+       return ret;
+}
+
+static int at91_mci_resume(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       if (mmc)
+               ret = mmc_resume_host(mmc);
+
+       return ret;
+}
+#else
+#define at91_mci_suspend       NULL
+#define at91_mci_resume                NULL
+#endif
+
+static struct platform_driver at91_mci_driver = {
+       .remove         = __exit_p(at91_mci_remove),
+       .suspend        = at91_mci_suspend,
+       .resume         = at91_mci_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init at91_mci_init(void)
+{
+       return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
+}
+
+static void __exit at91_mci_exit(void)
+{
+       platform_driver_unregister(&at91_mci_driver);
+}
+
+module_init(at91_mci_init);
+module_exit(at91_mci_exit);
+
+MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
+MODULE_AUTHOR("Nick Randell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
new file mode 100644 (file)
index 0000000..b7156a4
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver
+ *
+ *  Copyright (c) 2005, Advanced Micro Devices, Inc.
+ *
+ *  Developed with help from the 2.4.30 MMC AU1XXX controller including
+ *  the following copyright notices:
+ *     Copyright (c) 2003-2004 Embedded Edge, LLC.
+ *     Portions Copyright (C) 2002 Embedix, Inc
+ *     Copyright 2002 Hewlett-Packard Company
+
+ *  2.6 version of this driver inspired by:
+ *     (drivers/mmc/wbsd.c) Copyright (C) 2004-2005 Pierre Ossman,
+ *     All Rights Reserved.
+ *     (drivers/mmc/pxa.c) Copyright (C) 2003 Russell King,
+ *     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.
+ */
+
+/* Why is a timer used to detect insert events?
+ *
+ * From the AU1100 MMC application guide:
+ * If the Au1100-based design is intended to support both MultiMediaCards
+ * and 1- or 4-data bit SecureDigital cards, then the solution is to
+ * connect a weak (560KOhm) pull-up resistor to connector pin 1.
+ * In doing so, a MMC card never enters SPI-mode communications,
+ * but now the SecureDigital card-detect feature of CD/DAT3 is ineffective
+ * (the low to high transition will not occur).
+ *
+ * So we use the timer to check the status manually.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/mmc/host.h>
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/scatterlist.h>
+
+#include <au1xxx.h>
+#include "au1xmmc.h"
+
+#define DRIVER_NAME "au1xxx-mmc"
+
+/* Set this to enable special debugging macros */
+
+#ifdef DEBUG
+#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
+#else
+#define DBG(fmt, idx, args...)
+#endif
+
+const struct {
+       u32 iobase;
+       u32 tx_devid, rx_devid;
+       u16 bcsrpwr;
+       u16 bcsrstatus;
+       u16 wpstatus;
+} au1xmmc_card_table[] = {
+       { SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
+         BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
+#ifndef CONFIG_MIPS_DB1200
+       { SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
+         BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
+#endif
+};
+
+#define AU1XMMC_CONTROLLER_COUNT \
+       (sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
+
+/* This array stores pointers for the hosts (used by the IRQ handler) */
+struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
+static int dma = 1;
+
+#ifdef MODULE
+module_param(dma, bool, 0);
+MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
+#endif
+
+static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
+{
+       u32 val = au_readl(HOST_CONFIG(host));
+       val |= mask;
+       au_writel(val, HOST_CONFIG(host));
+       au_sync();
+}
+
+static inline void FLUSH_FIFO(struct au1xmmc_host *host)
+{
+       u32 val = au_readl(HOST_CONFIG2(host));
+
+       au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+       au_sync_delay(1);
+
+       /* SEND_STOP will turn off clock control - this re-enables it */
+       val &= ~SD_CONFIG2_DF;
+
+       au_writel(val, HOST_CONFIG2(host));
+       au_sync();
+}
+
+static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
+{
+       u32 val = au_readl(HOST_CONFIG(host));
+       val &= ~mask;
+       au_writel(val, HOST_CONFIG(host));
+       au_sync();
+}
+
+static inline void SEND_STOP(struct au1xmmc_host *host)
+{
+
+       /* We know the value of CONFIG2, so avoid a read we don't need */
+       u32 mask = SD_CONFIG2_EN;
+
+       WARN_ON(host->status != HOST_S_DATA);
+       host->status = HOST_S_STOP;
+
+       au_writel(mask | SD_CONFIG2_DF, HOST_CONFIG2(host));
+       au_sync();
+
+       /* Send the stop commmand */
+       au_writel(STOP_CMD, HOST_CMD(host));
+}
+
+static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
+{
+
+       u32 val = au1xmmc_card_table[host->id].bcsrpwr;
+
+       bcsr->board &= ~val;
+       if (state) bcsr->board |= val;
+
+       au_sync_delay(1);
+}
+
+static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
+{
+       return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
+               ? 1 : 0;
+}
+
+static int au1xmmc_card_readonly(struct mmc_host *mmc)
+{
+       struct au1xmmc_host *host = mmc_priv(mmc);
+       return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
+               ? 1 : 0;
+}
+
+static void au1xmmc_finish_request(struct au1xmmc_host *host)
+{
+
+       struct mmc_request *mrq = host->mrq;
+
+       host->mrq = NULL;
+       host->flags &= HOST_F_ACTIVE;
+
+       host->dma.len = 0;
+       host->dma.dir = 0;
+
+       host->pio.index  = 0;
+       host->pio.offset = 0;
+       host->pio.len = 0;
+
+       host->status = HOST_S_IDLE;
+
+       bcsr->disk_leds |= (1 << 8);
+
+       mmc_request_done(host->mmc, mrq);
+}
+
+static void au1xmmc_tasklet_finish(unsigned long param)
+{
+       struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+       au1xmmc_finish_request(host);
+}
+
+static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
+                               struct mmc_command *cmd)
+{
+
+       u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
+
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE:
+               break;
+       case MMC_RSP_R1:
+               mmccmd |= SD_CMD_RT_1;
+               break;
+       case MMC_RSP_R1B:
+               mmccmd |= SD_CMD_RT_1B;
+               break;
+       case MMC_RSP_R2:
+               mmccmd |= SD_CMD_RT_2;
+               break;
+       case MMC_RSP_R3:
+               mmccmd |= SD_CMD_RT_3;
+               break;
+       default:
+               printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
+                       mmc_resp_type(cmd));
+               return MMC_ERR_INVALID;
+       }
+
+       switch(cmd->opcode) {
+       case MMC_READ_SINGLE_BLOCK:
+       case SD_APP_SEND_SCR:
+               mmccmd |= SD_CMD_CT_2;
+               break;
+       case MMC_READ_MULTIPLE_BLOCK:
+               mmccmd |= SD_CMD_CT_4;
+               break;
+       case MMC_WRITE_BLOCK:
+               mmccmd |= SD_CMD_CT_1;
+               break;
+
+       case MMC_WRITE_MULTIPLE_BLOCK:
+               mmccmd |= SD_CMD_CT_3;
+               break;
+       case MMC_STOP_TRANSMISSION:
+               mmccmd |= SD_CMD_CT_7;
+               break;
+       }
+
+       au_writel(cmd->arg, HOST_CMDARG(host));
+       au_sync();
+
+       if (wait)
+               IRQ_OFF(host, SD_CONFIG_CR);
+
+       au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+       au_sync();
+
+       /* Wait for the command to go on the line */
+
+       while(1) {
+               if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO))
+                       break;
+       }
+
+       /* Wait for the command to come back */
+
+       if (wait) {
+               u32 status = au_readl(HOST_STATUS(host));
+
+               while(!(status & SD_STATUS_CR))
+                       status = au_readl(HOST_STATUS(host));
+
+               /* Clear the CR status */
+               au_writel(SD_STATUS_CR, HOST_STATUS(host));
+
+               IRQ_ON(host, SD_CONFIG_CR);
+       }
+
+       return MMC_ERR_NONE;
+}
+
+static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
+{
+
+       struct mmc_request *mrq = host->mrq;
+       struct mmc_data *data;
+       u32 crc;
+
+       WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP);
+
+       if (host->mrq == NULL)
+               return;
+
+       data = mrq->cmd->data;
+
+       if (status == 0)
+               status = au_readl(HOST_STATUS(host));
+
+       /* The transaction is really over when the SD_STATUS_DB bit is clear */
+
+       while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
+               status = au_readl(HOST_STATUS(host));
+
+       data->error = MMC_ERR_NONE;
+       dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
+
+        /* Process any errors */
+
+       crc = (status & (SD_STATUS_WC | SD_STATUS_RC));
+       if (host->flags & HOST_F_XMIT)
+               crc |= ((status & 0x07) == 0x02) ? 0 : 1;
+
+       if (crc)
+               data->error = MMC_ERR_BADCRC;
+
+       /* Clear the CRC bits */
+       au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+
+       data->bytes_xfered = 0;
+
+       if (data->error == MMC_ERR_NONE) {
+               if (host->flags & HOST_F_DMA) {
+                       u32 chan = DMA_CHANNEL(host);
+
+                       chan_tab_t *c = *((chan_tab_t **) chan);
+                       au1x_dma_chan_t *cp = c->chan_ptr;
+                       data->bytes_xfered = cp->ddma_bytecnt;
+               }
+               else
+                       data->bytes_xfered =
+                               (data->blocks * data->blksz) -
+                               host->pio.len;
+       }
+
+       au1xmmc_finish_request(host);
+}
+
+static void au1xmmc_tasklet_data(unsigned long param)
+{
+       struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+
+       u32 status = au_readl(HOST_STATUS(host));
+       au1xmmc_data_complete(host, status);
+}
+
+#define AU1XMMC_MAX_TRANSFER 8
+
+static void au1xmmc_send_pio(struct au1xmmc_host *host)
+{
+
+       struct mmc_data *data = 0;
+       int sg_len, max, count = 0;
+       unsigned char *sg_ptr;
+       u32 status = 0;
+       struct scatterlist *sg;
+
+       data = host->mrq->data;
+
+       if (!(host->flags & HOST_F_XMIT))
+               return;
+
+       /* This is the pointer to the data buffer */
+       sg = &data->sg[host->pio.index];
+       sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+
+       /* This is the space left inside the buffer */
+       sg_len = data->sg[host->pio.index].length - host->pio.offset;
+
+       /* Check to if we need less then the size of the sg_buffer */
+
+       max = (sg_len > host->pio.len) ? host->pio.len : sg_len;
+       if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER;
+
+       for(count = 0; count < max; count++ ) {
+               unsigned char val;
+
+               status = au_readl(HOST_STATUS(host));
+
+               if (!(status & SD_STATUS_TH))
+                       break;
+
+               val = *sg_ptr++;
+
+               au_writel((unsigned long) val, HOST_TXPORT(host));
+               au_sync();
+       }
+
+       host->pio.len -= count;
+       host->pio.offset += count;
+
+       if (count == sg_len) {
+               host->pio.index++;
+               host->pio.offset = 0;
+       }
+
+       if (host->pio.len == 0) {
+               IRQ_OFF(host, SD_CONFIG_TH);
+
+               if (host->flags & HOST_F_STOP)
+                       SEND_STOP(host);
+
+               tasklet_schedule(&host->data_task);
+       }
+}
+
+static void au1xmmc_receive_pio(struct au1xmmc_host *host)
+{
+
+       struct mmc_data *data = 0;
+       int sg_len = 0, max = 0, count = 0;
+       unsigned char *sg_ptr = 0;
+       u32 status = 0;
+       struct scatterlist *sg;
+
+       data = host->mrq->data;
+
+       if (!(host->flags & HOST_F_RECV))
+               return;
+
+       max = host->pio.len;
+
+       if (host->pio.index < host->dma.len) {
+               sg = &data->sg[host->pio.index];
+               sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+
+               /* This is the space left inside the buffer */
+               sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
+
+               /* Check to if we need less then the size of the sg_buffer */
+               if (sg_len < max) max = sg_len;
+       }
+
+       if (max > AU1XMMC_MAX_TRANSFER)
+               max = AU1XMMC_MAX_TRANSFER;
+
+       for(count = 0; count < max; count++ ) {
+               u32 val;
+               status = au_readl(HOST_STATUS(host));
+
+               if (!(status & SD_STATUS_NE))
+                       break;
+
+               if (status & SD_STATUS_RC) {
+                       DBG("RX CRC Error [%d + %d].\n", host->id,
+                                       host->pio.len, count);
+                       break;
+               }
+
+               if (status & SD_STATUS_RO) {
+                       DBG("RX Overrun [%d + %d]\n", host->id,
+                                       host->pio.len, count);
+                       break;
+               }
+               else if (status & SD_STATUS_RU) {
+                       DBG("RX Underrun [%d + %d]\n", host->id,
+                                       host->pio.len,  count);
+                       break;
+               }
+
+               val = au_readl(HOST_RXPORT(host));
+
+               if (sg_ptr)
+                       *sg_ptr++ = (unsigned char) (val & 0xFF);
+       }
+
+       host->pio.len -= count;
+       host->pio.offset += count;
+
+       if (sg_len && count == sg_len) {
+               host->pio.index++;
+               host->pio.offset = 0;
+       }
+
+       if (host->pio.len == 0) {
+               //IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF);
+               IRQ_OFF(host, SD_CONFIG_NE);
+
+               if (host->flags & HOST_F_STOP)
+                       SEND_STOP(host);
+
+               tasklet_schedule(&host->data_task);
+       }
+}
+
+/* static void au1xmmc_cmd_complete
+   This is called when a command has been completed - grab the response
+   and check for errors.  Then start the data transfer if it is indicated.
+*/
+
+static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
+{
+
+       struct mmc_request *mrq = host->mrq;
+       struct mmc_command *cmd;
+       int trans;
+
+       if (!host->mrq)
+               return;
+
+       cmd = mrq->cmd;
+       cmd->error = MMC_ERR_NONE;
+
+       if (cmd->flags & MMC_RSP_PRESENT) {
+               if (cmd->flags & MMC_RSP_136) {
+                       u32 r[4];
+                       int i;
+
+                       r[0] = au_readl(host->iobase + SD_RESP3);
+                       r[1] = au_readl(host->iobase + SD_RESP2);
+                       r[2] = au_readl(host->iobase + SD_RESP1);
+                       r[3] = au_readl(host->iobase + SD_RESP0);
+
+                       /* The CRC is omitted from the response, so really
+                        * we only got 120 bytes, but the engine expects
+                        * 128 bits, so we have to shift things up
+                        */
+
+                       for(i = 0; i < 4; i++) {
+                               cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
+                               if (i != 3)
+                                       cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+                       }
+               } else {
+                       /* Techincally, we should be getting all 48 bits of
+                        * the response (SD_RESP1 + SD_RESP2), but because
+                        * our response omits the CRC, our data ends up
+                        * being shifted 8 bits to the right.  In this case,
+                        * that means that the OSR data starts at bit 31,
+                        * so we can just read RESP0 and return that
+                        */
+                       cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+               }
+       }
+
+        /* Figure out errors */
+
+       if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC))
+               cmd->error = MMC_ERR_BADCRC;
+
+       trans = host->flags & (HOST_F_XMIT | HOST_F_RECV);
+
+       if (!trans || cmd->error != MMC_ERR_NONE) {
+
+               IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF);
+               tasklet_schedule(&host->finish_task);
+               return;
+       }
+
+       host->status = HOST_S_DATA;
+
+       if (host->flags & HOST_F_DMA) {
+               u32 channel = DMA_CHANNEL(host);
+
+               /* Start the DMA as soon as the buffer gets something in it */
+
+               if (host->flags & HOST_F_RECV) {
+                       u32 mask = SD_STATUS_DB | SD_STATUS_NE;
+
+                       while((status & mask) != mask)
+                               status = au_readl(HOST_STATUS(host));
+               }
+
+               au1xxx_dbdma_start(channel);
+       }
+}
+
+static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
+{
+
+       unsigned int pbus = get_au1x00_speed();
+       unsigned int divisor;
+       u32 config;
+
+       /* From databook:
+          divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
+       */
+
+       pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
+       pbus /= 2;
+
+       divisor = ((pbus / rate) / 2) - 1;
+
+       config = au_readl(HOST_CONFIG(host));
+
+       config &= ~(SD_CONFIG_DIV);
+       config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
+
+       au_writel(config, HOST_CONFIG(host));
+       au_sync();
+}
+
+static int
+au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
+{
+
+       int datalen = data->blocks * data->blksz;
+
+       if (dma != 0)
+               host->flags |= HOST_F_DMA;
+
+       if (data->flags & MMC_DATA_READ)
+               host->flags |= HOST_F_RECV;
+       else
+               host->flags |= HOST_F_XMIT;
+
+       if (host->mrq->stop)
+               host->flags |= HOST_F_STOP;
+
+       host->dma.dir = DMA_BIDIRECTIONAL;
+
+       host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+                                  data->sg_len, host->dma.dir);
+
+       if (host->dma.len == 0)
+               return MMC_ERR_TIMEOUT;
+
+       au_writel(data->blksz - 1, HOST_BLKSIZE(host));
+
+       if (host->flags & HOST_F_DMA) {
+               int i;
+               u32 channel = DMA_CHANNEL(host);
+
+               au1xxx_dbdma_stop(channel);
+
+               for(i = 0; i < host->dma.len; i++) {
+                       u32 ret = 0, flags = DDMA_FLAGS_NOIE;
+                       struct scatterlist *sg = &data->sg[i];
+                       int sg_len = sg->length;
+
+                       int len = (datalen > sg_len) ? sg_len : datalen;
+
+                       if (i == host->dma.len - 1)
+                               flags = DDMA_FLAGS_IE;
+
+                       if (host->flags & HOST_F_XMIT){
+                               ret = au1xxx_dbdma_put_source_flags(channel,
+                                       (void *) (page_address(sg->page) +
+                                                 sg->offset),
+                                       len, flags);
+                       }
+                       else {
+                               ret = au1xxx_dbdma_put_dest_flags(channel,
+                                       (void *) (page_address(sg->page) +
+                                                 sg->offset),
+                                       len, flags);
+                       }
+
+                       if (!ret)
+                               goto dataerr;
+
+                       datalen -= len;
+               }
+       }
+       else {
+               host->pio.index = 0;
+               host->pio.offset = 0;
+               host->pio.len = datalen;
+
+               if (host->flags & HOST_F_XMIT)
+                       IRQ_ON(host, SD_CONFIG_TH);
+               else
+                       IRQ_ON(host, SD_CONFIG_NE);
+                       //IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);
+       }
+
+       return MMC_ERR_NONE;
+
+ dataerr:
+       dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir);
+       return MMC_ERR_TIMEOUT;
+}
+
+/* static void au1xmmc_request
+   This actually starts a command or data transaction
+*/
+
+static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
+{
+
+       struct au1xmmc_host *host = mmc_priv(mmc);
+       int ret = MMC_ERR_NONE;
+
+       WARN_ON(irqs_disabled());
+       WARN_ON(host->status != HOST_S_IDLE);
+
+       host->mrq = mrq;
+       host->status = HOST_S_CMD;
+
+       bcsr->disk_leds &= ~(1 << 8);
+
+       if (mrq->data) {
+               FLUSH_FIFO(host);
+               ret = au1xmmc_prepare_data(host, mrq->data);
+       }
+
+       if (ret == MMC_ERR_NONE)
+               ret = au1xmmc_send_command(host, 0, mrq->cmd);
+
+       if (ret != MMC_ERR_NONE) {
+               mrq->cmd->error = ret;
+               au1xmmc_finish_request(host);
+       }
+}
+
+static void au1xmmc_reset_controller(struct au1xmmc_host *host)
+{
+
+       /* Apply the clock */
+       au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+        au_sync_delay(1);
+
+       au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+       au_sync_delay(5);
+
+       au_writel(~0, HOST_STATUS(host));
+       au_sync();
+
+       au_writel(0, HOST_BLKSIZE(host));
+       au_writel(0x001fffff, HOST_TIMEOUT(host));
+       au_sync();
+
+       au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+        au_sync();
+
+       au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+       au_sync_delay(1);
+
+       au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+       au_sync();
+
+       /* Configure interrupts */
+       au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+       au_sync();
+}
+
+
+static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
+{
+       struct au1xmmc_host *host = mmc_priv(mmc);
+
+       if (ios->power_mode == MMC_POWER_OFF)
+               au1xmmc_set_power(host, 0);
+       else if (ios->power_mode == MMC_POWER_ON) {
+               au1xmmc_set_power(host, 1);
+       }
+
+       if (ios->clock && ios->clock != host->clock) {
+               au1xmmc_set_clock(host, ios->clock);
+               host->clock = ios->clock;
+       }
+}
+
+static void au1xmmc_dma_callback(int irq, void *dev_id)
+{
+       struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
+
+       /* Avoid spurious interrupts */
+
+       if (!host->mrq)
+               return;
+
+       if (host->flags & HOST_F_STOP)
+               SEND_STOP(host);
+
+       tasklet_schedule(&host->data_task);
+}
+
+#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
+#define STATUS_DATA_IN  (SD_STATUS_NE)
+#define STATUS_DATA_OUT (SD_STATUS_TH)
+
+static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
+{
+
+       u32 status;
+       int i, ret = 0;
+
+       disable_irq(AU1100_SD_IRQ);
+
+       for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+               struct au1xmmc_host * host = au1xmmc_hosts[i];
+               u32 handled = 1;
+
+               status = au_readl(HOST_STATUS(host));
+
+               if (host->mrq && (status & STATUS_TIMEOUT)) {
+                       if (status & SD_STATUS_RAT)
+                               host->mrq->cmd->error = MMC_ERR_TIMEOUT;
+
+                       else if (status & SD_STATUS_DT)
+                               host->mrq->data->error = MMC_ERR_TIMEOUT;
+
+                       /* In PIO mode, interrupts might still be enabled */
+                       IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
+
+                       //IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
+                       tasklet_schedule(&host->finish_task);
+               }
+#if 0
+               else if (status & SD_STATUS_DD) {
+
+                       /* Sometimes we get a DD before a NE in PIO mode */
+
+                       if (!(host->flags & HOST_F_DMA) &&
+                                       (status & SD_STATUS_NE))
+                               au1xmmc_receive_pio(host);
+                       else {
+                               au1xmmc_data_complete(host, status);
+                               //tasklet_schedule(&host->data_task);
+                       }
+               }
+#endif
+               else if (status & (SD_STATUS_CR)) {
+                       if (host->status == HOST_S_CMD)
+                               au1xmmc_cmd_complete(host,status);
+               }
+               else if (!(host->flags & HOST_F_DMA)) {
+                       if ((host->flags & HOST_F_XMIT) &&
+                           (status & STATUS_DATA_OUT))
+                               au1xmmc_send_pio(host);
+                       else if ((host->flags & HOST_F_RECV) &&
+                           (status & STATUS_DATA_IN))
+                               au1xmmc_receive_pio(host);
+               }
+               else if (status & 0x203FBC70) {
+                       DBG("Unhandled status %8.8x\n", host->id, status);
+                       handled = 0;
+               }
+
+               au_writel(status, HOST_STATUS(host));
+               au_sync();
+
+               ret |= handled;
+       }
+
+       enable_irq(AU1100_SD_IRQ);
+       return ret;
+}
+
+static void au1xmmc_poll_event(unsigned long arg)
+{
+       struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
+
+       int card = au1xmmc_card_inserted(host);
+        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
+
+       if (card != controller) {
+               host->flags &= ~HOST_F_ACTIVE;
+               if (card) host->flags |= HOST_F_ACTIVE;
+               mmc_detect_change(host->mmc, 0);
+       }
+
+       if (host->mrq != NULL) {
+               u32 status = au_readl(HOST_STATUS(host));
+               DBG("PENDING - %8.8x\n", host->id, status);
+       }
+
+       mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
+}
+
+static dbdev_tab_t au1xmmc_mem_dbdev =
+{
+       DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
+};
+
+static void au1xmmc_init_dma(struct au1xmmc_host *host)
+{
+
+       u32 rxchan, txchan;
+
+       int txid = au1xmmc_card_table[host->id].tx_devid;
+       int rxid = au1xmmc_card_table[host->id].rx_devid;
+
+       /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+          of 8 bits.  And since devices are shared, we need to create
+          our own to avoid freaking out other devices
+       */
+
+       int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+
+       txchan = au1xxx_dbdma_chan_alloc(memid, txid,
+                                        au1xmmc_dma_callback, (void *) host);
+
+       rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
+                                        au1xmmc_dma_callback, (void *) host);
+
+       au1xxx_dbdma_set_devwidth(txchan, 8);
+       au1xxx_dbdma_set_devwidth(rxchan, 8);
+
+       au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
+       au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
+
+       host->tx_chan = txchan;
+       host->rx_chan = rxchan;
+}
+
+static const struct mmc_host_ops au1xmmc_ops = {
+       .request        = au1xmmc_request,
+       .set_ios        = au1xmmc_set_ios,
+       .get_ro         = au1xmmc_card_readonly,
+};
+
+static int __devinit au1xmmc_probe(struct platform_device *pdev)
+{
+
+       int i, ret = 0;
+
+       /* THe interrupt is shared among all controllers */
+       ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, IRQF_DISABLED, "MMC", 0);
+
+       if (ret) {
+               printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
+                               AU1100_SD_IRQ, ret);
+               return -ENXIO;
+       }
+
+       disable_irq(AU1100_SD_IRQ);
+
+       for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+               struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
+               struct au1xmmc_host *host = 0;
+
+               if (!mmc) {
+                       printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
+                       au1xmmc_hosts[i] = 0;
+                       continue;
+               }
+
+               mmc->ops = &au1xmmc_ops;
+
+               mmc->f_min =   450000;
+               mmc->f_max = 24000000;
+
+               mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
+               mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
+
+               mmc->max_blk_size = 2048;
+               mmc->max_blk_count = 512;
+
+               mmc->ocr_avail = AU1XMMC_OCR;
+
+               host = mmc_priv(mmc);
+               host->mmc = mmc;
+
+               host->id = i;
+               host->iobase = au1xmmc_card_table[host->id].iobase;
+               host->clock = 0;
+               host->power_mode = MMC_POWER_OFF;
+
+               host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
+               host->status = HOST_S_IDLE;
+
+               init_timer(&host->timer);
+
+               host->timer.function = au1xmmc_poll_event;
+               host->timer.data = (unsigned long) host;
+               host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
+
+               tasklet_init(&host->data_task, au1xmmc_tasklet_data,
+                               (unsigned long) host);
+
+               tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
+                               (unsigned long) host);
+
+               spin_lock_init(&host->lock);
+
+               if (dma != 0)
+                       au1xmmc_init_dma(host);
+
+               au1xmmc_reset_controller(host);
+
+               mmc_add_host(mmc);
+               au1xmmc_hosts[i] = host;
+
+               add_timer(&host->timer);
+
+               printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
+                      host->id, host->iobase, dma ? "dma" : "pio");
+       }
+
+       enable_irq(AU1100_SD_IRQ);
+
+       return 0;
+}
+
+static int __devexit au1xmmc_remove(struct platform_device *pdev)
+{
+
+       int i;
+
+       disable_irq(AU1100_SD_IRQ);
+
+       for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+               struct au1xmmc_host *host = au1xmmc_hosts[i];
+               if (!host) continue;
+
+               tasklet_kill(&host->data_task);
+               tasklet_kill(&host->finish_task);
+
+               del_timer_sync(&host->timer);
+               au1xmmc_set_power(host, 0);
+
+               mmc_remove_host(host->mmc);
+
+               au1xxx_dbdma_chan_free(host->tx_chan);
+               au1xxx_dbdma_chan_free(host->rx_chan);
+
+               au_writel(0x0, HOST_ENABLE(host));
+               au_sync();
+       }
+
+       free_irq(AU1100_SD_IRQ, 0);
+       return 0;
+}
+
+static struct platform_driver au1xmmc_driver = {
+       .probe         = au1xmmc_probe,
+       .remove        = au1xmmc_remove,
+       .suspend       = NULL,
+       .resume        = NULL,
+       .driver        = {
+               .name  = DRIVER_NAME,
+       },
+};
+
+static int __init au1xmmc_init(void)
+{
+       return platform_driver_register(&au1xmmc_driver);
+}
+
+static void __exit au1xmmc_exit(void)
+{
+       platform_driver_unregister(&au1xmmc_driver);
+}
+
+module_init(au1xmmc_init);
+module_exit(au1xmmc_exit);
+
+#ifdef MODULE
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
+MODULE_LICENSE("GPL");
+#endif
+
diff --git a/drivers/mmc/host/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
new file mode 100644 (file)
index 0000000..341cbdf
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef _AU1XMMC_H_
+#define _AU1XMMC_H_
+
+/* Hardware definitions */
+
+#define AU1XMMC_DESCRIPTOR_COUNT 1
+#define AU1XMMC_DESCRIPTOR_SIZE  2048
+
+#define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30  | \
+                     MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33  | \
+                     MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)
+
+/* Easy access macros */
+
+#define HOST_STATUS(h) ((h)->iobase + SD_STATUS)
+#define HOST_CONFIG(h) ((h)->iobase + SD_CONFIG)
+#define HOST_ENABLE(h) ((h)->iobase + SD_ENABLE)
+#define HOST_TXPORT(h) ((h)->iobase + SD_TXPORT)
+#define HOST_RXPORT(h) ((h)->iobase + SD_RXPORT)
+#define HOST_CMDARG(h) ((h)->iobase + SD_CMDARG)
+#define HOST_BLKSIZE(h)        ((h)->iobase + SD_BLKSIZE)
+#define HOST_CMD(h)    ((h)->iobase + SD_CMD)
+#define HOST_CONFIG2(h)        ((h)->iobase + SD_CONFIG2)
+#define HOST_TIMEOUT(h)        ((h)->iobase + SD_TIMEOUT)
+#define HOST_DEBUG(h)  ((h)->iobase + SD_DEBUG)
+
+#define DMA_CHANNEL(h) \
+       ( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
+
+/* This gives us a hard value for the stop command that we can write directly
+ * to the command register
+ */
+
+#define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO)
+
+/* This is the set of interrupts that we configure by default */
+
+#if 0
+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \
+               SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
+#endif
+
+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \
+               SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
+/* The poll event (looking for insert/remove events runs twice a second */
+#define AU1XMMC_DETECT_TIMEOUT (HZ/2)
+
+struct au1xmmc_host {
+  struct mmc_host *mmc;
+  struct mmc_request *mrq;
+
+  u32 id;
+
+  u32 flags;
+  u32 iobase;
+  u32 clock;
+  u32 bus_width;
+  u32 power_mode;
+
+  int status;
+
+   struct {
+          int len;
+          int dir;
+  } dma;
+
+   struct {
+          int index;
+          int offset;
+          int len;
+  } pio;
+
+  u32 tx_chan;
+  u32 rx_chan;
+
+  struct timer_list timer;
+  struct tasklet_struct finish_task;
+  struct tasklet_struct data_task;
+
+  spinlock_t lock;
+};
+
+/* Status flags used by the host structure */
+
+#define HOST_F_XMIT   0x0001
+#define HOST_F_RECV   0x0002
+#define HOST_F_DMA    0x0010
+#define HOST_F_ACTIVE 0x0100
+#define HOST_F_STOP   0x1000
+
+#define HOST_S_IDLE   0x0001
+#define HOST_S_CMD    0x0002
+#define HOST_S_DATA   0x0003
+#define HOST_S_STOP   0x0004
+
+#endif
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
new file mode 100644 (file)
index 0000000..7ee2045
--- /dev/null
@@ -0,0 +1,1137 @@
+/*
+ *  linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
+ *
+ *  Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
+ *  Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ *  derived from pxamci.c by Russell King
+ *
+ * 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.
+ *
+ *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Changed to conform redesigned i.MX scatter gather DMA interface
+ *
+ *  2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Updated for 2.6.14 kernel
+ *
+ *  2005-12-13 Jay Monkman <jtm@smoothsmoothie.com>
+ *             Found and corrected problems in the write path
+ *
+ *  2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             The event handling rewritten right way in softirq.
+ *             Added many ugly hacks and delays to overcome SDHC
+ *             deficiencies
+ *
+ */
+
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG
+#else
+#undef  DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/imx-dma.h>
+
+#include "imxmmc.h"
+
+#define DRIVER_NAME "imx-mmc"
+
+#define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \
+                     INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \
+                     INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO)
+
+struct imxmci_host {
+       struct mmc_host         *mmc;
+       spinlock_t              lock;
+       struct resource         *res;
+       int                     irq;
+       imx_dmach_t             dma;
+       unsigned int            clkrt;
+       unsigned int            cmdat;
+       volatile unsigned int   imask;
+       unsigned int            power_mode;
+       unsigned int            present;
+       struct imxmmc_platform_data *pdata;
+
+       struct mmc_request      *req;
+       struct mmc_command      *cmd;
+       struct mmc_data         *data;
+
+       struct timer_list       timer;
+       struct tasklet_struct   tasklet;
+       unsigned int            status_reg;
+       unsigned long           pending_events;
+       /* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */
+       u16                     *data_ptr;
+       unsigned int            data_cnt;
+       atomic_t                stuck_timeout;
+
+       unsigned int            dma_nents;
+       unsigned int            dma_size;
+       unsigned int            dma_dir;
+       int                     dma_allocated;
+
+       unsigned char           actual_bus_width;
+
+       int                     prev_cmd_code;
+};
+
+#define IMXMCI_PEND_IRQ_b      0
+#define IMXMCI_PEND_DMA_END_b  1
+#define IMXMCI_PEND_DMA_ERR_b  2
+#define IMXMCI_PEND_WAIT_RESP_b        3
+#define IMXMCI_PEND_DMA_DATA_b 4
+#define IMXMCI_PEND_CPU_DATA_b 5
+#define IMXMCI_PEND_CARD_XCHG_b        6
+#define IMXMCI_PEND_SET_INIT_b 7
+#define IMXMCI_PEND_STARTED_b  8
+
+#define IMXMCI_PEND_IRQ_m      (1 << IMXMCI_PEND_IRQ_b)
+#define IMXMCI_PEND_DMA_END_m  (1 << IMXMCI_PEND_DMA_END_b)
+#define IMXMCI_PEND_DMA_ERR_m  (1 << IMXMCI_PEND_DMA_ERR_b)
+#define IMXMCI_PEND_WAIT_RESP_m        (1 << IMXMCI_PEND_WAIT_RESP_b)
+#define IMXMCI_PEND_DMA_DATA_m (1 << IMXMCI_PEND_DMA_DATA_b)
+#define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b)
+#define IMXMCI_PEND_CARD_XCHG_m        (1 << IMXMCI_PEND_CARD_XCHG_b)
+#define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b)
+#define IMXMCI_PEND_STARTED_m  (1 << IMXMCI_PEND_STARTED_b)
+
+static void imxmci_stop_clock(struct imxmci_host *host)
+{
+       int i = 0;
+       MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK;
+       while(i < 0x1000) {
+               if(!(i & 0x7f))
+                       MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK;
+
+               if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) {
+                       /* Check twice before cut */
+                       if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN))
+                               return;
+               }
+
+               i++;
+       }
+       dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
+}
+
+static int imxmci_start_clock(struct imxmci_host *host)
+{
+       unsigned int trials = 0;
+       unsigned int delay_limit = 128;
+       unsigned long flags;
+
+       MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
+
+       clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
+
+       /*
+        * Command start of the clock, this usually succeeds in less
+        * then 6 delay loops, but during card detection (low clockrate)
+        * it takes up to 5000 delay loops and sometimes fails for the first time
+        */
+       MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+       do {
+               unsigned int delay = delay_limit;
+
+               while(delay--){
+                       if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+                               /* Check twice before cut */
+                               if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+                                       return 0;
+
+                       if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+                               return 0;
+               }
+
+               local_irq_save(flags);
+               /*
+                * Ensure, that request is not doubled under all possible circumstances.
+                * It is possible, that cock running state is missed, because some other
+                * IRQ or schedule delays this function execution and the clocks has
+                * been already stopped by other means (response processing, SDHC HW)
+                */
+               if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+                       MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+               local_irq_restore(flags);
+
+       } while(++trials<256);
+
+       dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+
+       return -1;
+}
+
+static void imxmci_softreset(void)
+{
+       /* reset sequence */
+       MMC_STR_STP_CLK = 0x8;
+       MMC_STR_STP_CLK = 0xD;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+       MMC_STR_STP_CLK = 0x5;
+
+       MMC_RES_TO = 0xff;
+       MMC_BLK_LEN = 512;
+       MMC_NOB = 1;
+}
+
+static int imxmci_busy_wait_for_status(struct imxmci_host *host,
+                       unsigned int *pstat, unsigned int stat_mask,
+                       int timeout, const char *where)
+{
+       int loops=0;
+       while(!(*pstat & stat_mask)) {
+               loops+=2;
+               if(loops >= timeout) {
+                       dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n",
+                               where, *pstat, stat_mask);
+                       return -1;
+               }
+               udelay(2);
+               *pstat |= MMC_STATUS;
+       }
+       if(!loops)
+               return 0;
+
+       /* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */
+       if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000))
+               dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
+                       loops, where, *pstat, stat_mask);
+       return loops;
+}
+
+static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
+{
+       unsigned int nob = data->blocks;
+       unsigned int blksz = data->blksz;
+       unsigned int datasz = nob * blksz;
+       int i;
+
+       if (data->flags & MMC_DATA_STREAM)
+               nob = 0xffff;
+
+       host->data = data;
+       data->bytes_xfered = 0;
+
+       MMC_NOB = nob;
+       MMC_BLK_LEN = blksz;
+
+       /*
+        * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise.
+        * We are in big troubles for non-512 byte transfers according to note in the paragraph
+        * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least.
+        * The situation is even more complex in reality. The SDHC in not able to handle wll
+        * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
+        * This is required for SCR read at least.
+        */
+       if (datasz < 512) {
+               host->dma_size = datasz;
+               if (data->flags & MMC_DATA_READ) {
+                       host->dma_dir = DMA_FROM_DEVICE;
+
+                       /* Hack to enable read SCR */
+                       MMC_NOB = 1;
+                       MMC_BLK_LEN = 512;
+               } else {
+                       host->dma_dir = DMA_TO_DEVICE;
+               }
+
+               /* Convert back to virtual address */
+               host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
+               host->data_cnt = 0;
+
+               clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+               set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+               return;
+       }
+
+       if (data->flags & MMC_DATA_READ) {
+               host->dma_dir = DMA_FROM_DEVICE;
+               host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+                                               data->sg_len,  host->dma_dir);
+
+               imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+                       host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ);
+
+               /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/
+               CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN;
+       } else {
+               host->dma_dir = DMA_TO_DEVICE;
+
+               host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+                                               data->sg_len,  host->dma_dir);
+
+               imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+                       host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE);
+
+               /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/
+               CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN;
+       }
+
+#if 1  /* This code is there only for consistency checking and can be disabled in future */
+       host->dma_size = 0;
+       for(i=0; i<host->dma_nents; i++)
+               host->dma_size+=data->sg[i].length;
+
+       if (datasz > host->dma_size) {
+               dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n",
+                      datasz, host->dma_size);
+       }
+#endif
+
+       host->dma_size = datasz;
+
+       wmb();
+
+       if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+               BLR(host->dma) = 0;     /* burst 64 byte read / 64 bytes write */
+       else
+               BLR(host->dma) = 16;    /* burst 16 byte read / 16 bytes write */
+
+       RSSR(host->dma) = DMA_REQ_SDHC;
+
+       set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+       clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+       /* start DMA engine for read, write is delayed after initial response */
+       if (host->dma_dir == DMA_FROM_DEVICE) {
+               imx_dma_enable(host->dma);
+       }
+}
+
+static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+       unsigned long flags;
+       u32 imask;
+
+       WARN_ON(host->cmd != NULL);
+       host->cmd = cmd;
+
+       /* Ensure, that clock are stopped else command programming and start fails */
+       imxmci_stop_clock(host);
+
+       if (cmd->flags & MMC_RSP_BUSY)
+               cmdat |= CMD_DAT_CONT_BUSY;
+
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_R1: /* short CRC, OPCODE */
+       case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
+               cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
+               break;
+       case MMC_RSP_R2: /* long 136 bit + CRC */
+               cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
+               break;
+       case MMC_RSP_R3: /* short */
+               cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
+               break;
+       default:
+               break;
+       }
+
+       if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
+               cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */
+
+       if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
+               cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+
+       MMC_CMD = cmd->opcode;
+       MMC_ARGH = cmd->arg >> 16;
+       MMC_ARGL = cmd->arg & 0xffff;
+       MMC_CMD_DAT_CONT = cmdat;
+
+       atomic_set(&host->stuck_timeout, 0);
+       set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);
+
+
+       imask = IMXMCI_INT_MASK_DEFAULT;
+       imask &= ~INT_MASK_END_CMD_RES;
+       if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
+               /*imask &= ~INT_MASK_BUF_READY;*/
+               imask &= ~INT_MASK_DATA_TRAN;
+               if ( cmdat & CMD_DAT_CONT_WRITE )
+                       imask &= ~INT_MASK_WRITE_OP_DONE;
+               if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+                       imask &= ~INT_MASK_BUF_READY;
+       }
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->imask = imask;
+       MMC_INT_MASK = host->imask;
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
+               cmd->opcode, cmd->opcode, imask);
+
+       imxmci_start_clock(host);
+}
+
+static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m |
+                       IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m);
+
+       host->imask = IMXMCI_INT_MASK_DEFAULT;
+       MMC_INT_MASK = host->imask;
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       if(req && req->cmd)
+               host->prev_cmd_code = req->cmd->opcode;
+
+       host->req = NULL;
+       host->cmd = NULL;
+       host->data = NULL;
+       mmc_request_done(host->mmc, req);
+}
+
+static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat)
+{
+       struct mmc_data *data = host->data;
+       int data_error;
+
+       if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){
+               imx_dma_disable(host->dma);
+               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+                            host->dma_dir);
+       }
+
+       if ( stat & STATUS_ERR_MASK ) {
+               dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat);
+               if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR))
+                       data->error = MMC_ERR_BADCRC;
+               else if(stat & STATUS_TIME_OUT_READ)
+                       data->error = MMC_ERR_TIMEOUT;
+               else
+                       data->error = MMC_ERR_FAILED;
+       } else {
+               data->bytes_xfered = host->dma_size;
+       }
+
+       data_error = data->error;
+
+       host->data = NULL;
+
+       return data_error;
+}
+
+static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat)
+{
+       struct mmc_command *cmd = host->cmd;
+       int i;
+       u32 a,b,c;
+       struct mmc_data *data = host->data;
+
+       if (!cmd)
+               return 0;
+
+       host->cmd = NULL;
+
+       if (stat & STATUS_TIME_OUT_RESP) {
+               dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
+               cmd->error = MMC_ERR_TIMEOUT;
+       } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+               dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
+               cmd->error = MMC_ERR_BADCRC;
+       }
+
+       if(cmd->flags & MMC_RSP_PRESENT) {
+               if(cmd->flags & MMC_RSP_136) {
+                       for (i = 0; i < 4; i++) {
+                               u32 a = MMC_RES_FIFO & 0xffff;
+                               u32 b = MMC_RES_FIFO & 0xffff;
+                               cmd->resp[i] = a<<16 | b;
+                       }
+               } else {
+                       a = MMC_RES_FIFO & 0xffff;
+                       b = MMC_RES_FIFO & 0xffff;
+                       c = MMC_RES_FIFO & 0xffff;
+                       cmd->resp[0] = a<<24 | b<<8 | c>>8;
+               }
+       }
+
+       dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n",
+               cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
+
+       if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) {
+               if (host->req->data->flags & MMC_DATA_WRITE) {
+
+                       /* Wait for FIFO to be empty before starting DMA write */
+
+                       stat = MMC_STATUS;
+                       if(imxmci_busy_wait_for_status(host, &stat,
+                               STATUS_APPL_BUFF_FE,
+                               40, "imxmci_cmd_done DMA WR") < 0) {
+                               cmd->error = MMC_ERR_FIFO;
+                               imxmci_finish_data(host, stat);
+                               if(host->req)
+                                       imxmci_finish_request(host, host->req);
+                               dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n",
+                                      stat);
+                               return 0;
+                       }
+
+                       if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+                               imx_dma_enable(host->dma);
+                       }
+               }
+       } else {
+               struct mmc_request *req;
+               imxmci_stop_clock(host);
+               req = host->req;
+
+               if(data)
+                       imxmci_finish_data(host, stat);
+
+               if( req ) {
+                       imxmci_finish_request(host, req);
+               } else {
+                       dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n");
+               }
+       }
+
+       return 1;
+}
+
+static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
+{
+       struct mmc_data *data = host->data;
+       int data_error;
+
+       if (!data)
+               return 0;
+
+       data_error = imxmci_finish_data(host, stat);
+
+       if (host->req->stop) {
+               imxmci_stop_clock(host);
+               imxmci_start_cmd(host, host->req->stop, 0);
+       } else {
+               struct mmc_request *req;
+               req = host->req;
+               if( req ) {
+                       imxmci_finish_request(host, req);
+               } else {
+                       dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n");
+               }
+       }
+
+       return 1;
+}
+
+static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
+{
+       int i;
+       int burst_len;
+       int trans_done = 0;
+       unsigned int stat = *pstat;
+
+       if(host->actual_bus_width != MMC_BUS_WIDTH_4)
+               burst_len = 16;
+       else
+               burst_len = 64;
+
+       /* This is unfortunately required */
+       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
+               stat);
+
+       udelay(20);     /* required for clocks < 8MHz*/
+
+       if(host->dma_dir == DMA_FROM_DEVICE) {
+               imxmci_busy_wait_for_status(host, &stat,
+                               STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE |
+                               STATUS_TIME_OUT_READ,
+                               50, "imxmci_cpu_driven_data read");
+
+               while((stat & (STATUS_APPL_BUFF_FF |  STATUS_DATA_TRANS_DONE)) &&
+                     !(stat & STATUS_TIME_OUT_READ) &&
+                     (host->data_cnt < 512)) {
+
+                       udelay(20);     /* required for clocks < 8MHz*/
+
+                       for(i = burst_len; i>=2 ; i-=2) {
+                               u16 data;
+                               data = MMC_BUFFER_ACCESS;
+                               udelay(10);     /* required for clocks < 8MHz*/
+                               if(host->data_cnt+2 <= host->dma_size) {
+                                       *(host->data_ptr++) = data;
+                               } else {
+                                       if(host->data_cnt < host->dma_size)
+                                               *(u8*)(host->data_ptr) = data;
+                               }
+                               host->data_cnt += 2;
+                       }
+
+                       stat = MMC_STATUS;
+
+                       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n",
+                               host->data_cnt, burst_len, stat);
+               }
+
+               if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512))
+                       trans_done = 1;
+
+               if(host->dma_size & 0x1ff)
+                       stat &= ~STATUS_CRC_READ_ERR;
+
+               if(stat & STATUS_TIME_OUT_READ) {
+                       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read timeout STATUS = 0x%x\n",
+                               stat);
+                       trans_done = -1;
+               }
+
+       } else {
+               imxmci_busy_wait_for_status(host, &stat,
+                               STATUS_APPL_BUFF_FE,
+                               20, "imxmci_cpu_driven_data write");
+
+               while((stat & STATUS_APPL_BUFF_FE) &&
+                     (host->data_cnt < host->dma_size)) {
+                       if(burst_len >= host->dma_size - host->data_cnt) {
+                               burst_len = host->dma_size - host->data_cnt;
+                               host->data_cnt = host->dma_size;
+                               trans_done = 1;
+                       } else {
+                               host->data_cnt += burst_len;
+                       }
+
+                       for(i = burst_len; i>0 ; i-=2)
+                               MMC_BUFFER_ACCESS = *(host->data_ptr++);
+
+                       stat = MMC_STATUS;
+
+                       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n",
+                               burst_len, stat);
+               }
+       }
+
+       *pstat = stat;
+
+       return trans_done;
+}
+
+static void imxmci_dma_irq(int dma, void *devid)
+{
+       struct imxmci_host *host = devid;
+       uint32_t stat = MMC_STATUS;
+
+       atomic_set(&host->stuck_timeout, 0);
+       host->status_reg = stat;
+       set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+       tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t imxmci_irq(int irq, void *devid)
+{
+       struct imxmci_host *host = devid;
+       uint32_t stat = MMC_STATUS;
+       int handled = 1;
+
+       MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT;
+
+       atomic_set(&host->stuck_timeout, 0);
+       host->status_reg = stat;
+       set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+       set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
+       tasklet_schedule(&host->tasklet);
+
+       return IRQ_RETVAL(handled);;
+}
+
+static void imxmci_tasklet_fnc(unsigned long data)
+{
+       struct imxmci_host *host = (struct imxmci_host *)data;
+       u32 stat;
+       unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */
+       int timeout = 0;
+
+       if(atomic_read(&host->stuck_timeout) > 4) {
+               char *what;
+               timeout = 1;
+               stat = MMC_STATUS;
+               host->status_reg = stat;
+               if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+                       if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+                               what = "RESP+DMA";
+                       else
+                               what = "RESP";
+               else
+                       if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+                               if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
+                                       what = "DATA";
+                               else
+                                       what = "DMA";
+                       else
+                               what = "???";
+
+               dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
+                      what, stat, MMC_INT_MASK);
+               dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
+                      MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
+               dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n",
+                      host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size);
+       }
+
+       if(!host->present || timeout)
+               host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
+                                   STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;
+
+       if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
+               clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+
+               stat = MMC_STATUS;
+               /*
+                * This is not required in theory, but there is chance to miss some flag
+                * which clears automatically by mask write, FreeScale original code keeps
+                * stat from IRQ time so do I
+                */
+               stat |= host->status_reg;
+
+               if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+                       stat &= ~STATUS_CRC_READ_ERR;
+
+               if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+                       imxmci_busy_wait_for_status(host, &stat,
+                                       STATUS_END_CMD_RESP | STATUS_ERR_MASK,
+                                       20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
+               }
+
+               if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
+                       if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+                               imxmci_cmd_done(host, stat);
+                       if(host->data && (stat & STATUS_ERR_MASK))
+                               imxmci_data_done(host, stat);
+               }
+
+               if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
+                       stat |= MMC_STATUS;
+                       if(imxmci_cpu_driven_data(host, &stat)){
+                               if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+                                       imxmci_cmd_done(host, stat);
+                               atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
+                                                       &host->pending_events);
+                               imxmci_data_done(host, stat);
+                       }
+               }
+       }
+
+       if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
+          !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+
+               stat = MMC_STATUS;
+               /* Same as above */
+               stat |= host->status_reg;
+
+               if(host->dma_dir == DMA_TO_DEVICE) {
+                       data_dir_mask = STATUS_WRITE_OP_DONE;
+               } else {
+                       data_dir_mask = STATUS_DATA_TRANS_DONE;
+               }
+
+               if(stat & data_dir_mask) {
+                       clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+                       imxmci_data_done(host, stat);
+               }
+       }
+
+       if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {
+
+               if(host->cmd)
+                       imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);
+
+               if(host->data)
+                       imxmci_data_done(host, STATUS_TIME_OUT_READ |
+                                        STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);
+
+               if(host->req)
+                       imxmci_finish_request(host, host->req);
+
+               mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+
+       }
+}
+
+static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+       struct imxmci_host *host = mmc_priv(mmc);
+       unsigned int cmdat;
+
+       WARN_ON(host->req != NULL);
+
+       host->req = req;
+
+       cmdat = 0;
+
+       if (req->data) {
+               imxmci_setup_data(host, req->data);
+
+               cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+               if (req->data->flags & MMC_DATA_WRITE)
+                       cmdat |= CMD_DAT_CONT_WRITE;
+
+               if (req->data->flags & MMC_DATA_STREAM) {
+                       cmdat |= CMD_DAT_CONT_STREAM_BLOCK;
+               }
+       }
+
+       imxmci_start_cmd(host, req->cmd, cmdat);
+}
+
+#define CLK_RATE 19200000
+
+static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct imxmci_host *host = mmc_priv(mmc);
+       int prescaler;
+
+       if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
+               host->actual_bus_width = MMC_BUS_WIDTH_4;
+               imx_gpio_mode(PB11_PF_SD_DAT3);
+       }else{
+               host->actual_bus_width = MMC_BUS_WIDTH_1;
+               imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+       }
+
+       if ( host->power_mode != ios->power_mode ) {
+               switch (ios->power_mode) {
+               case MMC_POWER_OFF:
+                       break;
+               case MMC_POWER_UP:
+                       set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+                       break;
+               case MMC_POWER_ON:
+                       break;
+               }
+               host->power_mode = ios->power_mode;
+       }
+
+       if ( ios->clock ) {
+               unsigned int clk;
+
+               /* The prescaler is 5 for PERCLK2 equal to 96MHz
+                * then 96MHz / 5 = 19.2 MHz
+                */
+               clk=imx_get_perclk2();
+               prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE;
+               switch(prescaler) {
+               case 0:
+               case 1: prescaler = 0;
+                       break;
+               case 2: prescaler = 1;
+                       break;
+               case 3: prescaler = 2;
+                       break;
+               case 4: prescaler = 4;
+                       break;
+               default:
+               case 5: prescaler = 5;
+                       break;
+               }
+
+               dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n",
+                       clk, prescaler);
+
+               for(clk=0; clk<8; clk++) {
+                       int x;
+                       x = CLK_RATE / (1<<clk);
+                       if( x <= ios->clock)
+                               break;
+               }
+
+               MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */
+
+               imxmci_stop_clock(host);
+               MMC_CLK_RATE = (prescaler<<3) | clk;
+               /*
+                * Under my understanding, clock should not be started there, because it would
+                * initiate SDHC sequencer and send last or random command into card
+                */
+               /*imxmci_start_clock(host);*/
+
+               dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
+       } else {
+               imxmci_stop_clock(host);
+       }
+}
+
+static const struct mmc_host_ops imxmci_ops = {
+       .request        = imxmci_request,
+       .set_ios        = imxmci_set_ios,
+};
+
+static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
+{
+       int i;
+
+       for (i = 0; i < dev->num_resources; i++)
+               if (dev->resource[i].flags == mask && nr-- == 0)
+                       return &dev->resource[i];
+       return NULL;
+}
+
+static int platform_device_irq(struct platform_device *dev, int nr)
+{
+       int i;
+
+       for (i = 0; i < dev->num_resources; i++)
+               if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
+                       return dev->resource[i].start;
+       return NO_IRQ;
+}
+
+static void imxmci_check_status(unsigned long data)
+{
+       struct imxmci_host *host = (struct imxmci_host *)data;
+
+       if( host->pdata->card_present() != host->present ) {
+               host->present ^= 1;
+               dev_info(mmc_dev(host->mmc), "card %s\n",
+                     host->present ? "inserted" : "removed");
+
+               set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events);
+               tasklet_schedule(&host->tasklet);
+       }
+
+       if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) ||
+          test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+               atomic_inc(&host->stuck_timeout);
+               if(atomic_read(&host->stuck_timeout) > 4)
+                       tasklet_schedule(&host->tasklet);
+       } else {
+               atomic_set(&host->stuck_timeout, 0);
+
+       }
+
+       mod_timer(&host->timer, jiffies + (HZ>>1));
+}
+
+static int imxmci_probe(struct platform_device *pdev)
+{
+       struct mmc_host *mmc;
+       struct imxmci_host *host = NULL;
+       struct resource *r;
+       int ret = 0, irq;
+
+       printk(KERN_INFO "i.MX mmc driver\n");
+
+       r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_device_irq(pdev, 0);
+       if (!r || irq == NO_IRQ)
+               return -ENXIO;
+
+       r = request_mem_region(r->start, 0x100, "IMXMCI");
+       if (!r)
+               return -EBUSY;
+
+       mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       mmc->ops = &imxmci_ops;
+       mmc->f_min = 150000;
+       mmc->f_max = CLK_RATE/2;
+       mmc->ocr_avail = MMC_VDD_32_33;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_BYTEBLOCK;
+
+       /* MMC core transfer sizes tunable parameters */
+       mmc->max_hw_segs = 64;
+       mmc->max_phys_segs = 64;
+       mmc->max_seg_size = 64*512;     /* default PAGE_CACHE_SIZE */
+       mmc->max_req_size = 64*512;     /* default PAGE_CACHE_SIZE */
+       mmc->max_blk_size = 2048;
+       mmc->max_blk_count = 65535;
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+       host->dma_allocated = 0;
+       host->pdata = pdev->dev.platform_data;
+
+       spin_lock_init(&host->lock);
+       host->res = r;
+       host->irq = irq;
+
+       imx_gpio_mode(PB8_PF_SD_DAT0);
+       imx_gpio_mode(PB9_PF_SD_DAT1);
+       imx_gpio_mode(PB10_PF_SD_DAT2);
+       /* Configured as GPIO with pull-up to ensure right MCC card mode */
+       /* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */
+       imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+       /* imx_gpio_mode(PB11_PF_SD_DAT3); */
+       imx_gpio_mode(PB12_PF_SD_CLK);
+       imx_gpio_mode(PB13_PF_SD_CMD);
+
+       imxmci_softreset();
+
+       if ( MMC_REV_NO != 0x390 ) {
+               dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
+                       MMC_REV_NO);
+               goto out;
+       }
+
+       MMC_READ_TO = 0x2db4; /* recommended in data sheet */
+
+       host->imask = IMXMCI_INT_MASK_DEFAULT;
+       MMC_INT_MASK = host->imask;
+
+
+       if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){
+               dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
+               ret = -EBUSY;
+               goto out;
+       }
+       host->dma_allocated=1;
+       imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
+
+       tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
+       host->status_reg=0;
+       host->pending_events=0;
+
+       ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host);
+       if (ret)
+               goto out;
+
+       host->present = host->pdata->card_present();
+       init_timer(&host->timer);
+       host->timer.data = (unsigned long)host;
+       host->timer.function = imxmci_check_status;
+       add_timer(&host->timer);
+       mod_timer(&host->timer, jiffies + (HZ>>1));
+
+       platform_set_drvdata(pdev, mmc);
+
+       mmc_add_host(mmc);
+
+       return 0;
+
+out:
+       if (host) {
+               if(host->dma_allocated){
+                       imx_dma_free(host->dma);
+                       host->dma_allocated=0;
+               }
+       }
+       if (mmc)
+               mmc_free_host(mmc);
+       release_resource(r);
+       return ret;
+}
+
+static int imxmci_remove(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (mmc) {
+               struct imxmci_host *host = mmc_priv(mmc);
+
+               tasklet_disable(&host->tasklet);
+
+               del_timer_sync(&host->timer);
+               mmc_remove_host(mmc);
+
+               free_irq(host->irq, host);
+               if(host->dma_allocated){
+                       imx_dma_free(host->dma);
+                       host->dma_allocated=0;
+               }
+
+               tasklet_kill(&host->tasklet);
+
+               release_resource(host->res);
+
+               mmc_free_host(mmc);
+       }
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct mmc_host *mmc = platform_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc)
+               ret = mmc_suspend_host(mmc, state);
+
+       return ret;
+}
+
+static int imxmci_resume(struct platform_device *dev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(dev);
+       struct imxmci_host *host;
+       int ret = 0;
+
+       if (mmc) {
+               host = mmc_priv(mmc);
+               if(host)
+                       set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+               ret = mmc_resume_host(mmc);
+       }
+
+       return ret;
+}
+#else
+#define imxmci_suspend  NULL
+#define imxmci_resume   NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver imxmci_driver = {
+       .probe          = imxmci_probe,
+       .remove         = imxmci_remove,
+       .suspend        = imxmci_suspend,
+       .resume         = imxmci_resume,
+       .driver         = {
+               .name           = DRIVER_NAME,
+       }
+};
+
+static int __init imxmci_init(void)
+{
+       return platform_driver_register(&imxmci_driver);
+}
+
+static void __exit imxmci_exit(void)
+{
+       platform_driver_unregister(&imxmci_driver);
+}
+
+module_init(imxmci_init);
+module_exit(imxmci_exit);
+
+MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/imxmmc.h b/drivers/mmc/host/imxmmc.h
new file mode 100644 (file)
index 0000000..e5339e3
--- /dev/null
@@ -0,0 +1,67 @@
+
+# define __REG16(x)    (*((volatile u16 *)IO_ADDRESS(x)))
+
+#define MMC_STR_STP_CLK  __REG16(IMX_MMC_BASE + 0x00)
+#define MMC_STATUS       __REG16(IMX_MMC_BASE + 0x04)
+#define MMC_CLK_RATE     __REG16(IMX_MMC_BASE + 0x08)
+#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C)
+#define MMC_RES_TO       __REG16(IMX_MMC_BASE + 0x10)
+#define MMC_READ_TO      __REG16(IMX_MMC_BASE + 0x14)
+#define MMC_BLK_LEN      __REG16(IMX_MMC_BASE + 0x18)
+#define MMC_NOB          __REG16(IMX_MMC_BASE + 0x1C)
+#define MMC_REV_NO       __REG16(IMX_MMC_BASE + 0x20)
+#define MMC_INT_MASK     __REG16(IMX_MMC_BASE + 0x24)
+#define MMC_CMD          __REG16(IMX_MMC_BASE + 0x28)
+#define MMC_ARGH         __REG16(IMX_MMC_BASE + 0x2C)
+#define MMC_ARGL         __REG16(IMX_MMC_BASE + 0x30)
+#define MMC_RES_FIFO     __REG16(IMX_MMC_BASE + 0x34)
+#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38)
+#define MMC_BUFFER_ACCESS_OFS 0x38
+
+
+#define STR_STP_CLK_ENDIAN              (1<<5)
+#define STR_STP_CLK_RESET               (1<<3)
+#define STR_STP_CLK_ENABLE              (1<<2)
+#define STR_STP_CLK_START_CLK           (1<<1)
+#define STR_STP_CLK_STOP_CLK            (1<<0)
+#define STATUS_CARD_PRESENCE            (1<<15)
+#define STATUS_SDIO_INT_ACTIVE          (1<<14)
+#define STATUS_END_CMD_RESP             (1<<13)
+#define STATUS_WRITE_OP_DONE            (1<<12)
+#define STATUS_DATA_TRANS_DONE          (1<<11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK   (3<<10)
+#define STATUS_CARD_BUS_CLK_RUN         (1<<8)
+#define STATUS_APPL_BUFF_FF             (1<<7)
+#define STATUS_APPL_BUFF_FE             (1<<6)
+#define STATUS_RESP_CRC_ERR             (1<<5)
+#define STATUS_CRC_READ_ERR             (1<<3)
+#define STATUS_CRC_WRITE_ERR            (1<<2)
+#define STATUS_TIME_OUT_RESP            (1<<1)
+#define STATUS_TIME_OUT_READ            (1<<0)
+#define STATUS_ERR_MASK                 0x2f
+#define CLK_RATE_PRESCALER(x)           ((x) & 0x7)
+#define CLK_RATE_CLK_RATE(x)            (((x) & 0x7) << 3)
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF  (1<<12)
+#define CMD_DAT_CONT_STOP_READWAIT      (1<<11)
+#define CMD_DAT_CONT_START_READWAIT     (1<<10)
+#define CMD_DAT_CONT_BUS_WIDTH_1        (0<<8)
+#define CMD_DAT_CONT_BUS_WIDTH_4        (2<<8)
+#define CMD_DAT_CONT_INIT               (1<<7)
+#define CMD_DAT_CONT_BUSY               (1<<6)
+#define CMD_DAT_CONT_STREAM_BLOCK       (1<<5)
+#define CMD_DAT_CONT_WRITE              (1<<4)
+#define CMD_DAT_CONT_DATA_ENABLE        (1<<3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6)
+#define INT_MASK_AUTO_CARD_DETECT       (1<<6)
+#define INT_MASK_DAT0_EN                (1<<5)
+#define INT_MASK_SDIO                   (1<<4)
+#define INT_MASK_BUF_READY              (1<<3)
+#define INT_MASK_END_CMD_RES            (1<<2)
+#define INT_MASK_WRITE_OP_DONE          (1<<1)
+#define INT_MASK_DATA_TRAN              (1<<0)
+#define INT_ALL                         (0x7f)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
new file mode 100644 (file)
index 0000000..d11c2d2
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ *  linux/drivers/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/highmem.h>
+#include <linux/mmc/host.h>
+#include <linux/amba/bus.h>
+#include <linux/clk.h>
+
+#include <asm/cacheflush.h>
+#include <asm/div64.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <asm/sizes.h>
+#include <asm/mach/mmc.h>
+
+#include "mmci.h"
+
+#define DRIVER_NAME "mmci-pl18x"
+
+#define DBG(host,fmt,args...)  \
+       pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
+
+static unsigned int fmax = 515633;
+
+static void
+mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
+{
+       writel(0, host->base + MMCICOMMAND);
+
+       BUG_ON(host->data);
+
+       host->mrq = NULL;
+       host->cmd = NULL;
+
+       if (mrq->data)
+               mrq->data->bytes_xfered = host->data_xfered;
+
+       /*
+        * Need to drop the host lock here; mmc_request_done may call
+        * back into the driver...
+        */
+       spin_unlock(&host->lock);
+       mmc_request_done(host->mmc, mrq);
+       spin_lock(&host->lock);
+}
+
+static void mmci_stop_data(struct mmci_host *host)
+{
+       writel(0, host->base + MMCIDATACTRL);
+       writel(0, host->base + MMCIMASK1);
+       host->data = NULL;
+}
+
+static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
+{
+       unsigned int datactrl, timeout, irqmask;
+       unsigned long long clks;
+       void __iomem *base;
+       int blksz_bits;
+
+       DBG(host, "blksz %04x blks %04x flags %08x\n",
+           data->blksz, data->blocks, data->flags);
+
+       host->data = data;
+       host->size = data->blksz;
+       host->data_xfered = 0;
+
+       mmci_init_sg(host, data);
+
+       clks = (unsigned long long)data->timeout_ns * host->cclk;
+       do_div(clks, 1000000000UL);
+
+       timeout = data->timeout_clks + (unsigned int)clks;
+
+       base = host->base;
+       writel(timeout, base + MMCIDATATIMER);
+       writel(host->size, base + MMCIDATALENGTH);
+
+       blksz_bits = ffs(data->blksz) - 1;
+       BUG_ON(1 << blksz_bits != data->blksz);
+
+       datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
+       if (data->flags & MMC_DATA_READ) {
+               datactrl |= MCI_DPSM_DIRECTION;
+               irqmask = MCI_RXFIFOHALFFULLMASK;
+
+               /*
+                * If we have less than a FIFOSIZE of bytes to transfer,
+                * trigger a PIO interrupt as soon as any data is available.
+                */
+               if (host->size < MCI_FIFOSIZE)
+                       irqmask |= MCI_RXDATAAVLBLMASK;
+       } else {
+               /*
+                * We don't actually need to include "FIFO empty" here
+                * since its implicit in "FIFO half empty".
+                */
+               irqmask = MCI_TXFIFOHALFEMPTYMASK;
+       }
+
+       writel(datactrl, base + MMCIDATACTRL);
+       writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
+       writel(irqmask, base + MMCIMASK1);
+}
+
+static void
+mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
+{
+       void __iomem *base = host->base;
+
+       DBG(host, "op %02x arg %08x flags %08x\n",
+           cmd->opcode, cmd->arg, cmd->flags);
+
+       if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
+               writel(0, base + MMCICOMMAND);
+               udelay(1);
+       }
+
+       c |= cmd->opcode | MCI_CPSM_ENABLE;
+       if (cmd->flags & MMC_RSP_PRESENT) {
+               if (cmd->flags & MMC_RSP_136)
+                       c |= MCI_CPSM_LONGRSP;
+               c |= MCI_CPSM_RESPONSE;
+       }
+       if (/*interrupt*/0)
+               c |= MCI_CPSM_INTERRUPT;
+
+       host->cmd = cmd;
+
+       writel(cmd->arg, base + MMCIARGUMENT);
+       writel(c, base + MMCICOMMAND);
+}
+
+static void
+mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
+             unsigned int status)
+{
+       if (status & MCI_DATABLOCKEND) {
+               host->data_xfered += data->blksz;
+       }
+       if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+               if (status & MCI_DATACRCFAIL)
+                       data->error = MMC_ERR_BADCRC;
+               else if (status & MCI_DATATIMEOUT)
+                       data->error = MMC_ERR_TIMEOUT;
+               else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
+                       data->error = MMC_ERR_FIFO;
+               status |= MCI_DATAEND;
+
+               /*
+                * We hit an error condition.  Ensure that any data
+                * partially written to a page is properly coherent.
+                */
+               if (host->sg_len && data->flags & MMC_DATA_READ)
+                       flush_dcache_page(host->sg_ptr->page);
+       }
+       if (status & MCI_DATAEND) {
+               mmci_stop_data(host);
+
+               if (!data->stop) {
+                       mmci_request_end(host, data->mrq);
+               } else {
+                       mmci_start_command(host, data->stop, 0);
+               }
+       }
+}
+
+static void
+mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
+            unsigned int status)
+{
+       void __iomem *base = host->base;
+
+       host->cmd = NULL;
+
+       cmd->resp[0] = readl(base + MMCIRESPONSE0);
+       cmd->resp[1] = readl(base + MMCIRESPONSE1);
+       cmd->resp[2] = readl(base + MMCIRESPONSE2);
+       cmd->resp[3] = readl(base + MMCIRESPONSE3);
+
+       if (status & MCI_CMDTIMEOUT) {
+               cmd->error = MMC_ERR_TIMEOUT;
+       } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {
+               cmd->error = MMC_ERR_BADCRC;
+       }
+
+       if (!cmd->data || cmd->error != MMC_ERR_NONE) {
+               if (host->data)
+                       mmci_stop_data(host);
+               mmci_request_end(host, cmd->mrq);
+       } else if (!(cmd->data->flags & MMC_DATA_READ)) {
+               mmci_start_data(host, cmd->data);
+       }
+}
+
+static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain)
+{
+       void __iomem *base = host->base;
+       char *ptr = buffer;
+       u32 status;
+
+       do {
+               int count = host->size - (readl(base + MMCIFIFOCNT) << 2);
+
+               if (count > remain)
+                       count = remain;
+
+               if (count <= 0)
+                       break;
+
+               readsl(base + MMCIFIFO, ptr, count >> 2);
+
+               ptr += count;
+               remain -= count;
+
+               if (remain == 0)
+                       break;
+
+               status = readl(base + MMCISTATUS);
+       } while (status & MCI_RXDATAAVLBL);
+
+       return ptr - buffer;
+}
+
+static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
+{
+       void __iomem *base = host->base;
+       char *ptr = buffer;
+
+       do {
+               unsigned int count, maxcnt;
+
+               maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;
+               count = min(remain, maxcnt);
+
+               writesl(base + MMCIFIFO, ptr, count >> 2);
+
+               ptr += count;
+               remain -= count;
+
+               if (remain == 0)
+                       break;
+
+               status = readl(base + MMCISTATUS);
+       } while (status & MCI_TXFIFOHALFEMPTY);
+
+       return ptr - buffer;
+}
+
+/*
+ * PIO data transfer IRQ handler.
+ */
+static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
+{
+       struct mmci_host *host = dev_id;
+       void __iomem *base = host->base;
+       u32 status;
+
+       status = readl(base + MMCISTATUS);
+
+       DBG(host, "irq1 %08x\n", status);
+
+       do {
+               unsigned long flags;
+               unsigned int remain, len;
+               char *buffer;
+
+               /*
+                * For write, we only need to test the half-empty flag
+                * here - if the FIFO is completely empty, then by
+                * definition it is more than half empty.
+                *
+                * For read, check for data available.
+                */
+               if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
+                       break;
+
+               /*
+                * Map the current scatter buffer.
+                */
+               buffer = mmci_kmap_atomic(host, &flags) + host->sg_off;
+               remain = host->sg_ptr->length - host->sg_off;
+
+               len = 0;
+               if (status & MCI_RXACTIVE)
+                       len = mmci_pio_read(host, buffer, remain);
+               if (status & MCI_TXACTIVE)
+                       len = mmci_pio_write(host, buffer, remain, status);
+
+               /*
+                * Unmap the buffer.
+                */
+               mmci_kunmap_atomic(host, buffer, &flags);
+
+               host->sg_off += len;
+               host->size -= len;
+               remain -= len;
+
+               if (remain)
+                       break;
+
+               /*
+                * If we were reading, and we have completed this
+                * page, ensure that the data cache is coherent.
+                */
+               if (status & MCI_RXACTIVE)
+                       flush_dcache_page(host->sg_ptr->page);
+
+               if (!mmci_next_sg(host))
+                       break;
+
+               status = readl(base + MMCISTATUS);
+       } while (1);
+
+       /*
+        * If we're nearing the end of the read, switch to
+        * "any data available" mode.
+        */
+       if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE)
+               writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
+
+       /*
+        * If we run out of data, disable the data IRQs; this
+        * prevents a race where the FIFO becomes empty before
+        * the chip itself has disabled the data path, and
+        * stops us racing with our data end IRQ.
+        */
+       if (host->size == 0) {
+               writel(0, base + MMCIMASK1);
+               writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Handle completion of command and data transfers.
+ */
+static irqreturn_t mmci_irq(int irq, void *dev_id)
+{
+       struct mmci_host *host = dev_id;
+       u32 status;
+       int ret = 0;
+
+       spin_lock(&host->lock);
+
+       do {
+               struct mmc_command *cmd;
+               struct mmc_data *data;
+
+               status = readl(host->base + MMCISTATUS);
+               status &= readl(host->base + MMCIMASK0);
+               writel(status, host->base + MMCICLEAR);
+
+               DBG(host, "irq0 %08x\n", status);
+
+               data = host->data;
+               if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
+                             MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
+                       mmci_data_irq(host, data, status);
+
+               cmd = host->cmd;
+               if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
+                       mmci_cmd_irq(host, cmd, status);
+
+               ret = 1;
+       } while (status);
+
+       spin_unlock(&host->lock);
+
+       return IRQ_RETVAL(ret);
+}
+
+static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct mmci_host *host = mmc_priv(mmc);
+
+       WARN_ON(host->mrq != NULL);
+
+       spin_lock_irq(&host->lock);
+
+       host->mrq = mrq;
+
+       if (mrq->data && mrq->data->flags & MMC_DATA_READ)
+               mmci_start_data(host, mrq->data);
+
+       mmci_start_command(host, mrq->cmd, 0);
+
+       spin_unlock_irq(&host->lock);
+}
+
+static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct mmci_host *host = mmc_priv(mmc);
+       u32 clk = 0, pwr = 0;
+
+       if (ios->clock) {
+               if (ios->clock >= host->mclk) {
+                       clk = MCI_CLK_BYPASS;
+                       host->cclk = host->mclk;
+               } else {
+                       clk = host->mclk / (2 * ios->clock) - 1;
+                       if (clk > 256)
+                               clk = 255;
+                       host->cclk = host->mclk / (2 * (clk + 1));
+               }
+               clk |= MCI_CLK_ENABLE;
+       }
+
+       if (host->plat->translate_vdd)
+               pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
+
+       switch (ios->power_mode) {
+       case MMC_POWER_OFF:
+               break;
+       case MMC_POWER_UP:
+               pwr |= MCI_PWR_UP;
+               break;
+       case MMC_POWER_ON:
+               pwr |= MCI_PWR_ON;
+               break;
+       }
+
+       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               pwr |= MCI_ROD;
+
+       writel(clk, host->base + MMCICLOCK);
+
+       if (host->pwr != pwr) {
+               host->pwr = pwr;
+               writel(pwr, host->base + MMCIPOWER);
+       }
+}
+
+static const struct mmc_host_ops mmci_ops = {
+       .request        = mmci_request,
+       .set_ios        = mmci_set_ios,
+};
+
+static void mmci_check_status(unsigned long data)
+{
+       struct mmci_host *host = (struct mmci_host *)data;
+       unsigned int status;
+
+       status = host->plat->status(mmc_dev(host->mmc));
+       if (status ^ host->oldstat)
+               mmc_detect_change(host->mmc, 0);
+
+       host->oldstat = status;
+       mod_timer(&host->timer, jiffies + HZ);
+}
+
+static int mmci_probe(struct amba_device *dev, void *id)
+{
+       struct mmc_platform_data *plat = dev->dev.platform_data;
+       struct mmci_host *host;
+       struct mmc_host *mmc;
+       int ret;
+
+       /* must have platform data */
+       if (!plat) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = amba_request_regions(dev, DRIVER_NAME);
+       if (ret)
+               goto out;
+
+       mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto rel_regions;
+       }
+
+       host = mmc_priv(mmc);
+       host->clk = clk_get(&dev->dev, "MCLK");
+       if (IS_ERR(host->clk)) {
+               ret = PTR_ERR(host->clk);
+               host->clk = NULL;
+               goto host_free;
+       }
+
+       ret = clk_enable(host->clk);
+       if (ret)
+               goto clk_free;
+
+       host->plat = plat;
+       host->mclk = clk_get_rate(host->clk);
+       host->mmc = mmc;
+       host->base = ioremap(dev->res.start, SZ_4K);
+       if (!host->base) {
+               ret = -ENOMEM;
+               goto clk_disable;
+       }
+
+       mmc->ops = &mmci_ops;
+       mmc->f_min = (host->mclk + 511) / 512;
+       mmc->f_max = min(host->mclk, fmax);
+       mmc->ocr_avail = plat->ocr_mask;
+       mmc->caps = MMC_CAP_MULTIWRITE;
+
+       /*
+        * We can do SGIO
+        */
+       mmc->max_hw_segs = 16;
+       mmc->max_phys_segs = NR_SG;
+
+       /*
+        * Since we only have a 16-bit data length register, we must
+        * ensure that we don't exceed 2^16-1 bytes in a single request.
+        */
+       mmc->max_req_size = 65535;
+
+       /*
+        * Set the maximum segment size.  Since we aren't doing DMA
+        * (yet) we are only limited by the data length register.
+        */
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Block size can be up to 2048 bytes, but must be a power of two.
+        */
+       mmc->max_blk_size = 2048;
+
+       /*
+        * No limit on the number of blocks transferred.
+        */
+       mmc->max_blk_count = mmc->max_req_size;
+
+       spin_lock_init(&host->lock);
+
+       writel(0, host->base + MMCIMASK0);
+       writel(0, host->base + MMCIMASK1);
+       writel(0xfff, host->base + MMCICLEAR);
+
+       ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
+       if (ret)
+               goto unmap;
+
+       ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host);
+       if (ret)
+               goto irq0_free;
+
+       writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+
+       amba_set_drvdata(dev, mmc);
+
+       mmc_add_host(mmc);
+
+       printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n",
+               mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
+               (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
+
+       init_timer(&host->timer);
+       host->timer.data = (unsigned long)host;
+       host->timer.function = mmci_check_status;
+       host->timer.expires = jiffies + HZ;
+       add_timer(&host->timer);
+
+       return 0;
+
+ irq0_free:
+       free_irq(dev->irq[0], host);
+ unmap:
+       iounmap(host->base);
+ clk_disable:
+       clk_disable(host->clk);
+ clk_free:
+       clk_put(host->clk);
+ host_free:
+       mmc_free_host(mmc);
+ rel_regions:
+       amba_release_regions(dev);
+ out:
+       return ret;
+}
+
+static int mmci_remove(struct amba_device *dev)
+{
+       struct mmc_host *mmc = amba_get_drvdata(dev);
+
+       amba_set_drvdata(dev, NULL);
+
+       if (mmc) {
+               struct mmci_host *host = mmc_priv(mmc);
+
+               del_timer_sync(&host->timer);
+
+               mmc_remove_host(mmc);
+
+               writel(0, host->base + MMCIMASK0);
+               writel(0, host->base + MMCIMASK1);
+
+               writel(0, host->base + MMCICOMMAND);
+               writel(0, host->base + MMCIDATACTRL);
+
+               free_irq(dev->irq[0], host);
+               free_irq(dev->irq[1], host);
+
+               iounmap(host->base);
+               clk_disable(host->clk);
+               clk_put(host->clk);
+
+               mmc_free_host(mmc);
+
+               amba_release_regions(dev);
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mmci_suspend(struct amba_device *dev, pm_message_t state)
+{
+       struct mmc_host *mmc = amba_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc) {
+               struct mmci_host *host = mmc_priv(mmc);
+
+               ret = mmc_suspend_host(mmc, state);
+               if (ret == 0)
+                       writel(0, host->base + MMCIMASK0);
+       }
+
+       return ret;
+}
+
+static int mmci_resume(struct amba_device *dev)
+{
+       struct mmc_host *mmc = amba_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc) {
+               struct mmci_host *host = mmc_priv(mmc);
+
+               writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+
+               ret = mmc_resume_host(mmc);
+       }
+
+       return ret;
+}
+#else
+#define mmci_suspend   NULL
+#define mmci_resume    NULL
+#endif
+
+static struct amba_id mmci_ids[] = {
+       {
+               .id     = 0x00041180,
+               .mask   = 0x000fffff,
+       },
+       {
+               .id     = 0x00041181,
+               .mask   = 0x000fffff,
+       },
+       { 0, 0 },
+};
+
+static struct amba_driver mmci_driver = {
+       .drv            = {
+               .name   = DRIVER_NAME,
+       },
+       .probe          = mmci_probe,
+       .remove         = mmci_remove,
+       .suspend        = mmci_suspend,
+       .resume         = mmci_resume,
+       .id_table       = mmci_ids,
+};
+
+static int __init mmci_init(void)
+{
+       return amba_driver_register(&mmci_driver);
+}
+
+static void __exit mmci_exit(void)
+{
+       amba_driver_unregister(&mmci_driver);
+}
+
+module_init(mmci_init);
+module_exit(mmci_exit);
+module_param(fmax, uint, 0444);
+
+MODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
new file mode 100644 (file)
index 0000000..6d7eadc
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *  linux/drivers/mmc/mmci.h - ARM PrimeCell MMCI PL180/1 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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.
+ */
+#define MMCIPOWER              0x000
+#define MCI_PWR_OFF            0x00
+#define MCI_PWR_UP             0x02
+#define MCI_PWR_ON             0x03
+#define MCI_OD                 (1 << 6)
+#define MCI_ROD                        (1 << 7)
+
+#define MMCICLOCK              0x004
+#define MCI_CLK_ENABLE         (1 << 8)
+#define MCI_CLK_PWRSAVE                (1 << 9)
+#define MCI_CLK_BYPASS         (1 << 10)
+
+#define MMCIARGUMENT           0x008
+#define MMCICOMMAND            0x00c
+#define MCI_CPSM_RESPONSE      (1 << 6)
+#define MCI_CPSM_LONGRSP       (1 << 7)
+#define MCI_CPSM_INTERRUPT     (1 << 8)
+#define MCI_CPSM_PENDING       (1 << 9)
+#define MCI_CPSM_ENABLE                (1 << 10)
+
+#define MMCIRESPCMD            0x010
+#define MMCIRESPONSE0          0x014
+#define MMCIRESPONSE1          0x018
+#define MMCIRESPONSE2          0x01c
+#define MMCIRESPONSE3          0x020
+#define MMCIDATATIMER          0x024
+#define MMCIDATALENGTH         0x028
+#define MMCIDATACTRL           0x02c
+#define MCI_DPSM_ENABLE                (1 << 0)
+#define MCI_DPSM_DIRECTION     (1 << 1)
+#define MCI_DPSM_MODE          (1 << 2)
+#define MCI_DPSM_DMAENABLE     (1 << 3)
+
+#define MMCIDATACNT            0x030
+#define MMCISTATUS             0x034
+#define MCI_CMDCRCFAIL         (1 << 0)
+#define MCI_DATACRCFAIL                (1 << 1)
+#define MCI_CMDTIMEOUT         (1 << 2)
+#define MCI_DATATIMEOUT                (1 << 3)
+#define MCI_TXUNDERRUN         (1 << 4)
+#define MCI_RXOVERRUN          (1 << 5)
+#define MCI_CMDRESPEND         (1 << 6)
+#define MCI_CMDSENT            (1 << 7)
+#define MCI_DATAEND            (1 << 8)
+#define MCI_DATABLOCKEND       (1 << 10)
+#define MCI_CMDACTIVE          (1 << 11)
+#define MCI_TXACTIVE           (1 << 12)
+#define MCI_RXACTIVE           (1 << 13)
+#define MCI_TXFIFOHALFEMPTY    (1 << 14)
+#define MCI_RXFIFOHALFFULL     (1 << 15)
+#define MCI_TXFIFOFULL         (1 << 16)
+#define MCI_RXFIFOFULL         (1 << 17)
+#define MCI_TXFIFOEMPTY                (1 << 18)
+#define MCI_RXFIFOEMPTY                (1 << 19)
+#define MCI_TXDATAAVLBL                (1 << 20)
+#define MCI_RXDATAAVLBL                (1 << 21)
+
+#define MMCICLEAR              0x038
+#define MCI_CMDCRCFAILCLR      (1 << 0)
+#define MCI_DATACRCFAILCLR     (1 << 1)
+#define MCI_CMDTIMEOUTCLR      (1 << 2)
+#define MCI_DATATIMEOUTCLR     (1 << 3)
+#define MCI_TXUNDERRUNCLR      (1 << 4)
+#define MCI_RXOVERRUNCLR       (1 << 5)
+#define MCI_CMDRESPENDCLR      (1 << 6)
+#define MCI_CMDSENTCLR         (1 << 7)
+#define MCI_DATAENDCLR         (1 << 8)
+#define MCI_DATABLOCKENDCLR    (1 << 10)
+
+#define MMCIMASK0              0x03c
+#define MCI_CMDCRCFAILMASK     (1 << 0)
+#define MCI_DATACRCFAILMASK    (1 << 1)
+#define MCI_CMDTIMEOUTMASK     (1 << 2)
+#define MCI_DATATIMEOUTMASK    (1 << 3)
+#define MCI_TXUNDERRUNMASK     (1 << 4)
+#define MCI_RXOVERRUNMASK      (1 << 5)
+#define MCI_CMDRESPENDMASK     (1 << 6)
+#define MCI_CMDSENTMASK                (1 << 7)
+#define MCI_DATAENDMASK                (1 << 8)
+#define MCI_DATABLOCKENDMASK   (1 << 10)
+#define MCI_CMDACTIVEMASK      (1 << 11)
+#define MCI_TXACTIVEMASK       (1 << 12)
+#define MCI_RXACTIVEMASK       (1 << 13)
+#define MCI_TXFIFOHALFEMPTYMASK        (1 << 14)
+#define MCI_RXFIFOHALFFULLMASK (1 << 15)
+#define MCI_TXFIFOFULLMASK     (1 << 16)
+#define MCI_RXFIFOFULLMASK     (1 << 17)
+#define MCI_TXFIFOEMPTYMASK    (1 << 18)
+#define MCI_RXFIFOEMPTYMASK    (1 << 19)
+#define MCI_TXDATAAVLBLMASK    (1 << 20)
+#define MCI_RXDATAAVLBLMASK    (1 << 21)
+
+#define MMCIMASK1              0x040
+#define MMCIFIFOCNT            0x048
+#define MMCIFIFO               0x080 /* to 0x0bc */
+
+#define MCI_IRQENABLE  \
+       (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK|     \
+       MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|       \
+       MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
+
+/*
+ * The size of the FIFO in bytes.
+ */
+#define MCI_FIFOSIZE   (16*4)
+       
+#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
+
+#define NR_SG          16
+
+struct clk;
+
+struct mmci_host {
+       void __iomem            *base;
+       struct mmc_request      *mrq;
+       struct mmc_command      *cmd;
+       struct mmc_data         *data;
+       struct mmc_host         *mmc;
+       struct clk              *clk;
+
+       unsigned int            data_xfered;
+
+       spinlock_t              lock;
+
+       unsigned int            mclk;
+       unsigned int            cclk;
+       u32                     pwr;
+       struct mmc_platform_data *plat;
+
+       struct timer_list       timer;
+       unsigned int            oldstat;
+
+       unsigned int            sg_len;
+
+       /* pio stuff */
+       struct scatterlist      *sg_ptr;
+       unsigned int            sg_off;
+       unsigned int            size;
+};
+
+static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
+{
+       /*
+        * Ideally, we want the higher levels to pass us a scatter list.
+        */
+       host->sg_len = data->sg_len;
+       host->sg_ptr = data->sg;
+       host->sg_off = 0;
+}
+
+static inline int mmci_next_sg(struct mmci_host *host)
+{
+       host->sg_ptr++;
+       host->sg_off = 0;
+       return --host->sg_len;
+}
+
+static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags)
+{
+       struct scatterlist *sg = host->sg_ptr;
+
+       local_irq_save(*flags);
+       return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+}
+
+static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
+{
+       kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+       local_irq_restore(*flags);
+}
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
new file mode 100644 (file)
index 0000000..1914e65
--- /dev/null
@@ -0,0 +1,1295 @@
+/*
+ *  linux/drivers/media/mmc/omap.c
+ *
+ *  Copyright (C) 2004 Nokia Corporation
+ *  Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com>
+ *  Misc hacks here and there by Tony Lindgren <tony@atomide.com>
+ *  Other hacks (DMA, SD, etc) by David Brownell
+ *
+ * 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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/scatterlist.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/tps65010.h>
+
+#define        OMAP_MMC_REG_CMD        0x00
+#define        OMAP_MMC_REG_ARGL       0x04
+#define        OMAP_MMC_REG_ARGH       0x08
+#define        OMAP_MMC_REG_CON        0x0c
+#define        OMAP_MMC_REG_STAT       0x10
+#define        OMAP_MMC_REG_IE         0x14
+#define        OMAP_MMC_REG_CTO        0x18
+#define        OMAP_MMC_REG_DTO        0x1c
+#define        OMAP_MMC_REG_DATA       0x20
+#define        OMAP_MMC_REG_BLEN       0x24
+#define        OMAP_MMC_REG_NBLK       0x28
+#define        OMAP_MMC_REG_BUF        0x2c
+#define OMAP_MMC_REG_SDIO      0x34
+#define        OMAP_MMC_REG_REV        0x3c
+#define        OMAP_MMC_REG_RSP0       0x40
+#define        OMAP_MMC_REG_RSP1       0x44
+#define        OMAP_MMC_REG_RSP2       0x48
+#define        OMAP_MMC_REG_RSP3       0x4c
+#define        OMAP_MMC_REG_RSP4       0x50
+#define        OMAP_MMC_REG_RSP5       0x54
+#define        OMAP_MMC_REG_RSP6       0x58
+#define        OMAP_MMC_REG_RSP7       0x5c
+#define        OMAP_MMC_REG_IOSR       0x60
+#define        OMAP_MMC_REG_SYSC       0x64
+#define        OMAP_MMC_REG_SYSS       0x68
+
+#define        OMAP_MMC_STAT_CARD_ERR          (1 << 14)
+#define        OMAP_MMC_STAT_CARD_IRQ          (1 << 13)
+#define        OMAP_MMC_STAT_OCR_BUSY          (1 << 12)
+#define        OMAP_MMC_STAT_A_EMPTY           (1 << 11)
+#define        OMAP_MMC_STAT_A_FULL            (1 << 10)
+#define        OMAP_MMC_STAT_CMD_CRC           (1 <<  8)
+#define        OMAP_MMC_STAT_CMD_TOUT          (1 <<  7)
+#define        OMAP_MMC_STAT_DATA_CRC          (1 <<  6)
+#define        OMAP_MMC_STAT_DATA_TOUT         (1 <<  5)
+#define        OMAP_MMC_STAT_END_BUSY          (1 <<  4)
+#define        OMAP_MMC_STAT_END_OF_DATA       (1 <<  3)
+#define        OMAP_MMC_STAT_CARD_BUSY         (1 <<  2)
+#define        OMAP_MMC_STAT_END_OF_CMD        (1 <<  0)
+
+#define OMAP_MMC_READ(host, reg)       __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC    0
+#define OMAP_MMC_CMDTYPE_BCR   1
+#define OMAP_MMC_CMDTYPE_AC    2
+#define OMAP_MMC_CMDTYPE_ADTC  3
+
+
+#define DRIVER_NAME "mmci-omap"
+
+/* Specifies how often in millisecs to poll for card status changes
+ * when the cover switch is open */
+#define OMAP_MMC_SWITCH_POLL_DELAY     500
+
+static int mmc_omap_enable_poll = 1;
+
+struct mmc_omap_host {
+       int                     initialized;
+       int                     suspended;
+       struct mmc_request *    mrq;
+       struct mmc_command *    cmd;
+       struct mmc_data *       data;
+       struct mmc_host *       mmc;
+       struct device *         dev;
+       unsigned char           id; /* 16xx chips have 2 MMC blocks */
+       struct clk *            iclk;
+       struct clk *            fclk;
+       struct resource         *mem_res;
+       void __iomem            *virt_base;
+       unsigned int            phys_base;
+       int                     irq;
+       unsigned char           bus_mode;
+       unsigned char           hw_bus_mode;
+
+       unsigned int            sg_len;
+       int                     sg_idx;
+       u16 *                   buffer;
+       u32                     buffer_bytes_left;
+       u32                     total_bytes_left;
+
+       unsigned                use_dma:1;
+       unsigned                brs_received:1, dma_done:1;
+       unsigned                dma_is_read:1;
+       unsigned                dma_in_use:1;
+       int                     dma_ch;
+       spinlock_t              dma_lock;
+       struct timer_list       dma_timer;
+       unsigned                dma_len;
+
+       short                   power_pin;
+       short                   wp_pin;
+
+       int                     switch_pin;
+       struct work_struct      switch_work;
+       struct timer_list       switch_timer;
+       int                     switch_last_state;
+};
+
+static inline int
+mmc_omap_cover_is_open(struct mmc_omap_host *host)
+{
+       if (host->switch_pin < 0)
+               return 0;
+       return omap_get_gpio_datain(host->switch_pin);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" :
+                       "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
+static ssize_t
+mmc_omap_show_enable_poll(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
+}
+
+static ssize_t
+mmc_omap_store_enable_poll(struct device *dev,
+       struct device_attribute *attr, const char *buf,
+       size_t size)
+{
+       int enable_poll;
+
+       if (sscanf(buf, "%10d", &enable_poll) != 1)
+               return -EINVAL;
+
+       if (enable_poll != mmc_omap_enable_poll) {
+               struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+               mmc_omap_enable_poll = enable_poll;
+               if (enable_poll && host->switch_pin >= 0)
+                       schedule_work(&host->switch_work);
+       }
+       return size;
+}
+
+static DEVICE_ATTR(enable_poll, 0664,
+                  mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
+
+static void
+mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+       u32 cmdreg;
+       u32 resptype;
+       u32 cmdtype;
+
+       host->cmd = cmd;
+
+       resptype = 0;
+       cmdtype = 0;
+
+       /* Our hardware needs to know exact type */
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE:
+               break;
+       case MMC_RSP_R1:
+       case MMC_RSP_R1B:
+               /* resp 1, 1b, 6, 7 */
+               resptype = 1;
+               break;
+       case MMC_RSP_R2:
+               resptype = 2;
+               break;
+       case MMC_RSP_R3:
+               resptype = 3;
+               break;
+       default:
+               dev_err(mmc_dev(host->mmc), "Invalid response type: %04x\n", mmc_resp_type(cmd));
+               break;
+       }
+
+       if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) {
+               cmdtype = OMAP_MMC_CMDTYPE_ADTC;
+       } else if (mmc_cmd_type(cmd) == MMC_CMD_BC) {
+               cmdtype = OMAP_MMC_CMDTYPE_BC;
+       } else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) {
+               cmdtype = OMAP_MMC_CMDTYPE_BCR;
+       } else {
+               cmdtype = OMAP_MMC_CMDTYPE_AC;
+       }
+
+       cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
+
+       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               cmdreg |= 1 << 6;
+
+       if (cmd->flags & MMC_RSP_BUSY)
+               cmdreg |= 1 << 11;
+
+       if (host->data && !(host->data->flags & MMC_DATA_WRITE))
+               cmdreg |= 1 << 15;
+
+       clk_enable(host->fclk);
+
+       OMAP_MMC_WRITE(host, CTO, 200);
+       OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
+       OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
+       OMAP_MMC_WRITE(host, IE,
+                      OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
+                      OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
+                      OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
+                      OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
+                      OMAP_MMC_STAT_END_OF_DATA);
+       OMAP_MMC_WRITE(host, CMD, cmdreg);
+}
+
+static void
+mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       if (host->dma_in_use) {
+               enum dma_data_direction dma_data_dir;
+
+               BUG_ON(host->dma_ch < 0);
+               if (data->error != MMC_ERR_NONE)
+                       omap_stop_dma(host->dma_ch);
+               /* Release DMA channel lazily */
+               mod_timer(&host->dma_timer, jiffies + HZ);
+               if (data->flags & MMC_DATA_WRITE)
+                       dma_data_dir = DMA_TO_DEVICE;
+               else
+                       dma_data_dir = DMA_FROM_DEVICE;
+               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+                            dma_data_dir);
+       }
+       host->data = NULL;
+       host->sg_len = 0;
+       clk_disable(host->fclk);
+
+       /* NOTE:  MMC layer will sometimes poll-wait CMD13 next, issuing
+        * dozens of requests until the card finishes writing data.
+        * It'd be cheaper to just wait till an EOFB interrupt arrives...
+        */
+
+       if (!data->stop) {
+               host->mrq = NULL;
+               mmc_request_done(host->mmc, data->mrq);
+               return;
+       }
+
+       mmc_omap_start_command(host, data->stop);
+}
+
+static void
+mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       unsigned long flags;
+       int done;
+
+       if (!host->dma_in_use) {
+               mmc_omap_xfer_done(host, data);
+               return;
+       }
+       done = 0;
+       spin_lock_irqsave(&host->dma_lock, flags);
+       if (host->dma_done)
+               done = 1;
+       else
+               host->brs_received = 1;
+       spin_unlock_irqrestore(&host->dma_lock, flags);
+       if (done)
+               mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_dma_timer(unsigned long data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+       BUG_ON(host->dma_ch < 0);
+       omap_free_dma(host->dma_ch);
+       host->dma_ch = -1;
+}
+
+static void
+mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       unsigned long flags;
+       int done;
+
+       done = 0;
+       spin_lock_irqsave(&host->dma_lock, flags);
+       if (host->brs_received)
+               done = 1;
+       else
+               host->dma_done = 1;
+       spin_unlock_irqrestore(&host->dma_lock, flags);
+       if (done)
+               mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+       host->cmd = NULL;
+
+       if (cmd->flags & MMC_RSP_PRESENT) {
+               if (cmd->flags & MMC_RSP_136) {
+                       /* response type 2 */
+                       cmd->resp[3] =
+                               OMAP_MMC_READ(host, RSP0) |
+                               (OMAP_MMC_READ(host, RSP1) << 16);
+                       cmd->resp[2] =
+                               OMAP_MMC_READ(host, RSP2) |
+                               (OMAP_MMC_READ(host, RSP3) << 16);
+                       cmd->resp[1] =
+                               OMAP_MMC_READ(host, RSP4) |
+                               (OMAP_MMC_READ(host, RSP5) << 16);
+                       cmd->resp[0] =
+                               OMAP_MMC_READ(host, RSP6) |
+                               (OMAP_MMC_READ(host, RSP7) << 16);
+               } else {
+                       /* response types 1, 1b, 3, 4, 5, 6 */
+                       cmd->resp[0] =
+                               OMAP_MMC_READ(host, RSP6) |
+                               (OMAP_MMC_READ(host, RSP7) << 16);
+               }
+       }
+
+       if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
+               host->mrq = NULL;
+               clk_disable(host->fclk);
+               mmc_request_done(host->mmc, cmd->mrq);
+       }
+}
+
+/* PIO only */
+static void
+mmc_omap_sg_to_buf(struct mmc_omap_host *host)
+{
+       struct scatterlist *sg;
+
+       sg = host->data->sg + host->sg_idx;
+       host->buffer_bytes_left = sg->length;
+       host->buffer = page_address(sg->page) + sg->offset;
+       if (host->buffer_bytes_left > host->total_bytes_left)
+               host->buffer_bytes_left = host->total_bytes_left;
+}
+
+/* PIO only */
+static void
+mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
+{
+       int n;
+
+       if (host->buffer_bytes_left == 0) {
+               host->sg_idx++;
+               BUG_ON(host->sg_idx == host->sg_len);
+               mmc_omap_sg_to_buf(host);
+       }
+       n = 64;
+       if (n > host->buffer_bytes_left)
+               n = host->buffer_bytes_left;
+       host->buffer_bytes_left -= n;
+       host->total_bytes_left -= n;
+       host->data->bytes_xfered += n;
+
+       if (write) {
+               __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
+       } else {
+               __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
+       }
+}
+
+static inline void mmc_omap_report_irq(u16 status)
+{
+       static const char *mmc_omap_status_bits[] = {
+               "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
+               "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
+       };
+       int i, c = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
+               if (status & (1 << i)) {
+                       if (c)
+                               printk(" ");
+                       printk("%s", mmc_omap_status_bits[i]);
+                       c++;
+               }
+}
+
+static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+{
+       struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
+       u16 status;
+       int end_command;
+       int end_transfer;
+       int transfer_error;
+
+       if (host->cmd == NULL && host->data == NULL) {
+               status = OMAP_MMC_READ(host, STAT);
+               dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
+               if (status != 0) {
+                       OMAP_MMC_WRITE(host, STAT, status);
+                       OMAP_MMC_WRITE(host, IE, 0);
+               }
+               return IRQ_HANDLED;
+       }
+
+       end_command = 0;
+       end_transfer = 0;
+       transfer_error = 0;
+
+       while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
+               OMAP_MMC_WRITE(host, STAT, status);
+#ifdef CONFIG_MMC_DEBUG
+               dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
+                       status, host->cmd != NULL ? host->cmd->opcode : -1);
+               mmc_omap_report_irq(status);
+               printk("\n");
+#endif
+               if (host->total_bytes_left) {
+                       if ((status & OMAP_MMC_STAT_A_FULL) ||
+                           (status & OMAP_MMC_STAT_END_OF_DATA))
+                               mmc_omap_xfer_data(host, 0);
+                       if (status & OMAP_MMC_STAT_A_EMPTY)
+                               mmc_omap_xfer_data(host, 1);
+               }
+
+               if (status & OMAP_MMC_STAT_END_OF_DATA) {
+                       end_transfer = 1;
+               }
+
+               if (status & OMAP_MMC_STAT_DATA_TOUT) {
+                       dev_dbg(mmc_dev(host->mmc), "data timeout\n");
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_TIMEOUT;
+                               transfer_error = 1;
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_DATA_CRC) {
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_BADCRC;
+                               dev_dbg(mmc_dev(host->mmc),
+                                        "data CRC error, bytes left %d\n",
+                                       host->total_bytes_left);
+                               transfer_error = 1;
+                       } else {
+                               dev_dbg(mmc_dev(host->mmc), "data CRC error\n");
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CMD_TOUT) {
+                       /* Timeouts are routine with some commands */
+                       if (host->cmd) {
+                               if (host->cmd->opcode != MMC_ALL_SEND_CID &&
+                                               host->cmd->opcode !=
+                                               MMC_SEND_OP_COND &&
+                                               host->cmd->opcode !=
+                                               MMC_APP_CMD &&
+                                               !mmc_omap_cover_is_open(host))
+                                       dev_err(mmc_dev(host->mmc),
+                                               "command timeout, CMD %d\n",
+                                               host->cmd->opcode);
+                               host->cmd->error = MMC_ERR_TIMEOUT;
+                               end_command = 1;
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CMD_CRC) {
+                       if (host->cmd) {
+                               dev_err(mmc_dev(host->mmc),
+                                       "command CRC error (CMD%d, arg 0x%08x)\n",
+                                       host->cmd->opcode, host->cmd->arg);
+                               host->cmd->error = MMC_ERR_BADCRC;
+                               end_command = 1;
+                       } else
+                               dev_err(mmc_dev(host->mmc),
+                                       "command CRC error without cmd?\n");
+               }
+
+               if (status & OMAP_MMC_STAT_CARD_ERR) {
+                       if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
+                               u32 response = OMAP_MMC_READ(host, RSP6)
+                                       | (OMAP_MMC_READ(host, RSP7) << 16);
+                               /* STOP sometimes sets must-ignore bits */
+                               if (!(response & (R1_CC_ERROR
+                                                               | R1_ILLEGAL_COMMAND
+                                                               | R1_COM_CRC_ERROR))) {
+                                       end_command = 1;
+                                       continue;
+                               }
+                       }
+
+                       dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
+                               host->cmd->opcode);
+                       if (host->cmd) {
+                               host->cmd->error = MMC_ERR_FAILED;
+                               end_command = 1;
+                       }
+                       if (host->data) {
+                               host->data->error = MMC_ERR_FAILED;
+                               transfer_error = 1;
+                       }
+               }
+
+               /*
+                * NOTE: On 1610 the END_OF_CMD may come too early when
+                * starting a write 
+                */
+               if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
+                   (!(status & OMAP_MMC_STAT_A_EMPTY))) {
+                       end_command = 1;
+               }
+       }
+
+       if (end_command) {
+               mmc_omap_cmd_done(host, host->cmd);
+       }
+       if (transfer_error)
+               mmc_omap_xfer_done(host, host->data);
+       else if (end_transfer)
+               mmc_omap_end_of_data(host, host->data);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
+
+       schedule_work(&host->switch_work);
+
+       return IRQ_HANDLED;
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
+
+       schedule_work(&host->switch_work);
+}
+
+static void mmc_omap_switch_handler(struct work_struct *work)
+{
+       struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work);
+       struct mmc_card *card;
+       static int complained = 0;
+       int cards = 0, cover_open;
+
+       if (host->switch_pin == -1)
+               return;
+       cover_open = mmc_omap_cover_is_open(host);
+       if (cover_open != host->switch_last_state) {
+               kobject_uevent(&host->dev->kobj, KOBJ_CHANGE);
+               host->switch_last_state = cover_open;
+       }
+       mmc_detect_change(host->mmc, 0);
+       list_for_each_entry(card, &host->mmc->cards, node) {
+               if (mmc_card_present(card))
+                       cards++;
+       }
+       if (mmc_omap_cover_is_open(host)) {
+               if (!complained) {
+                       dev_info(mmc_dev(host->mmc), "cover is open\n");
+                       complained = 1;
+               }
+               if (mmc_omap_enable_poll)
+                       mod_timer(&host->switch_timer, jiffies +
+                               msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
+       } else {
+               complained = 0;
+       }
+}
+
+/* Prepare to transfer the next segment of a scatterlist */
+static void
+mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       int dma_ch = host->dma_ch;
+       unsigned long data_addr;
+       u16 buf, frame;
+       u32 count;
+       struct scatterlist *sg = &data->sg[host->sg_idx];
+       int src_port = 0;
+       int dst_port = 0;
+       int sync_dev = 0;
+
+       data_addr = host->phys_base + OMAP_MMC_REG_DATA;
+       frame = data->blksz;
+       count = sg_dma_len(sg);
+
+       if ((data->blocks == 1) && (count > data->blksz))
+               count = frame;
+
+       host->dma_len = count;
+
+       /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx.
+        * Use 16 or 32 word frames when the blocksize is at least that large.
+        * Blocksize is usually 512 bytes; but not for some SD reads.
+        */
+       if (cpu_is_omap15xx() && frame > 32)
+               frame = 32;
+       else if (frame > 64)
+               frame = 64;
+       count /= frame;
+       frame >>= 1;
+
+       if (!(data->flags & MMC_DATA_WRITE)) {
+               buf = 0x800f | ((frame - 1) << 8);
+
+               if (cpu_class_is_omap1()) {
+                       src_port = OMAP_DMA_PORT_TIPB;
+                       dst_port = OMAP_DMA_PORT_EMIFF;
+               }
+               if (cpu_is_omap24xx())
+                       sync_dev = OMAP24XX_DMA_MMC1_RX;
+
+               omap_set_dma_src_params(dma_ch, src_port,
+                                       OMAP_DMA_AMODE_CONSTANT,
+                                       data_addr, 0, 0);
+               omap_set_dma_dest_params(dma_ch, dst_port,
+                                        OMAP_DMA_AMODE_POST_INC,
+                                        sg_dma_address(sg), 0, 0);
+               omap_set_dma_dest_data_pack(dma_ch, 1);
+               omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+       } else {
+               buf = 0x0f80 | ((frame - 1) << 0);
+
+               if (cpu_class_is_omap1()) {
+                       src_port = OMAP_DMA_PORT_EMIFF;
+                       dst_port = OMAP_DMA_PORT_TIPB;
+               }
+               if (cpu_is_omap24xx())
+                       sync_dev = OMAP24XX_DMA_MMC1_TX;
+
+               omap_set_dma_dest_params(dma_ch, dst_port,
+                                        OMAP_DMA_AMODE_CONSTANT,
+                                        data_addr, 0, 0);
+               omap_set_dma_src_params(dma_ch, src_port,
+                                       OMAP_DMA_AMODE_POST_INC,
+                                       sg_dma_address(sg), 0, 0);
+               omap_set_dma_src_data_pack(dma_ch, 1);
+               omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+       }
+
+       /* Max limit for DMA frame count is 0xffff */
+       BUG_ON(count > 0xffff);
+
+       OMAP_MMC_WRITE(host, BUF, buf);
+       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
+                                    frame, count, OMAP_DMA_SYNC_FRAME,
+                                    sync_dev, 0);
+}
+
+/* A scatterlist segment completed */
+static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+       struct mmc_data *mmcdat = host->data;
+
+       if (unlikely(host->dma_ch < 0)) {
+               dev_err(mmc_dev(host->mmc),
+                       "DMA callback while DMA not enabled\n");
+               return;
+       }
+       /* FIXME: We really should do something to _handle_ the errors */
+       if (ch_status & OMAP1_DMA_TOUT_IRQ) {
+               dev_err(mmc_dev(host->mmc),"DMA timeout\n");
+               return;
+       }
+       if (ch_status & OMAP_DMA_DROP_IRQ) {
+               dev_err(mmc_dev(host->mmc), "DMA sync error\n");
+               return;
+       }
+       if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
+               return;
+       }
+       mmcdat->bytes_xfered += host->dma_len;
+       host->sg_idx++;
+       if (host->sg_idx < host->sg_len) {
+               mmc_omap_prepare_dma(host, host->data);
+               omap_start_dma(host->dma_ch);
+       } else
+               mmc_omap_dma_done(host, host->data);
+}
+
+static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       const char *dev_name;
+       int sync_dev, dma_ch, is_read, r;
+
+       is_read = !(data->flags & MMC_DATA_WRITE);
+       del_timer_sync(&host->dma_timer);
+       if (host->dma_ch >= 0) {
+               if (is_read == host->dma_is_read)
+                       return 0;
+               omap_free_dma(host->dma_ch);
+               host->dma_ch = -1;
+       }
+
+       if (is_read) {
+               if (host->id == 1) {
+                       sync_dev = OMAP_DMA_MMC_RX;
+                       dev_name = "MMC1 read";
+               } else {
+                       sync_dev = OMAP_DMA_MMC2_RX;
+                       dev_name = "MMC2 read";
+               }
+       } else {
+               if (host->id == 1) {
+                       sync_dev = OMAP_DMA_MMC_TX;
+                       dev_name = "MMC1 write";
+               } else {
+                       sync_dev = OMAP_DMA_MMC2_TX;
+                       dev_name = "MMC2 write";
+               }
+       }
+       r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb,
+                            host, &dma_ch);
+       if (r != 0) {
+               dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r);
+               return r;
+       }
+       host->dma_ch = dma_ch;
+       host->dma_is_read = is_read;
+
+       return 0;
+}
+
+static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       u16 reg;
+
+       reg = OMAP_MMC_READ(host, SDIO);
+       reg &= ~(1 << 5);
+       OMAP_MMC_WRITE(host, SDIO, reg);
+       /* Set maximum timeout */
+       OMAP_MMC_WRITE(host, CTO, 0xff);
+}
+
+static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       int timeout;
+       u16 reg;
+
+       /* Convert ns to clock cycles by assuming 20MHz frequency
+        * 1 cycle at 20MHz = 500 ns
+        */
+       timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
+
+       /* Check if we need to use timeout multiplier register */
+       reg = OMAP_MMC_READ(host, SDIO);
+       if (timeout > 0xffff) {
+               reg |= (1 << 5);
+               timeout /= 1024;
+       } else
+               reg &= ~(1 << 5);
+       OMAP_MMC_WRITE(host, SDIO, reg);
+       OMAP_MMC_WRITE(host, DTO, timeout);
+}
+
+static void
+mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       struct mmc_data *data = req->data;
+       int i, use_dma, block_size;
+       unsigned sg_len;
+
+       host->data = data;
+       if (data == NULL) {
+               OMAP_MMC_WRITE(host, BLEN, 0);
+               OMAP_MMC_WRITE(host, NBLK, 0);
+               OMAP_MMC_WRITE(host, BUF, 0);
+               host->dma_in_use = 0;
+               set_cmd_timeout(host, req);
+               return;
+       }
+
+       block_size = data->blksz;
+
+       OMAP_MMC_WRITE(host, NBLK, data->blocks - 1);
+       OMAP_MMC_WRITE(host, BLEN, block_size - 1);
+       set_data_timeout(host, req);
+
+       /* cope with calling layer confusion; it issues "single
+        * block" writes using multi-block scatterlists.
+        */
+       sg_len = (data->blocks == 1) ? 1 : data->sg_len;
+
+       /* Only do DMA for entire blocks */
+       use_dma = host->use_dma;
+       if (use_dma) {
+               for (i = 0; i < sg_len; i++) {
+                       if ((data->sg[i].length % block_size) != 0) {
+                               use_dma = 0;
+                               break;
+                       }
+               }
+       }
+
+       host->sg_idx = 0;
+       if (use_dma) {
+               if (mmc_omap_get_dma_channel(host, data) == 0) {
+                       enum dma_data_direction dma_data_dir;
+
+                       if (data->flags & MMC_DATA_WRITE)
+                               dma_data_dir = DMA_TO_DEVICE;
+                       else
+                               dma_data_dir = DMA_FROM_DEVICE;
+
+                       host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+                                               sg_len, dma_data_dir);
+                       host->total_bytes_left = 0;
+                       mmc_omap_prepare_dma(host, req->data);
+                       host->brs_received = 0;
+                       host->dma_done = 0;
+                       host->dma_in_use = 1;
+               } else
+                       use_dma = 0;
+       }
+
+       /* Revert to PIO? */
+       if (!use_dma) {
+               OMAP_MMC_WRITE(host, BUF, 0x1f1f);
+               host->total_bytes_left = data->blocks * block_size;
+               host->sg_len = sg_len;
+               mmc_omap_sg_to_buf(host);
+               host->dma_in_use = 0;
+       }
+}
+
+static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+
+       WARN_ON(host->mrq != NULL);
+
+       host->mrq = req;
+
+       /* only touch fifo AFTER the controller readies it */
+       mmc_omap_prepare_data(host, req);
+       mmc_omap_start_command(host, req->cmd);
+       if (host->dma_in_use)
+               omap_start_dma(host->dma_ch);
+}
+
+static void innovator_fpga_socket_power(int on)
+{
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+       if (on) {
+               fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+                    OMAP1510_FPGA_POWER);
+       } else {
+               fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+                    OMAP1510_FPGA_POWER);
+       }
+#endif
+}
+
+/*
+ * Turn the socket power on/off. Innovator uses FPGA, most boards
+ * probably use GPIO.
+ */
+static void mmc_omap_power(struct mmc_omap_host *host, int on)
+{
+       if (on) {
+               if (machine_is_omap_innovator())
+                       innovator_fpga_socket_power(1);
+               else if (machine_is_omap_h2())
+                       tps65010_set_gpio_out_value(GPIO3, HIGH);
+               else if (machine_is_omap_h3())
+                       /* GPIO 4 of TPS65010 sends SD_EN signal */
+                       tps65010_set_gpio_out_value(GPIO4, HIGH);
+               else if (cpu_is_omap24xx()) {
+                       u16 reg = OMAP_MMC_READ(host, CON);
+                       OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
+               } else
+                       if (host->power_pin >= 0)
+                               omap_set_gpio_dataout(host->power_pin, 1);
+       } else {
+               if (machine_is_omap_innovator())
+                       innovator_fpga_socket_power(0);
+               else if (machine_is_omap_h2())
+                       tps65010_set_gpio_out_value(GPIO3, LOW);
+               else if (machine_is_omap_h3())
+                       tps65010_set_gpio_out_value(GPIO4, LOW);
+               else if (cpu_is_omap24xx()) {
+                       u16 reg = OMAP_MMC_READ(host, CON);
+                       OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
+               } else
+                       if (host->power_pin >= 0)
+                               omap_set_gpio_dataout(host->power_pin, 0);
+       }
+}
+
+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;
+
+       if (ios->clock == 0)
+               return 0;
+
+       dsor = func_clk_rate / ios->clock;
+       if (dsor < 1)
+               dsor = 1;
+
+       if (func_clk_rate / dsor > ios->clock)
+               dsor++;
+
+       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:
+               /* Cannot touch dsor yet, just power up MMC */
+               mmc_omap_power(host, 1);
+               return;
+       case MMC_POWER_ON:
+               dsor |= 1 << 11;
+               break;
+       }
+
+       clk_enable(host->fclk);
+
+       /* On insanely high arm_per frequencies something sometimes
+        * goes somehow out of sync, and the POW bit is not being set,
+        * which results in the while loop below getting stuck.
+        * 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_ON) {
+               /* Send clock cycles, poll completion */
+               OMAP_MMC_WRITE(host, IE, 0);
+               OMAP_MMC_WRITE(host, STAT, 0xffff);
+               OMAP_MMC_WRITE(host, CMD, 1 << 7);
+               while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
+               OMAP_MMC_WRITE(host, STAT, 1);
+       }
+       clk_disable(host->fclk);
+}
+
+static int mmc_omap_get_ro(struct mmc_host *mmc)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+
+       return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
+}
+
+static const struct mmc_host_ops mmc_omap_ops = {
+       .request        = mmc_omap_request,
+       .set_ios        = mmc_omap_set_ios,
+       .get_ro         = mmc_omap_get_ro,
+};
+
+static int __init mmc_omap_probe(struct platform_device *pdev)
+{
+       struct omap_mmc_conf *minfo = pdev->dev.platform_data;
+       struct mmc_host *mmc;
+       struct mmc_omap_host *host = NULL;
+       struct resource *res;
+       int ret = 0;
+       int irq;
+
+       if (minfo == NULL) {
+               dev_err(&pdev->dev, "platform data missing\n");
+               return -ENXIO;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (res == NULL || irq < 0)
+               return -ENXIO;
+
+       res = request_mem_region(res->start, res->end - res->start + 1,
+                                pdev->name);
+       if (res == NULL)
+               return -EBUSY;
+
+       mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+       if (mmc == NULL) {
+               ret = -ENOMEM;
+               goto err_free_mem_region;
+       }
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       spin_lock_init(&host->dma_lock);
+       init_timer(&host->dma_timer);
+       host->dma_timer.function = mmc_omap_dma_timer;
+       host->dma_timer.data = (unsigned long) host;
+
+       host->id = pdev->id;
+       host->mem_res = res;
+       host->irq = irq;
+
+       if (cpu_is_omap24xx()) {
+               host->iclk = clk_get(&pdev->dev, "mmc_ick");
+               if (IS_ERR(host->iclk))
+                       goto err_free_mmc_host;
+               clk_enable(host->iclk);
+       }
+
+       if (!cpu_is_omap24xx())
+               host->fclk = clk_get(&pdev->dev, "mmc_ck");
+       else
+               host->fclk = clk_get(&pdev->dev, "mmc_fck");
+
+       if (IS_ERR(host->fclk)) {
+               ret = PTR_ERR(host->fclk);
+               goto err_free_iclk;
+       }
+
+       /* REVISIT:
+        * Also, use minfo->cover to decide how to manage
+        * the card detect sensing.
+        */
+       host->power_pin = minfo->power_pin;
+       host->switch_pin = minfo->switch_pin;
+       host->wp_pin = minfo->wp_pin;
+       host->use_dma = 1;
+       host->dma_ch = -1;
+
+       host->irq = irq;
+       host->phys_base = host->mem_res->start;
+       host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
+
+       mmc->ops = &mmc_omap_ops;
+       mmc->f_min = 400000;
+       mmc->f_max = 24000000;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
+
+       if (minfo->wire4)
+                mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+       /* Use scatterlist DMA to reduce per-transfer costs.
+        * NOTE max_seg_size assumption that small blocks aren't
+        * normally used (except e.g. for reading SD registers).
+        */
+       mmc->max_phys_segs = 32;
+       mmc->max_hw_segs = 32;
+       mmc->max_blk_size = 2048;       /* BLEN is 11 bits (+1) */
+       mmc->max_blk_count = 2048;      /* NBLK is 11 bits (+1) */
+       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+       mmc->max_seg_size = mmc->max_req_size;
+
+       if (host->power_pin >= 0) {
+               if ((ret = omap_request_gpio(host->power_pin)) != 0) {
+                       dev_err(mmc_dev(host->mmc),
+                               "Unable to get GPIO pin for MMC power\n");
+                       goto err_free_fclk;
+               }
+               omap_set_gpio_direction(host->power_pin, 0);
+       }
+
+       ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
+       if (ret)
+               goto err_free_power_gpio;
+
+       host->dev = &pdev->dev;
+       platform_set_drvdata(pdev, host);
+
+       if (host->switch_pin >= 0) {
+               INIT_WORK(&host->switch_work, mmc_omap_switch_handler);
+               init_timer(&host->switch_timer);
+               host->switch_timer.function = mmc_omap_switch_timer;
+               host->switch_timer.data = (unsigned long) host;
+               if (omap_request_gpio(host->switch_pin) != 0) {
+                       dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n");
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+
+               omap_set_gpio_direction(host->switch_pin, 1);
+               ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
+                                 mmc_omap_switch_irq, IRQF_TRIGGER_RISING, DRIVER_NAME, host);
+               if (ret) {
+                       dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n");
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+               ret = device_create_file(&pdev->dev, &dev_attr_cover_switch);
+               if (ret == 0) {
+                       ret = device_create_file(&pdev->dev, &dev_attr_enable_poll);
+                       if (ret != 0)
+                               device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+               }
+               if (ret) {
+                       dev_warn(mmc_dev(host->mmc), "Unable to create sysfs attributes\n");
+                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+               if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
+                       schedule_work(&host->switch_work);
+       }
+
+       mmc_add_host(mmc);
+
+       return 0;
+
+no_switch:
+       /* FIXME: Free other resources too. */
+       if (host) {
+               if (host->iclk && !IS_ERR(host->iclk))
+                       clk_put(host->iclk);
+               if (host->fclk && !IS_ERR(host->fclk))
+                       clk_put(host->fclk);
+               mmc_free_host(host->mmc);
+       }
+err_free_power_gpio:
+       if (host->power_pin >= 0)
+               omap_free_gpio(host->power_pin);
+err_free_fclk:
+       clk_put(host->fclk);
+err_free_iclk:
+       if (host->iclk != NULL) {
+               clk_disable(host->iclk);
+               clk_put(host->iclk);
+       }
+err_free_mmc_host:
+       mmc_free_host(host->mmc);
+err_free_mem_region:
+       release_mem_region(res->start, res->end - res->start + 1);
+       return ret;
+}
+
+static int mmc_omap_remove(struct platform_device *pdev)
+{
+       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       BUG_ON(host == NULL);
+
+       mmc_remove_host(host->mmc);
+       free_irq(host->irq, host);
+
+       if (host->power_pin >= 0)
+               omap_free_gpio(host->power_pin);
+       if (host->switch_pin >= 0) {
+               device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+               device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+               free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+               omap_free_gpio(host->switch_pin);
+               host->switch_pin = -1;
+               del_timer_sync(&host->switch_timer);
+               flush_scheduled_work();
+       }
+       if (host->iclk && !IS_ERR(host->iclk))
+               clk_put(host->iclk);
+       if (host->fclk && !IS_ERR(host->fclk))
+               clk_put(host->fclk);
+
+       release_mem_region(pdev->resource[0].start,
+                          pdev->resource[0].end - pdev->resource[0].start + 1);
+
+       mmc_free_host(host->mmc);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       int ret = 0;
+       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+       if (host && host->suspended)
+               return 0;
+
+       if (host) {
+               ret = mmc_suspend_host(host->mmc, mesg);
+               if (ret == 0)
+                       host->suspended = 1;
+       }
+       return ret;
+}
+
+static int mmc_omap_resume(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+       if (host && !host->suspended)
+               return 0;
+
+       if (host) {
+               ret = mmc_resume_host(host->mmc);
+               if (ret == 0)
+                       host->suspended = 0;
+       }
+
+       return ret;
+}
+#else
+#define mmc_omap_suspend       NULL
+#define mmc_omap_resume                NULL
+#endif
+
+static struct platform_driver mmc_omap_driver = {
+       .probe          = mmc_omap_probe,
+       .remove         = mmc_omap_remove,
+       .suspend        = mmc_omap_suspend,
+       .resume         = mmc_omap_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init mmc_omap_init(void)
+{
+       return platform_driver_register(&mmc_omap_driver);
+}
+
+static void __exit mmc_omap_exit(void)
+{
+       platform_driver_unregister(&mmc_omap_driver);
+}
+
+module_init(mmc_omap_init);
+module_exit(mmc_omap_exit);
+
+MODULE_DESCRIPTION("OMAP Multimedia Card driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_AUTHOR("Juha Yrjölä");
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
new file mode 100644 (file)
index 0000000..d97d386
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ *  linux/drivers/mmc/pxa.c - PXA MMCI driver
+ *
+ *  Copyright (C) 2003 Russell King, 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.
+ *
+ *  This hardware is really sick:
+ *   - No way to clear interrupts.
+ *   - Have to turn off the clock whenever we touch the device.
+ *   - Doesn't tell you how many data blocks were transferred.
+ *  Yuck!
+ *
+ *     1 and 3 byte data transfers not supported
+ *     max block length up to 1023
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/mmc.h>
+
+#include "pxamci.h"
+
+#define DRIVER_NAME    "pxa2xx-mci"
+
+#define NR_SG  1
+
+struct pxamci_host {
+       struct mmc_host         *mmc;
+       spinlock_t              lock;
+       struct resource         *res;
+       void __iomem            *base;
+       int                     irq;
+       int                     dma;
+       unsigned int            clkrt;
+       unsigned int            cmdat;
+       unsigned int            imask;
+       unsigned int            power_mode;
+       struct pxamci_platform_data *pdata;
+
+       struct mmc_request      *mrq;
+       struct mmc_command      *cmd;
+       struct mmc_data         *data;
+
+       dma_addr_t              sg_dma;
+       struct pxa_dma_desc     *sg_cpu;
+       unsigned int            dma_len;
+
+       unsigned int            dma_dir;
+};
+
+static void pxamci_stop_clock(struct pxamci_host *host)
+{
+       if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
+               unsigned long timeout = 10000;
+               unsigned int v;
+
+               writel(STOP_CLOCK, host->base + MMC_STRPCL);
+
+               do {
+                       v = readl(host->base + MMC_STAT);
+                       if (!(v & STAT_CLK_EN))
+                               break;
+                       udelay(1);
+               } while (timeout--);
+
+               if (v & STAT_CLK_EN)
+                       dev_err(mmc_dev(host->mmc), "unable to stop clock\n");
+       }
+}
+
+static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->imask &= ~mask;
+       writel(host->imask, host->base + MMC_I_MASK);
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->imask |= mask;
+       writel(host->imask, host->base + MMC_I_MASK);
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
+{
+       unsigned int nob = data->blocks;
+       unsigned long long clks;
+       unsigned int timeout;
+       u32 dcmd;
+       int i;
+
+       host->data = data;
+
+       if (data->flags & MMC_DATA_STREAM)
+               nob = 0xffff;
+
+       writel(nob, host->base + MMC_NOB);
+       writel(data->blksz, host->base + MMC_BLKLEN);
+
+       clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
+       do_div(clks, 1000000000UL);
+       timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
+       writel((timeout + 255) / 256, host->base + MMC_RDTO);
+
+       if (data->flags & MMC_DATA_READ) {
+               host->dma_dir = DMA_FROM_DEVICE;
+               dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
+               DRCMRTXMMC = 0;
+               DRCMRRXMMC = host->dma | DRCMR_MAPVLD;
+       } else {
+               host->dma_dir = DMA_TO_DEVICE;
+               dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
+               DRCMRRXMMC = 0;
+               DRCMRTXMMC = host->dma | DRCMR_MAPVLD;
+       }
+
+       dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
+
+       host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+                                  host->dma_dir);
+
+       for (i = 0; i < host->dma_len; i++) {
+               if (data->flags & MMC_DATA_READ) {
+                       host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
+                       host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
+               } else {
+                       host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);
+                       host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
+               }
+               host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]);
+               host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
+                                       sizeof(struct pxa_dma_desc);
+       }
+       host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;
+       wmb();
+
+       DDADR(host->dma) = host->sg_dma;
+       DCSR(host->dma) = DCSR_RUN;
+}
+
+static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+       WARN_ON(host->cmd != NULL);
+       host->cmd = cmd;
+
+       if (cmd->flags & MMC_RSP_BUSY)
+               cmdat |= CMDAT_BUSY;
+
+#define RSP_TYPE(x)    ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
+       switch (RSP_TYPE(mmc_resp_type(cmd))) {
+       case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */
+               cmdat |= CMDAT_RESP_SHORT;
+               break;
+       case RSP_TYPE(MMC_RSP_R3):
+               cmdat |= CMDAT_RESP_R3;
+               break;
+       case RSP_TYPE(MMC_RSP_R2):
+               cmdat |= CMDAT_RESP_R2;
+               break;
+       default:
+               break;
+       }
+
+       writel(cmd->opcode, host->base + MMC_CMD);
+       writel(cmd->arg >> 16, host->base + MMC_ARGH);
+       writel(cmd->arg & 0xffff, host->base + MMC_ARGL);
+       writel(cmdat, host->base + MMC_CMDAT);
+       writel(host->clkrt, host->base + MMC_CLKRT);
+
+       writel(START_CLOCK, host->base + MMC_STRPCL);
+
+       pxamci_enable_irq(host, END_CMD_RES);
+}
+
+static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
+{
+       host->mrq = NULL;
+       host->cmd = NULL;
+       host->data = NULL;
+       mmc_request_done(host->mmc, mrq);
+}
+
+static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
+{
+       struct mmc_command *cmd = host->cmd;
+       int i;
+       u32 v;
+
+       if (!cmd)
+               return 0;
+
+       host->cmd = NULL;
+
+       /*
+        * Did I mention this is Sick.  We always need to
+        * discard the upper 8 bits of the first 16-bit word.
+        */
+       v = readl(host->base + MMC_RES) & 0xffff;
+       for (i = 0; i < 4; i++) {
+               u32 w1 = readl(host->base + MMC_RES) & 0xffff;
+               u32 w2 = readl(host->base + MMC_RES) & 0xffff;
+               cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8;
+               v = w2;
+       }
+
+       if (stat & STAT_TIME_OUT_RESPONSE) {
+               cmd->error = MMC_ERR_TIMEOUT;
+       } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+#ifdef CONFIG_PXA27x
+               /*
+                * workaround for erratum #42:
+                * Intel PXA27x Family Processor Specification Update Rev 001
+                */
+               if (cmd->opcode == MMC_ALL_SEND_CID ||
+                   cmd->opcode == MMC_SEND_CSD ||
+                   cmd->opcode == MMC_SEND_CID) {
+                       /* a bogus CRC error can appear if the msb of
+                          the 15 byte response is a one */
+                       if ((cmd->resp[0] & 0x80000000) == 0)
+                               cmd->error = MMC_ERR_BADCRC;
+               } else {
+                       pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode);
+               }
+#else
+               cmd->error = MMC_ERR_BADCRC;
+#endif
+       }
+
+       pxamci_disable_irq(host, END_CMD_RES);
+       if (host->data && cmd->error == MMC_ERR_NONE) {
+               pxamci_enable_irq(host, DATA_TRAN_DONE);
+       } else {
+               pxamci_finish_request(host, host->mrq);
+       }
+
+       return 1;
+}
+
+static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
+{
+       struct mmc_data *data = host->data;
+
+       if (!data)
+               return 0;
+
+       DCSR(host->dma) = 0;
+       dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+                    host->dma_dir);
+
+       if (stat & STAT_READ_TIME_OUT)
+               data->error = MMC_ERR_TIMEOUT;
+       else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR))
+               data->error = MMC_ERR_BADCRC;
+
+       /*
+        * There appears to be a hardware design bug here.  There seems to
+        * be no way to find out how much data was transferred to the card.
+        * This means that if there was an error on any block, we mark all
+        * data blocks as being in error.
+        */
+       if (data->error == MMC_ERR_NONE)
+               data->bytes_xfered = data->blocks * data->blksz;
+       else
+               data->bytes_xfered = 0;
+
+       pxamci_disable_irq(host, DATA_TRAN_DONE);
+
+       host->data = NULL;
+       if (host->mrq->stop) {
+               pxamci_stop_clock(host);
+               pxamci_start_cmd(host, host->mrq->stop, 0);
+       } else {
+               pxamci_finish_request(host, host->mrq);
+       }
+
+       return 1;
+}
+
+static irqreturn_t pxamci_irq(int irq, void *devid)
+{
+       struct pxamci_host *host = devid;
+       unsigned int ireg;
+       int handled = 0;
+
+       ireg = readl(host->base + MMC_I_REG);
+
+       if (ireg) {
+               unsigned stat = readl(host->base + MMC_STAT);
+
+               pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
+
+               if (ireg & END_CMD_RES)
+                       handled |= pxamci_cmd_done(host, stat);
+               if (ireg & DATA_TRAN_DONE)
+                       handled |= pxamci_data_done(host, stat);
+       }
+
+       return IRQ_RETVAL(handled);
+}
+
+static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct pxamci_host *host = mmc_priv(mmc);
+       unsigned int cmdat;
+
+       WARN_ON(host->mrq != NULL);
+
+       host->mrq = mrq;
+
+       pxamci_stop_clock(host);
+
+       cmdat = host->cmdat;
+       host->cmdat &= ~CMDAT_INIT;
+
+       if (mrq->data) {
+               pxamci_setup_data(host, mrq->data);
+
+               cmdat &= ~CMDAT_BUSY;
+               cmdat |= CMDAT_DATAEN | CMDAT_DMAEN;
+               if (mrq->data->flags & MMC_DATA_WRITE)
+                       cmdat |= CMDAT_WRITE;
+
+               if (mrq->data->flags & MMC_DATA_STREAM)
+                       cmdat |= CMDAT_STREAM;
+       }
+
+       pxamci_start_cmd(host, mrq->cmd, cmdat);
+}
+
+static int pxamci_get_ro(struct mmc_host *mmc)
+{
+       struct pxamci_host *host = mmc_priv(mmc);
+
+       if (host->pdata && host->pdata->get_ro)
+               return host->pdata->get_ro(mmc_dev(mmc));
+       /* Host doesn't support read only detection so assume writeable */
+       return 0;
+}
+
+static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct pxamci_host *host = mmc_priv(mmc);
+
+       if (ios->clock) {
+               unsigned int clk = CLOCKRATE / ios->clock;
+               if (CLOCKRATE / clk > ios->clock)
+                       clk <<= 1;
+               host->clkrt = fls(clk) - 1;
+               pxa_set_cken(CKEN_MMC, 1);
+
+               /*
+                * we write clkrt on the next command
+                */
+       } else {
+               pxamci_stop_clock(host);
+               pxa_set_cken(CKEN_MMC, 0);
+       }
+
+       if (host->power_mode != ios->power_mode) {
+               host->power_mode = ios->power_mode;
+
+               if (host->pdata && host->pdata->setpower)
+                       host->pdata->setpower(mmc_dev(mmc), ios->vdd);
+
+               if (ios->power_mode == MMC_POWER_ON)
+                       host->cmdat |= CMDAT_INIT;
+       }
+
+       pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
+                host->clkrt, host->cmdat);
+}
+
+static const struct mmc_host_ops pxamci_ops = {
+       .request        = pxamci_request,
+       .get_ro         = pxamci_get_ro,
+       .set_ios        = pxamci_set_ios,
+};
+
+static void pxamci_dma_irq(int dma, void *devid)
+{
+       printk(KERN_ERR "DMA%d: IRQ???\n", dma);
+       DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+}
+
+static irqreturn_t pxamci_detect_irq(int irq, void *devid)
+{
+       struct pxamci_host *host = mmc_priv(devid);
+
+       mmc_detect_change(devid, host->pdata->detect_delay);
+       return IRQ_HANDLED;
+}
+
+static int pxamci_probe(struct platform_device *pdev)
+{
+       struct mmc_host *mmc;
+       struct pxamci_host *host = NULL;
+       struct resource *r;
+       int ret, irq;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!r || irq < 0)
+               return -ENXIO;
+
+       r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
+       if (!r)
+               return -EBUSY;
+
+       mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       mmc->ops = &pxamci_ops;
+       mmc->f_min = CLOCKRATE_MIN;
+       mmc->f_max = CLOCKRATE_MAX;
+
+       /*
+        * We can do SG-DMA, but we don't because we never know how much
+        * data we successfully wrote to the card.
+        */
+       mmc->max_phys_segs = NR_SG;
+
+       /*
+        * Our hardware DMA can handle a maximum of one page per SG entry.
+        */
+       mmc->max_seg_size = PAGE_SIZE;
+
+       /*
+        * Block length register is 10 bits.
+        */
+       mmc->max_blk_size = 1023;
+
+       /*
+        * Block count register is 16 bits.
+        */
+       mmc->max_blk_count = 65535;
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+       host->dma = -1;
+       host->pdata = pdev->dev.platform_data;
+       mmc->ocr_avail = host->pdata ?
+                        host->pdata->ocr_mask :
+                        MMC_VDD_32_33|MMC_VDD_33_34;
+
+       host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);
+       if (!host->sg_cpu) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       spin_lock_init(&host->lock);
+       host->res = r;
+       host->irq = irq;
+       host->imask = MMC_I_MASK_ALL;
+
+       host->base = ioremap(r->start, SZ_4K);
+       if (!host->base) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /*
+        * Ensure that the host controller is shut down, and setup
+        * with our defaults.
+        */
+       pxamci_stop_clock(host);
+       writel(0, host->base + MMC_SPI);
+       writel(64, host->base + MMC_RESTO);
+       writel(host->imask, host->base + MMC_I_MASK);
+
+       host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,
+                                   pxamci_dma_irq, host);
+       if (host->dma < 0) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
+       if (ret)
+               goto out;
+
+       platform_set_drvdata(pdev, mmc);
+
+       if (host->pdata && host->pdata->init)
+               host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc);
+
+       mmc_add_host(mmc);
+
+       return 0;
+
+ out:
+       if (host) {
+               if (host->dma >= 0)
+                       pxa_free_dma(host->dma);
+               if (host->base)
+                       iounmap(host->base);
+               if (host->sg_cpu)
+                       dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+       }
+       if (mmc)
+               mmc_free_host(mmc);
+       release_resource(r);
+       return ret;
+}
+
+static int pxamci_remove(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (mmc) {
+               struct pxamci_host *host = mmc_priv(mmc);
+
+               if (host->pdata && host->pdata->exit)
+                       host->pdata->exit(&pdev->dev, mmc);
+
+               mmc_remove_host(mmc);
+
+               pxamci_stop_clock(host);
+               writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
+                      END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
+                      host->base + MMC_I_MASK);
+
+               DRCMRRXMMC = 0;
+               DRCMRTXMMC = 0;
+
+               free_irq(host->irq, host);
+               pxa_free_dma(host->dma);
+               iounmap(host->base);
+               dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+
+               release_resource(host->res);
+
+               mmc_free_host(mmc);
+       }
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int pxamci_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct mmc_host *mmc = platform_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc)
+               ret = mmc_suspend_host(mmc, state);
+
+       return ret;
+}
+
+static int pxamci_resume(struct platform_device *dev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc)
+               ret = mmc_resume_host(mmc);
+
+       return ret;
+}
+#else
+#define pxamci_suspend NULL
+#define pxamci_resume  NULL
+#endif
+
+static struct platform_driver pxamci_driver = {
+       .probe          = pxamci_probe,
+       .remove         = pxamci_remove,
+       .suspend        = pxamci_suspend,
+       .resume         = pxamci_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init pxamci_init(void)
+{
+       return platform_driver_register(&pxamci_driver);
+}
+
+static void __exit pxamci_exit(void)
+{
+       platform_driver_unregister(&pxamci_driver);
+}
+
+module_init(pxamci_init);
+module_exit(pxamci_exit);
+
+MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h
new file mode 100644 (file)
index 0000000..1b16322
--- /dev/null
@@ -0,0 +1,124 @@
+#undef MMC_STRPCL
+#undef MMC_STAT
+#undef MMC_CLKRT
+#undef MMC_SPI
+#undef MMC_CMDAT
+#undef MMC_RESTO
+#undef MMC_RDTO
+#undef MMC_BLKLEN
+#undef MMC_NOB
+#undef MMC_PRTBUF
+#undef MMC_I_MASK
+#undef END_CMD_RES
+#undef PRG_DONE
+#undef DATA_TRAN_DONE
+#undef MMC_I_REG
+#undef MMC_CMD
+#undef MMC_ARGH
+#undef MMC_ARGL
+#undef MMC_RES
+#undef MMC_RXFIFO
+#undef MMC_TXFIFO
+
+#define MMC_STRPCL     0x0000
+#define STOP_CLOCK             (1 << 0)
+#define START_CLOCK            (2 << 0)
+
+#define MMC_STAT       0x0004
+#define STAT_END_CMD_RES               (1 << 13)
+#define STAT_PRG_DONE                  (1 << 12)
+#define STAT_DATA_TRAN_DONE            (1 << 11)
+#define STAT_CLK_EN                    (1 << 8)
+#define STAT_RECV_FIFO_FULL            (1 << 7)
+#define STAT_XMIT_FIFO_EMPTY           (1 << 6)
+#define STAT_RES_CRC_ERR               (1 << 5)
+#define STAT_SPI_READ_ERROR_TOKEN      (1 << 4)
+#define STAT_CRC_READ_ERROR            (1 << 3)
+#define STAT_CRC_WRITE_ERROR           (1 << 2)
+#define STAT_TIME_OUT_RESPONSE         (1 << 1)
+#define STAT_READ_TIME_OUT             (1 << 0)
+
+#define MMC_CLKRT      0x0008          /* 3 bit */
+
+#define MMC_SPI                0x000c
+#define SPI_CS_ADDRESS         (1 << 3)
+#define SPI_CS_EN              (1 << 2)
+#define CRC_ON                 (1 << 1)
+#define SPI_EN                 (1 << 0)
+
+#define MMC_CMDAT      0x0010
+#define CMDAT_DMAEN            (1 << 7)
+#define CMDAT_INIT             (1 << 6)
+#define CMDAT_BUSY             (1 << 5)
+#define CMDAT_STREAM           (1 << 4)        /* 1 = stream */
+#define CMDAT_WRITE            (1 << 3)        /* 1 = write */
+#define CMDAT_DATAEN           (1 << 2)
+#define CMDAT_RESP_NONE                (0 << 0)
+#define CMDAT_RESP_SHORT       (1 << 0)
+#define CMDAT_RESP_R2          (2 << 0)
+#define CMDAT_RESP_R3          (3 << 0)
+
+#define MMC_RESTO      0x0014  /* 7 bit */
+
+#define MMC_RDTO       0x0018  /* 16 bit */
+
+#define MMC_BLKLEN     0x001c  /* 10 bit */
+
+#define MMC_NOB                0x0020  /* 16 bit */
+
+#define MMC_PRTBUF     0x0024
+#define BUF_PART_FULL          (1 << 0)
+
+#define MMC_I_MASK     0x0028
+
+/*PXA27x MMC interrupts*/
+#define SDIO_SUSPEND_ACK       (1 << 12)
+#define SDIO_INT               (1 << 11)
+#define RD_STALLED             (1 << 10)
+#define RES_ERR                (1 << 9)
+#define DAT_ERR                (1 << 8)
+#define TINT                   (1 << 7)
+
+/*PXA2xx MMC interrupts*/
+#define TXFIFO_WR_REQ          (1 << 6)
+#define RXFIFO_RD_REQ          (1 << 5)
+#define CLK_IS_OFF             (1 << 4)
+#define STOP_CMD               (1 << 3)
+#define END_CMD_RES            (1 << 2)
+#define PRG_DONE               (1 << 1)
+#define DATA_TRAN_DONE         (1 << 0)
+
+#ifdef CONFIG_PXA27x
+#define MMC_I_MASK_ALL          0x00001fff
+#else
+#define MMC_I_MASK_ALL          0x0000007f
+#endif
+
+#define MMC_I_REG      0x002c
+/* same as MMC_I_MASK */
+
+#define MMC_CMD                0x0030
+
+#define MMC_ARGH       0x0034  /* 16 bit */
+
+#define MMC_ARGL       0x0038  /* 16 bit */
+
+#define MMC_RES                0x003c  /* 16 bit */
+
+#define MMC_RXFIFO     0x0040  /* 8 bit */
+
+#define MMC_TXFIFO     0x0044  /* 8 bit */
+
+/*
+ * The base MMC clock rate
+ */
+#ifdef CONFIG_PXA27x
+#define CLOCKRATE_MIN  304688
+#define CLOCKRATE_MAX  19500000
+#else
+#define CLOCKRATE_MIN  312500
+#define CLOCKRATE_MAX  20000000
+#endif
+
+#define CLOCKRATE      CLOCKRATE_MAX
+
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
new file mode 100644 (file)
index 0000000..ff5bf73
--- /dev/null
@@ -0,0 +1,1535 @@
+/*
+ *  linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
+ *
+ *  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.
+ */
+
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/mmc/host.h>
+
+#include <asm/scatterlist.h>
+
+#include "sdhci.h"
+
+#define DRIVER_NAME "sdhci"
+
+#define DBG(f, x...) \
+       pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
+
+static unsigned int debug_nodma = 0;
+static unsigned int debug_forcedma = 0;
+static unsigned int debug_quirks = 0;
+
+#define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
+#define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
+/* Controller doesn't like some resets when there is no card inserted. */
+#define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
+
+static const struct pci_device_id pci_ids[] __devinitdata = {
+       {
+               .vendor         = PCI_VENDOR_ID_RICOH,
+               .device         = PCI_DEVICE_ID_RICOH_R5C822,
+               .subvendor      = PCI_VENDOR_ID_IBM,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_CLOCK_BEFORE_RESET |
+                                 SDHCI_QUIRK_FORCE_DMA,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_RICOH,
+               .device         = PCI_DEVICE_ID_RICOH_R5C822,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_FORCE_DMA |
+                                 SDHCI_QUIRK_NO_CARD_NO_RESET,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_TI,
+               .device         = PCI_DEVICE_ID_TI_XX21_XX11_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_FORCE_DMA,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_ENE,
+               .device         = PCI_DEVICE_ID_ENE_CB712_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+       },
+
+       {       /* Generic SD host controller */
+               PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
+       },
+
+       { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
+static void sdhci_finish_data(struct sdhci_host *);
+
+static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
+static void sdhci_finish_command(struct sdhci_host *);
+
+static void sdhci_dumpregs(struct sdhci_host *host)
+{
+       printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
+
+       printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
+               readl(host->ioaddr + SDHCI_DMA_ADDRESS),
+               readw(host->ioaddr + SDHCI_HOST_VERSION));
+       printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
+               readw(host->ioaddr + SDHCI_BLOCK_SIZE),
+               readw(host->ioaddr + SDHCI_BLOCK_COUNT));
+       printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
+               readl(host->ioaddr + SDHCI_ARGUMENT),
+               readw(host->ioaddr + SDHCI_TRANSFER_MODE));
+       printk(KERN_DEBUG DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
+               readl(host->ioaddr + SDHCI_PRESENT_STATE),
+               readb(host->ioaddr + SDHCI_HOST_CONTROL));
+       printk(KERN_DEBUG DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
+               readb(host->ioaddr + SDHCI_POWER_CONTROL),
+               readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
+       printk(KERN_DEBUG DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
+               readb(host->ioaddr + SDHCI_WALK_UP_CONTROL),
+               readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
+       printk(KERN_DEBUG DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
+               readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
+               readl(host->ioaddr + SDHCI_INT_STATUS));
+       printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
+               readl(host->ioaddr + SDHCI_INT_ENABLE),
+               readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
+       printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
+               readw(host->ioaddr + SDHCI_ACMD12_ERR),
+               readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
+       printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Max curr: 0x%08x\n",
+               readl(host->ioaddr + SDHCI_CAPABILITIES),
+               readl(host->ioaddr + SDHCI_MAX_CURRENT));
+
+       printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Low level functions                                                       *
+ *                                                                           *
+\*****************************************************************************/
+
+static void sdhci_reset(struct sdhci_host *host, u8 mask)
+{
+       unsigned long timeout;
+
+       if (host->chip->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
+               if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+                       SDHCI_CARD_PRESENT))
+                       return;
+       }
+
+       writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
+
+       if (mask & SDHCI_RESET_ALL)
+               host->clock = 0;
+
+       /* Wait max 100 ms */
+       timeout = 100;
+
+       /* hw clears the bit when it's done */
+       while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
+               if (timeout == 0) {
+                       printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
+                               mmc_hostname(host->mmc), (int)mask);
+                       sdhci_dumpregs(host);
+                       return;
+               }
+               timeout--;
+               mdelay(1);
+       }
+}
+
+static void sdhci_init(struct sdhci_host *host)
+{
+       u32 intmask;
+
+       sdhci_reset(host, SDHCI_RESET_ALL);
+
+       intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+               SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
+               SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
+               SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
+               SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
+               SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
+
+       writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
+       writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_activate_led(struct sdhci_host *host)
+{
+       u8 ctrl;
+
+       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       ctrl |= SDHCI_CTRL_LED;
+       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+}
+
+static void sdhci_deactivate_led(struct sdhci_host *host)
+{
+       u8 ctrl;
+
+       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       ctrl &= ~SDHCI_CTRL_LED;
+       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Core functions                                                            *
+ *                                                                           *
+\*****************************************************************************/
+
+static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
+{
+       return page_address(host->cur_sg->page) + host->cur_sg->offset;
+}
+
+static inline int sdhci_next_sg(struct sdhci_host* host)
+{
+       /*
+        * Skip to next SG entry.
+        */
+       host->cur_sg++;
+       host->num_sg--;
+
+       /*
+        * Any entries left?
+        */
+       if (host->num_sg > 0) {
+               host->offset = 0;
+               host->remain = host->cur_sg->length;
+       }
+
+       return host->num_sg;
+}
+
+static void sdhci_read_block_pio(struct sdhci_host *host)
+{
+       int blksize, chunk_remain;
+       u32 data;
+       char *buffer;
+       int size;
+
+       DBG("PIO reading\n");
+
+       blksize = host->data->blksz;
+       chunk_remain = 0;
+       data = 0;
+
+       buffer = sdhci_sg_to_buffer(host) + host->offset;
+
+       while (blksize) {
+               if (chunk_remain == 0) {
+                       data = readl(host->ioaddr + SDHCI_BUFFER);
+                       chunk_remain = min(blksize, 4);
+               }
+
+               size = min(host->remain, chunk_remain);
+
+               chunk_remain -= size;
+               blksize -= size;
+               host->offset += size;
+               host->remain -= size;
+
+               while (size) {
+                       *buffer = data & 0xFF;
+                       buffer++;
+                       data >>= 8;
+                       size--;
+               }
+
+               if (host->remain == 0) {
+                       if (sdhci_next_sg(host) == 0) {
+                               BUG_ON(blksize != 0);
+                               return;
+                       }
+                       buffer = sdhci_sg_to_buffer(host);
+               }
+       }
+}
+
+static void sdhci_write_block_pio(struct sdhci_host *host)
+{
+       int blksize, chunk_remain;
+       u32 data;
+       char *buffer;
+       int bytes, size;
+
+       DBG("PIO writing\n");
+
+       blksize = host->data->blksz;
+       chunk_remain = 4;
+       data = 0;
+
+       bytes = 0;
+       buffer = sdhci_sg_to_buffer(host) + host->offset;
+
+       while (blksize) {
+               size = min(host->remain, chunk_remain);
+
+               chunk_remain -= size;
+               blksize -= size;
+               host->offset += size;
+               host->remain -= size;
+
+               while (size) {
+                       data >>= 8;
+                       data |= (u32)*buffer << 24;
+                       buffer++;
+                       size--;
+               }
+
+               if (chunk_remain == 0) {
+                       writel(data, host->ioaddr + SDHCI_BUFFER);
+                       chunk_remain = min(blksize, 4);
+               }
+
+               if (host->remain == 0) {
+                       if (sdhci_next_sg(host) == 0) {
+                               BUG_ON(blksize != 0);
+                               return;
+                       }
+                       buffer = sdhci_sg_to_buffer(host);
+               }
+       }
+}
+
+static void sdhci_transfer_pio(struct sdhci_host *host)
+{
+       u32 mask;
+
+       BUG_ON(!host->data);
+
+       if (host->num_sg == 0)
+               return;
+
+       if (host->data->flags & MMC_DATA_READ)
+               mask = SDHCI_DATA_AVAILABLE;
+       else
+               mask = SDHCI_SPACE_AVAILABLE;
+
+       while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
+               if (host->data->flags & MMC_DATA_READ)
+                       sdhci_read_block_pio(host);
+               else
+                       sdhci_write_block_pio(host);
+
+               if (host->num_sg == 0)
+                       break;
+       }
+
+       DBG("PIO transfer complete.\n");
+}
+
+static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
+{
+       u8 count;
+       unsigned target_timeout, current_timeout;
+
+       WARN_ON(host->data);
+
+       if (data == NULL)
+               return;
+
+       DBG("blksz %04x blks %04x flags %08x\n",
+               data->blksz, data->blocks, data->flags);
+       DBG("tsac %d ms nsac %d clk\n",
+               data->timeout_ns / 1000000, data->timeout_clks);
+
+       /* Sanity checks */
+       BUG_ON(data->blksz * data->blocks > 524288);
+       BUG_ON(data->blksz > host->mmc->max_blk_size);
+       BUG_ON(data->blocks > 65535);
+
+       /* timeout in us */
+       target_timeout = data->timeout_ns / 1000 +
+               data->timeout_clks / host->clock;
+
+       /*
+        * Figure out needed cycles.
+        * We do this in steps in order to fit inside a 32 bit int.
+        * The first step is the minimum timeout, which will have a
+        * minimum resolution of 6 bits:
+        * (1) 2^13*1000 > 2^22,
+        * (2) host->timeout_clk < 2^16
+        *     =>
+        *     (1) / (2) > 2^6
+        */
+       count = 0;
+       current_timeout = (1 << 13) * 1000 / host->timeout_clk;
+       while (current_timeout < target_timeout) {
+               count++;
+               current_timeout <<= 1;
+               if (count >= 0xF)
+                       break;
+       }
+
+       if (count >= 0xF) {
+               printk(KERN_WARNING "%s: Too large timeout requested!\n",
+                       mmc_hostname(host->mmc));
+               count = 0xE;
+       }
+
+       writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
+
+       if (host->flags & SDHCI_USE_DMA) {
+               int count;
+
+               count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len,
+                       (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
+               BUG_ON(count != 1);
+
+               writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
+       } else {
+               host->cur_sg = data->sg;
+               host->num_sg = data->sg_len;
+
+               host->offset = 0;
+               host->remain = host->cur_sg->length;
+       }
+
+       /* We do not handle DMA boundaries, so set it to max (512 KiB) */
+       writew(SDHCI_MAKE_BLKSZ(7, data->blksz),
+               host->ioaddr + SDHCI_BLOCK_SIZE);
+       writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
+}
+
+static void sdhci_set_transfer_mode(struct sdhci_host *host,
+       struct mmc_data *data)
+{
+       u16 mode;
+
+       WARN_ON(host->data);
+
+       if (data == NULL)
+               return;
+
+       mode = SDHCI_TRNS_BLK_CNT_EN;
+       if (data->blocks > 1)
+               mode |= SDHCI_TRNS_MULTI;
+       if (data->flags & MMC_DATA_READ)
+               mode |= SDHCI_TRNS_READ;
+       if (host->flags & SDHCI_USE_DMA)
+               mode |= SDHCI_TRNS_DMA;
+
+       writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
+}
+
+static void sdhci_finish_data(struct sdhci_host *host)
+{
+       struct mmc_data *data;
+       u16 blocks;
+
+       BUG_ON(!host->data);
+
+       data = host->data;
+       host->data = NULL;
+
+       if (host->flags & SDHCI_USE_DMA) {
+               pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len,
+                       (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
+       }
+
+       /*
+        * Controller doesn't count down when in single block mode.
+        */
+       if ((data->blocks == 1) && (data->error == MMC_ERR_NONE))
+               blocks = 0;
+       else
+               blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
+       data->bytes_xfered = data->blksz * (data->blocks - blocks);
+
+       if ((data->error == MMC_ERR_NONE) && blocks) {
+               printk(KERN_ERR "%s: Controller signalled completion even "
+                       "though there were blocks left.\n",
+                       mmc_hostname(host->mmc));
+               data->error = MMC_ERR_FAILED;
+       }
+
+       DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
+
+       if (data->stop) {
+               /*
+                * The controller needs a reset of internal state machines
+                * upon error conditions.
+                */
+               if (data->error != MMC_ERR_NONE) {
+                       sdhci_reset(host, SDHCI_RESET_CMD);
+                       sdhci_reset(host, SDHCI_RESET_DATA);
+               }
+
+               sdhci_send_command(host, data->stop);
+       } else
+               tasklet_schedule(&host->finish_tasklet);
+}
+
+static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
+{
+       int flags;
+       u32 mask;
+       unsigned long timeout;
+
+       WARN_ON(host->cmd);
+
+       DBG("Sending cmd (%x)\n", cmd->opcode);
+
+       /* Wait max 10 ms */
+       timeout = 10;
+
+       mask = SDHCI_CMD_INHIBIT;
+       if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
+               mask |= SDHCI_DATA_INHIBIT;
+
+       /* We shouldn't wait for data inihibit for stop commands, even
+          though they might use busy signaling */
+       if (host->mrq->data && (cmd == host->mrq->data->stop))
+               mask &= ~SDHCI_DATA_INHIBIT;
+
+       while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
+               if (timeout == 0) {
+                       printk(KERN_ERR "%s: Controller never released "
+                               "inhibit bit(s).\n", mmc_hostname(host->mmc));
+                       sdhci_dumpregs(host);
+                       cmd->error = MMC_ERR_FAILED;
+                       tasklet_schedule(&host->finish_tasklet);
+                       return;
+               }
+               timeout--;
+               mdelay(1);
+       }
+
+       mod_timer(&host->timer, jiffies + 10 * HZ);
+
+       host->cmd = cmd;
+
+       sdhci_prepare_data(host, cmd->data);
+
+       writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
+
+       sdhci_set_transfer_mode(host, cmd->data);
+
+       if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
+               printk(KERN_ERR "%s: Unsupported response type!\n",
+                       mmc_hostname(host->mmc));
+               cmd->error = MMC_ERR_INVALID;
+               tasklet_schedule(&host->finish_tasklet);
+               return;
+       }
+
+       if (!(cmd->flags & MMC_RSP_PRESENT))
+               flags = SDHCI_CMD_RESP_NONE;
+       else if (cmd->flags & MMC_RSP_136)
+               flags = SDHCI_CMD_RESP_LONG;
+       else if (cmd->flags & MMC_RSP_BUSY)
+               flags = SDHCI_CMD_RESP_SHORT_BUSY;
+       else
+               flags = SDHCI_CMD_RESP_SHORT;
+
+       if (cmd->flags & MMC_RSP_CRC)
+               flags |= SDHCI_CMD_CRC;
+       if (cmd->flags & MMC_RSP_OPCODE)
+               flags |= SDHCI_CMD_INDEX;
+       if (cmd->data)
+               flags |= SDHCI_CMD_DATA;
+
+       writew(SDHCI_MAKE_CMD(cmd->opcode, flags),
+               host->ioaddr + SDHCI_COMMAND);
+}
+
+static void sdhci_finish_command(struct sdhci_host *host)
+{
+       int i;
+
+       BUG_ON(host->cmd == NULL);
+
+       if (host->cmd->flags & MMC_RSP_PRESENT) {
+               if (host->cmd->flags & MMC_RSP_136) {
+                       /* CRC is stripped so we need to do some shifting. */
+                       for (i = 0;i < 4;i++) {
+                               host->cmd->resp[i] = readl(host->ioaddr +
+                                       SDHCI_RESPONSE + (3-i)*4) << 8;
+                               if (i != 3)
+                                       host->cmd->resp[i] |=
+                                               readb(host->ioaddr +
+                                               SDHCI_RESPONSE + (3-i)*4-1);
+                       }
+               } else {
+                       host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
+               }
+       }
+
+       host->cmd->error = MMC_ERR_NONE;
+
+       DBG("Ending cmd (%x)\n", host->cmd->opcode);
+
+       if (host->cmd->data)
+               host->data = host->cmd->data;
+       else
+               tasklet_schedule(&host->finish_tasklet);
+
+       host->cmd = NULL;
+}
+
+static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+       int div;
+       u16 clk;
+       unsigned long timeout;
+
+       if (clock == host->clock)
+               return;
+
+       writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
+
+       if (clock == 0)
+               goto out;
+
+       for (div = 1;div < 256;div *= 2) {
+               if ((host->max_clk / div) <= clock)
+                       break;
+       }
+       div >>= 1;
+
+       clk = div << SDHCI_DIVIDER_SHIFT;
+       clk |= SDHCI_CLOCK_INT_EN;
+       writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
+
+       /* Wait max 10 ms */
+       timeout = 10;
+       while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
+               & SDHCI_CLOCK_INT_STABLE)) {
+               if (timeout == 0) {
+                       printk(KERN_ERR "%s: Internal clock never "
+                               "stabilised.\n", mmc_hostname(host->mmc));
+                       sdhci_dumpregs(host);
+                       return;
+               }
+               timeout--;
+               mdelay(1);
+       }
+
+       clk |= SDHCI_CLOCK_CARD_EN;
+       writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
+
+out:
+       host->clock = clock;
+}
+
+static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
+{
+       u8 pwr;
+
+       if (host->power == power)
+               return;
+
+       if (power == (unsigned short)-1) {
+               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
+               goto out;
+       }
+
+       /*
+        * Spec says that we should clear the power reg before setting
+        * a new value. Some controllers don't seem to like this though.
+        */
+       if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
+
+       pwr = SDHCI_POWER_ON;
+
+       switch (1 << power) {
+       case MMC_VDD_165_195:
+               pwr |= SDHCI_POWER_180;
+               break;
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
+               pwr |= SDHCI_POWER_300;
+               break;
+       case MMC_VDD_32_33:
+       case MMC_VDD_33_34:
+               pwr |= SDHCI_POWER_330;
+               break;
+       default:
+               BUG();
+       }
+
+       writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
+
+out:
+       host->power = power;
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * MMC callbacks                                                             *
+ *                                                                           *
+\*****************************************************************************/
+
+static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct sdhci_host *host;
+       unsigned long flags;
+
+       host = mmc_priv(mmc);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       WARN_ON(host->mrq != NULL);
+
+       sdhci_activate_led(host);
+
+       host->mrq = mrq;
+
+       if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+               host->mrq->cmd->error = MMC_ERR_TIMEOUT;
+               tasklet_schedule(&host->finish_tasklet);
+       } else
+               sdhci_send_command(host, mrq->cmd);
+
+       mmiowb();
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct sdhci_host *host;
+       unsigned long flags;
+       u8 ctrl;
+
+       host = mmc_priv(mmc);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       /*
+        * Reset the chip on each power off.
+        * Should clear out any weird states.
+        */
+       if (ios->power_mode == MMC_POWER_OFF) {
+               writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
+               sdhci_init(host);
+       }
+
+       sdhci_set_clock(host, ios->clock);
+
+       if (ios->power_mode == MMC_POWER_OFF)
+               sdhci_set_power(host, -1);
+       else
+               sdhci_set_power(host, ios->vdd);
+
+       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+
+       if (ios->bus_width == MMC_BUS_WIDTH_4)
+               ctrl |= SDHCI_CTRL_4BITBUS;
+       else
+               ctrl &= ~SDHCI_CTRL_4BITBUS;
+
+       if (ios->timing == MMC_TIMING_SD_HS)
+               ctrl |= SDHCI_CTRL_HISPD;
+       else
+               ctrl &= ~SDHCI_CTRL_HISPD;
+
+       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
+       mmiowb();
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static int sdhci_get_ro(struct mmc_host *mmc)
+{
+       struct sdhci_host *host;
+       unsigned long flags;
+       int present;
+
+       host = mmc_priv(mmc);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       return !(present & SDHCI_WRITE_PROTECT);
+}
+
+static const struct mmc_host_ops sdhci_ops = {
+       .request        = sdhci_request,
+       .set_ios        = sdhci_set_ios,
+       .get_ro         = sdhci_get_ro,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Tasklets                                                                  *
+ *                                                                           *
+\*****************************************************************************/
+
+static void sdhci_tasklet_card(unsigned long param)
+{
+       struct sdhci_host *host;
+       unsigned long flags;
+
+       host = (struct sdhci_host*)param;
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+               if (host->mrq) {
+                       printk(KERN_ERR "%s: Card removed during transfer!\n",
+                               mmc_hostname(host->mmc));
+                       printk(KERN_ERR "%s: Resetting controller.\n",
+                               mmc_hostname(host->mmc));
+
+                       sdhci_reset(host, SDHCI_RESET_CMD);
+                       sdhci_reset(host, SDHCI_RESET_DATA);
+
+                       host->mrq->cmd->error = MMC_ERR_FAILED;
+                       tasklet_schedule(&host->finish_tasklet);
+               }
+       }
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+}
+
+static void sdhci_tasklet_finish(unsigned long param)
+{
+       struct sdhci_host *host;
+       unsigned long flags;
+       struct mmc_request *mrq;
+
+       host = (struct sdhci_host*)param;
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       del_timer(&host->timer);
+
+       mrq = host->mrq;
+
+       DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode);
+
+       /*
+        * The controller needs a reset of internal state machines
+        * upon error conditions.
+        */
+       if ((mrq->cmd->error != MMC_ERR_NONE) ||
+               (mrq->data && ((mrq->data->error != MMC_ERR_NONE) ||
+               (mrq->data->stop && (mrq->data->stop->error != MMC_ERR_NONE))))) {
+
+               /* Some controllers need this kick or reset won't work here */
+               if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
+                       unsigned int clock;
+
+                       /* This is to force an update */
+                       clock = host->clock;
+                       host->clock = 0;
+                       sdhci_set_clock(host, clock);
+               }
+
+               /* Spec says we should do both at the same time, but Ricoh
+                  controllers do not like that. */
+               sdhci_reset(host, SDHCI_RESET_CMD);
+               sdhci_reset(host, SDHCI_RESET_DATA);
+       }
+
+       host->mrq = NULL;
+       host->cmd = NULL;
+       host->data = NULL;
+
+       sdhci_deactivate_led(host);
+
+       mmiowb();
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       mmc_request_done(host->mmc, mrq);
+}
+
+static void sdhci_timeout_timer(unsigned long data)
+{
+       struct sdhci_host *host;
+       unsigned long flags;
+
+       host = (struct sdhci_host*)data;
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       if (host->mrq) {
+               printk(KERN_ERR "%s: Timeout waiting for hardware "
+                       "interrupt.\n", mmc_hostname(host->mmc));
+               sdhci_dumpregs(host);
+
+               if (host->data) {
+                       host->data->error = MMC_ERR_TIMEOUT;
+                       sdhci_finish_data(host);
+               } else {
+                       if (host->cmd)
+                               host->cmd->error = MMC_ERR_TIMEOUT;
+                       else
+                               host->mrq->cmd->error = MMC_ERR_TIMEOUT;
+
+                       tasklet_schedule(&host->finish_tasklet);
+               }
+       }
+
+       mmiowb();
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Interrupt handling                                                        *
+ *                                                                           *
+\*****************************************************************************/
+
+static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
+{
+       BUG_ON(intmask == 0);
+
+       if (!host->cmd) {
+               printk(KERN_ERR "%s: Got command interrupt even though no "
+                       "command operation was in progress.\n",
+                       mmc_hostname(host->mmc));
+               sdhci_dumpregs(host);
+               return;
+       }
+
+       if (intmask & SDHCI_INT_RESPONSE)
+               sdhci_finish_command(host);
+       else {
+               if (intmask & SDHCI_INT_TIMEOUT)
+                       host->cmd->error = MMC_ERR_TIMEOUT;
+               else if (intmask & SDHCI_INT_CRC)
+                       host->cmd->error = MMC_ERR_BADCRC;
+               else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
+                       host->cmd->error = MMC_ERR_FAILED;
+               else
+                       host->cmd->error = MMC_ERR_INVALID;
+
+               tasklet_schedule(&host->finish_tasklet);
+       }
+}
+
+static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
+{
+       BUG_ON(intmask == 0);
+
+       if (!host->data) {
+               /*
+                * A data end interrupt is sent together with the response
+                * for the stop command.
+                */
+               if (intmask & SDHCI_INT_DATA_END)
+                       return;
+
+               printk(KERN_ERR "%s: Got data interrupt even though no "
+                       "data operation was in progress.\n",
+                       mmc_hostname(host->mmc));
+               sdhci_dumpregs(host);
+
+               return;
+       }
+
+       if (intmask & SDHCI_INT_DATA_TIMEOUT)
+               host->data->error = MMC_ERR_TIMEOUT;
+       else if (intmask & SDHCI_INT_DATA_CRC)
+               host->data->error = MMC_ERR_BADCRC;
+       else if (intmask & SDHCI_INT_DATA_END_BIT)
+               host->data->error = MMC_ERR_FAILED;
+
+       if (host->data->error != MMC_ERR_NONE)
+               sdhci_finish_data(host);
+       else {
+               if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
+                       sdhci_transfer_pio(host);
+
+               if (intmask & SDHCI_INT_DATA_END)
+                       sdhci_finish_data(host);
+       }
+}
+
+static irqreturn_t sdhci_irq(int irq, void *dev_id)
+{
+       irqreturn_t result;
+       struct sdhci_host* host = dev_id;
+       u32 intmask;
+
+       spin_lock(&host->lock);
+
+       intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
+
+       if (!intmask || intmask == 0xffffffff) {
+               result = IRQ_NONE;
+               goto out;
+       }
+
+       DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
+
+       if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+               writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
+                       host->ioaddr + SDHCI_INT_STATUS);
+               tasklet_schedule(&host->card_tasklet);
+       }
+
+       intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
+
+       if (intmask & SDHCI_INT_CMD_MASK) {
+               writel(intmask & SDHCI_INT_CMD_MASK,
+                       host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
+       }
+
+       if (intmask & SDHCI_INT_DATA_MASK) {
+               writel(intmask & SDHCI_INT_DATA_MASK,
+                       host->ioaddr + SDHCI_INT_STATUS);
+               sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
+       }
+
+       intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
+
+       if (intmask & SDHCI_INT_BUS_POWER) {
+               printk(KERN_ERR "%s: Card is consuming too much power!\n",
+                       mmc_hostname(host->mmc));
+               writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
+       }
+
+       intmask &= SDHCI_INT_BUS_POWER;
+
+       if (intmask) {
+               printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
+                       mmc_hostname(host->mmc), intmask);
+               sdhci_dumpregs(host);
+
+               writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
+       }
+
+       result = IRQ_HANDLED;
+
+       mmiowb();
+out:
+       spin_unlock(&host->lock);
+
+       return result;
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Suspend/resume                                                            *
+ *                                                                           *
+\*****************************************************************************/
+
+#ifdef CONFIG_PM
+
+static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state)
+{
+       struct sdhci_chip *chip;
+       int i, ret;
+
+       chip = pci_get_drvdata(pdev);
+       if (!chip)
+               return 0;
+
+       DBG("Suspending...\n");
+
+       for (i = 0;i < chip->num_slots;i++) {
+               if (!chip->hosts[i])
+                       continue;
+               ret = mmc_suspend_host(chip->hosts[i]->mmc, state);
+               if (ret) {
+                       for (i--;i >= 0;i--)
+                               mmc_resume_host(chip->hosts[i]->mmc);
+                       return ret;
+               }
+       }
+
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+
+       for (i = 0;i < chip->num_slots;i++) {
+               if (!chip->hosts[i])
+                       continue;
+               free_irq(chip->hosts[i]->irq, chip->hosts[i]);
+       }
+
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int sdhci_resume (struct pci_dev *pdev)
+{
+       struct sdhci_chip *chip;
+       int i, ret;
+
+       chip = pci_get_drvdata(pdev);
+       if (!chip)
+               return 0;
+
+       DBG("Resuming...\n");
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       for (i = 0;i < chip->num_slots;i++) {
+               if (!chip->hosts[i])
+                       continue;
+               if (chip->hosts[i]->flags & SDHCI_USE_DMA)
+                       pci_set_master(pdev);
+               ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
+                       IRQF_SHARED, chip->hosts[i]->slot_descr,
+                       chip->hosts[i]);
+               if (ret)
+                       return ret;
+               sdhci_init(chip->hosts[i]);
+               mmiowb();
+               ret = mmc_resume_host(chip->hosts[i]->mmc);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define sdhci_suspend NULL
+#define sdhci_resume NULL
+
+#endif /* CONFIG_PM */
+
+/*****************************************************************************\
+ *                                                                           *
+ * Device probing/removal                                                    *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+{
+       int ret;
+       unsigned int version;
+       struct sdhci_chip *chip;
+       struct mmc_host *mmc;
+       struct sdhci_host *host;
+
+       u8 first_bar;
+       unsigned int caps;
+
+       chip = pci_get_drvdata(pdev);
+       BUG_ON(!chip);
+
+       ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
+       if (ret)
+               return ret;
+
+       first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
+
+       if (first_bar > 5) {
+               printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n");
+               return -ENODEV;
+       }
+
+       if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) {
+               printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n");
+               return -ENODEV;
+       }
+
+       if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
+               printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. "
+                       "You may experience problems.\n");
+       }
+
+       if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
+               printk(KERN_ERR DRIVER_NAME ": Vendor specific interface. Aborting.\n");
+               return -ENODEV;
+       }
+
+       if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) {
+               printk(KERN_ERR DRIVER_NAME ": Unknown interface. Aborting.\n");
+               return -ENODEV;
+       }
+
+       mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev);
+       if (!mmc)
+               return -ENOMEM;
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       host->chip = chip;
+       chip->hosts[slot] = host;
+
+       host->bar = first_bar + slot;
+
+       host->addr = pci_resource_start(pdev, host->bar);
+       host->irq = pdev->irq;
+
+       DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
+
+       snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
+
+       ret = pci_request_region(pdev, host->bar, host->slot_descr);
+       if (ret)
+               goto free;
+
+       host->ioaddr = ioremap_nocache(host->addr,
+               pci_resource_len(pdev, host->bar));
+       if (!host->ioaddr) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       sdhci_reset(host, SDHCI_RESET_ALL);
+
+       version = readw(host->ioaddr + SDHCI_HOST_VERSION);
+       version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
+       if (version != 0) {
+               printk(KERN_ERR "%s: Unknown controller version (%d). "
+                       "You may experience problems.\n", host->slot_descr,
+                       version);
+       }
+
+       caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+
+       if (debug_nodma)
+               DBG("DMA forced off\n");
+       else if (debug_forcedma) {
+               DBG("DMA forced on\n");
+               host->flags |= SDHCI_USE_DMA;
+       } else if (chip->quirks & SDHCI_QUIRK_FORCE_DMA)
+               host->flags |= SDHCI_USE_DMA;
+       else if ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA)
+               DBG("Controller doesn't have DMA interface\n");
+       else if (!(caps & SDHCI_CAN_DO_DMA))
+               DBG("Controller doesn't have DMA capability\n");
+       else
+               host->flags |= SDHCI_USE_DMA;
+
+       if (host->flags & SDHCI_USE_DMA) {
+               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+                       printk(KERN_WARNING "%s: No suitable DMA available. "
+                               "Falling back to PIO.\n", host->slot_descr);
+                       host->flags &= ~SDHCI_USE_DMA;
+               }
+       }
+
+       if (host->flags & SDHCI_USE_DMA)
+               pci_set_master(pdev);
+       else /* XXX: Hack to get MMC layer to avoid highmem */
+               pdev->dma_mask = 0;
+
+       host->max_clk =
+               (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+       if (host->max_clk == 0) {
+               printk(KERN_ERR "%s: Hardware doesn't specify base clock "
+                       "frequency.\n", host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+       host->max_clk *= 1000000;
+
+       host->timeout_clk =
+               (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
+       if (host->timeout_clk == 0) {
+               printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
+                       "frequency.\n", host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+       if (caps & SDHCI_TIMEOUT_CLK_UNIT)
+               host->timeout_clk *= 1000;
+
+       /*
+        * Set host parameters.
+        */
+       mmc->ops = &sdhci_ops;
+       mmc->f_min = host->max_clk / 256;
+       mmc->f_max = host->max_clk;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
+
+       if (caps & SDHCI_CAN_DO_HISPD)
+               mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+
+       mmc->ocr_avail = 0;
+       if (caps & SDHCI_CAN_VDD_330)
+               mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
+       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_165_195;
+
+       if (mmc->ocr_avail == 0) {
+               printk(KERN_ERR "%s: Hardware doesn't report any "
+                       "support voltages.\n", host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+
+       spin_lock_init(&host->lock);
+
+       /*
+        * Maximum number of segments. Hardware cannot do scatter lists.
+        */
+       if (host->flags & SDHCI_USE_DMA)
+               mmc->max_hw_segs = 1;
+       else
+               mmc->max_hw_segs = 16;
+       mmc->max_phys_segs = 16;
+
+       /*
+        * Maximum number of sectors in one transfer. Limited by DMA boundary
+        * size (512KiB).
+        */
+       mmc->max_req_size = 524288;
+
+       /*
+        * Maximum segment size. Could be one segment with the maximum number
+        * of bytes.
+        */
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Maximum block size. This varies from controller to controller and
+        * is specified in the capabilities register.
+        */
+       mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+       if (mmc->max_blk_size >= 3) {
+               printk(KERN_ERR "%s: Invalid maximum block size.\n",
+                       host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+       mmc->max_blk_size = 512 << mmc->max_blk_size;
+
+       /*
+        * Maximum block count.
+        */
+       mmc->max_blk_count = 65535;
+
+       /*
+        * Init tasklets.
+        */
+       tasklet_init(&host->card_tasklet,
+               sdhci_tasklet_card, (unsigned long)host);
+       tasklet_init(&host->finish_tasklet,
+               sdhci_tasklet_finish, (unsigned long)host);
+
+       setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
+
+       ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
+               host->slot_descr, host);
+       if (ret)
+               goto untasklet;
+
+       sdhci_init(host);
+
+#ifdef CONFIG_MMC_DEBUG
+       sdhci_dumpregs(host);
+#endif
+
+       mmiowb();
+
+       mmc_add_host(mmc);
+
+       printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
+               host->addr, host->irq,
+               (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
+
+       return 0;
+
+untasklet:
+       tasklet_kill(&host->card_tasklet);
+       tasklet_kill(&host->finish_tasklet);
+unmap:
+       iounmap(host->ioaddr);
+release:
+       pci_release_region(pdev, host->bar);
+free:
+       mmc_free_host(mmc);
+
+       return ret;
+}
+
+static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
+{
+       struct sdhci_chip *chip;
+       struct mmc_host *mmc;
+       struct sdhci_host *host;
+
+       chip = pci_get_drvdata(pdev);
+       host = chip->hosts[slot];
+       mmc = host->mmc;
+
+       chip->hosts[slot] = NULL;
+
+       mmc_remove_host(mmc);
+
+       sdhci_reset(host, SDHCI_RESET_ALL);
+
+       free_irq(host->irq, host);
+
+       del_timer_sync(&host->timer);
+
+       tasklet_kill(&host->card_tasklet);
+       tasklet_kill(&host->finish_tasklet);
+
+       iounmap(host->ioaddr);
+
+       pci_release_region(pdev, host->bar);
+
+       mmc_free_host(mmc);
+}
+
+static int __devinit sdhci_probe(struct pci_dev *pdev,
+       const struct pci_device_id *ent)
+{
+       int ret, i;
+       u8 slots, rev;
+       struct sdhci_chip *chip;
+
+       BUG_ON(pdev == NULL);
+       BUG_ON(ent == NULL);
+
+       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
+
+       printk(KERN_INFO DRIVER_NAME
+               ": SDHCI controller found at %s [%04x:%04x] (rev %x)\n",
+               pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
+               (int)rev);
+
+       ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
+       if (ret)
+               return ret;
+
+       slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
+       DBG("found %d slot(s)\n", slots);
+       if (slots == 0)
+               return -ENODEV;
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       chip = kzalloc(sizeof(struct sdhci_chip) +
+               sizeof(struct sdhci_host*) * slots, GFP_KERNEL);
+       if (!chip) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       chip->pdev = pdev;
+       chip->quirks = ent->driver_data;
+
+       if (debug_quirks)
+               chip->quirks = debug_quirks;
+
+       chip->num_slots = slots;
+       pci_set_drvdata(pdev, chip);
+
+       for (i = 0;i < slots;i++) {
+               ret = sdhci_probe_slot(pdev, i);
+               if (ret) {
+                       for (i--;i >= 0;i--)
+                               sdhci_remove_slot(pdev, i);
+                       goto free;
+               }
+       }
+
+       return 0;
+
+free:
+       pci_set_drvdata(pdev, NULL);
+       kfree(chip);
+
+err:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void __devexit sdhci_remove(struct pci_dev *pdev)
+{
+       int i;
+       struct sdhci_chip *chip;
+
+       chip = pci_get_drvdata(pdev);
+
+       if (chip) {
+               for (i = 0;i < chip->num_slots;i++)
+                       sdhci_remove_slot(pdev, i);
+
+               pci_set_drvdata(pdev, NULL);
+
+               kfree(chip);
+       }
+
+       pci_disable_device(pdev);
+}
+
+static struct pci_driver sdhci_driver = {
+       .name =         DRIVER_NAME,
+       .id_table =     pci_ids,
+       .probe =        sdhci_probe,
+       .remove =       __devexit_p(sdhci_remove),
+       .suspend =      sdhci_suspend,
+       .resume =       sdhci_resume,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Driver init/exit                                                          *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __init sdhci_drv_init(void)
+{
+       printk(KERN_INFO DRIVER_NAME
+               ": Secure Digital Host Controller Interface driver\n");
+       printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+
+       return pci_register_driver(&sdhci_driver);
+}
+
+static void __exit sdhci_drv_exit(void)
+{
+       DBG("Exiting\n");
+
+       pci_unregister_driver(&sdhci_driver);
+}
+
+module_init(sdhci_drv_init);
+module_exit(sdhci_drv_exit);
+
+module_param(debug_nodma, uint, 0444);
+module_param(debug_forcedma, uint, 0444);
+module_param(debug_quirks, uint, 0444);
+
+MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
+MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM_DESC(debug_nodma, "Forcefully disable DMA transfers. (default 0)");
+MODULE_PARM_DESC(debug_forcedma, "Forcefully enable DMA transfers. (default 0)");
+MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
new file mode 100644 (file)
index 0000000..7400f4b
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *  linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
+ *
+ *  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.
+ */
+
+/*
+ * PCI registers
+ */
+
+#define PCI_SDHCI_IFPIO                        0x00
+#define PCI_SDHCI_IFDMA                        0x01
+#define PCI_SDHCI_IFVENDOR             0x02
+
+#define PCI_SLOT_INFO                  0x40    /* 8 bits */
+#define  PCI_SLOT_INFO_SLOTS(x)                ((x >> 4) & 7)
+#define  PCI_SLOT_INFO_FIRST_BAR_MASK  0x07
+
+/*
+ * Controller registers
+ */
+
+#define SDHCI_DMA_ADDRESS      0x00
+
+#define SDHCI_BLOCK_SIZE       0x04
+#define  SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
+
+#define SDHCI_BLOCK_COUNT      0x06
+
+#define SDHCI_ARGUMENT         0x08
+
+#define SDHCI_TRANSFER_MODE    0x0C
+#define  SDHCI_TRNS_DMA                0x01
+#define  SDHCI_TRNS_BLK_CNT_EN 0x02
+#define  SDHCI_TRNS_ACMD12     0x04
+#define  SDHCI_TRNS_READ       0x10
+#define  SDHCI_TRNS_MULTI      0x20
+
+#define SDHCI_COMMAND          0x0E
+#define  SDHCI_CMD_RESP_MASK   0x03
+#define  SDHCI_CMD_CRC         0x08
+#define  SDHCI_CMD_INDEX       0x10
+#define  SDHCI_CMD_DATA                0x20
+
+#define  SDHCI_CMD_RESP_NONE   0x00
+#define  SDHCI_CMD_RESP_LONG   0x01
+#define  SDHCI_CMD_RESP_SHORT  0x02
+#define  SDHCI_CMD_RESP_SHORT_BUSY 0x03
+
+#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
+
+#define SDHCI_RESPONSE         0x10
+
+#define SDHCI_BUFFER           0x20
+
+#define SDHCI_PRESENT_STATE    0x24
+#define  SDHCI_CMD_INHIBIT     0x00000001
+#define  SDHCI_DATA_INHIBIT    0x00000002
+#define  SDHCI_DOING_WRITE     0x00000100
+#define  SDHCI_DOING_READ      0x00000200
+#define  SDHCI_SPACE_AVAILABLE 0x00000400
+#define  SDHCI_DATA_AVAILABLE  0x00000800
+#define  SDHCI_CARD_PRESENT    0x00010000
+#define  SDHCI_WRITE_PROTECT   0x00080000
+
+#define SDHCI_HOST_CONTROL     0x28
+#define  SDHCI_CTRL_LED                0x01
+#define  SDHCI_CTRL_4BITBUS    0x02
+#define  SDHCI_CTRL_HISPD      0x04
+
+#define SDHCI_POWER_CONTROL    0x29
+#define  SDHCI_POWER_ON                0x01
+#define  SDHCI_POWER_180       0x0A
+#define  SDHCI_POWER_300       0x0C
+#define  SDHCI_POWER_330       0x0E
+
+#define SDHCI_BLOCK_GAP_CONTROL        0x2A
+
+#define SDHCI_WALK_UP_CONTROL  0x2B
+
+#define SDHCI_CLOCK_CONTROL    0x2C
+#define  SDHCI_DIVIDER_SHIFT   8
+#define  SDHCI_CLOCK_CARD_EN   0x0004
+#define  SDHCI_CLOCK_INT_STABLE        0x0002
+#define  SDHCI_CLOCK_INT_EN    0x0001
+
+#define SDHCI_TIMEOUT_CONTROL  0x2E
+
+#define SDHCI_SOFTWARE_RESET   0x2F
+#define  SDHCI_RESET_ALL       0x01
+#define  SDHCI_RESET_CMD       0x02
+#define  SDHCI_RESET_DATA      0x04
+
+#define SDHCI_INT_STATUS       0x30
+#define SDHCI_INT_ENABLE       0x34
+#define SDHCI_SIGNAL_ENABLE    0x38
+#define  SDHCI_INT_RESPONSE    0x00000001
+#define  SDHCI_INT_DATA_END    0x00000002
+#define  SDHCI_INT_DMA_END     0x00000008
+#define  SDHCI_INT_SPACE_AVAIL 0x00000010
+#define  SDHCI_INT_DATA_AVAIL  0x00000020
+#define  SDHCI_INT_CARD_INSERT 0x00000040
+#define  SDHCI_INT_CARD_REMOVE 0x00000080
+#define  SDHCI_INT_CARD_INT    0x00000100
+#define  SDHCI_INT_TIMEOUT     0x00010000
+#define  SDHCI_INT_CRC         0x00020000
+#define  SDHCI_INT_END_BIT     0x00040000
+#define  SDHCI_INT_INDEX       0x00080000
+#define  SDHCI_INT_DATA_TIMEOUT        0x00100000
+#define  SDHCI_INT_DATA_CRC    0x00200000
+#define  SDHCI_INT_DATA_END_BIT        0x00400000
+#define  SDHCI_INT_BUS_POWER   0x00800000
+#define  SDHCI_INT_ACMD12ERR   0x01000000
+
+#define  SDHCI_INT_NORMAL_MASK 0x00007FFF
+#define  SDHCI_INT_ERROR_MASK  0xFFFF8000
+
+#define  SDHCI_INT_CMD_MASK    (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
+               SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
+#define  SDHCI_INT_DATA_MASK   (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
+               SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
+               SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
+               SDHCI_INT_DATA_END_BIT)
+
+#define SDHCI_ACMD12_ERR       0x3C
+
+/* 3E-3F reserved */
+
+#define SDHCI_CAPABILITIES     0x40
+#define  SDHCI_TIMEOUT_CLK_MASK        0x0000003F
+#define  SDHCI_TIMEOUT_CLK_SHIFT 0
+#define  SDHCI_TIMEOUT_CLK_UNIT        0x00000080
+#define  SDHCI_CLOCK_BASE_MASK 0x00003F00
+#define  SDHCI_CLOCK_BASE_SHIFT        8
+#define  SDHCI_MAX_BLOCK_MASK  0x00030000
+#define  SDHCI_MAX_BLOCK_SHIFT  16
+#define  SDHCI_CAN_DO_HISPD    0x00200000
+#define  SDHCI_CAN_DO_DMA      0x00400000
+#define  SDHCI_CAN_VDD_330     0x01000000
+#define  SDHCI_CAN_VDD_300     0x02000000
+#define  SDHCI_CAN_VDD_180     0x04000000
+
+/* 44-47 reserved for more caps */
+
+#define SDHCI_MAX_CURRENT      0x48
+
+/* 4C-4F reserved for more max current */
+
+/* 50-FB reserved */
+
+#define SDHCI_SLOT_INT_STATUS  0xFC
+
+#define SDHCI_HOST_VERSION     0xFE
+#define  SDHCI_VENDOR_VER_MASK 0xFF00
+#define  SDHCI_VENDOR_VER_SHIFT        8
+#define  SDHCI_SPEC_VER_MASK   0x00FF
+#define  SDHCI_SPEC_VER_SHIFT  0
+
+struct sdhci_chip;
+
+struct sdhci_host {
+       struct sdhci_chip       *chip;
+       struct mmc_host         *mmc;           /* MMC structure */
+
+       spinlock_t              lock;           /* Mutex */
+
+       int                     flags;          /* Host attributes */
+#define SDHCI_USE_DMA          (1<<0)
+
+       unsigned int            max_clk;        /* Max possible freq (MHz) */
+       unsigned int            timeout_clk;    /* Timeout freq (KHz) */
+
+       unsigned int            clock;          /* Current clock (MHz) */
+       unsigned short          power;          /* Current voltage */
+
+       struct mmc_request      *mrq;           /* Current request */
+       struct mmc_command      *cmd;           /* Current command */
+       struct mmc_data         *data;          /* Current data request */
+
+       struct scatterlist      *cur_sg;        /* We're working on this */
+       int                     num_sg;         /* Entries left */
+       int                     offset;         /* Offset into current sg */
+       int                     remain;         /* Bytes left in current */
+
+       char                    slot_descr[20]; /* Name for reservations */
+
+       int                     irq;            /* Device IRQ */
+       int                     bar;            /* PCI BAR index */
+       unsigned long           addr;           /* Bus address */
+       void __iomem *          ioaddr;         /* Mapped address */
+
+       struct tasklet_struct   card_tasklet;   /* Tasklet structures */
+       struct tasklet_struct   finish_tasklet;
+
+       struct timer_list       timer;          /* Timer for timeouts */
+};
+
+struct sdhci_chip {
+       struct pci_dev          *pdev;
+
+       unsigned long           quirks;
+
+       int                     num_slots;      /* Slots on controller */
+       struct sdhci_host       *hosts[0];      /* Pointers to hosts */
+};
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);
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
new file mode 100644 (file)
index 0000000..867ca6a
--- /dev/null
@@ -0,0 +1,2061 @@
+/*
+ *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
+ *
+ *  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
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ *
+ * Warning!
+ *
+ * Changes to the FIFO system should be done with extreme care since
+ * the hardware is full of bugs related to the FIFO. Known issues are:
+ *
+ * - FIFO size field in FSR is always zero.
+ *
+ * - FIFO interrupts tend not to work as they should. Interrupts are
+ *   triggered only for full/empty events, not for threshold values.
+ *
+ * - On APIC systems the FIFO empty interrupt is sometimes lost.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/pnp.h>
+#include <linux/highmem.h>
+#include <linux/mmc/host.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/scatterlist.h>
+
+#include "wbsd.h"
+
+#define DRIVER_NAME "wbsd"
+
+#define DBG(x...) \
+       pr_debug(DRIVER_NAME ": " x)
+#define DBGF(f, x...) \
+       pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x)
+
+/*
+ * Device resources
+ */
+
+#ifdef CONFIG_PNP
+
+static const struct pnp_device_id pnp_dev_table[] = {
+       { "WEC0517", 0 },
+       { "WEC0518", 0 },
+       { "", 0 },
+};
+
+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+
+#endif /* CONFIG_PNP */
+
+static const int config_ports[] = { 0x2E, 0x4E };
+static const int unlock_codes[] = { 0x83, 0x87 };
+
+static const int valid_ids[] = {
+       0x7112,
+       };
+
+#ifdef CONFIG_PNP
+static unsigned int nopnp = 0;
+#else
+static const unsigned int nopnp = 1;
+#endif
+static unsigned int io = 0x248;
+static unsigned int irq = 6;
+static int dma = 2;
+
+/*
+ * Basic functions
+ */
+
+static inline void wbsd_unlock_config(struct wbsd_host *host)
+{
+       BUG_ON(host->config == 0);
+
+       outb(host->unlock_code, host->config);
+       outb(host->unlock_code, host->config);
+}
+
+static inline void wbsd_lock_config(struct wbsd_host *host)
+{
+       BUG_ON(host->config == 0);
+
+       outb(LOCK_CODE, host->config);
+}
+
+static inline void wbsd_write_config(struct wbsd_host *host, u8 reg, u8 value)
+{
+       BUG_ON(host->config == 0);
+
+       outb(reg, host->config);
+       outb(value, host->config + 1);
+}
+
+static inline u8 wbsd_read_config(struct wbsd_host *host, u8 reg)
+{
+       BUG_ON(host->config == 0);
+
+       outb(reg, host->config);
+       return inb(host->config + 1);
+}
+
+static inline void wbsd_write_index(struct wbsd_host *host, u8 index, u8 value)
+{
+       outb(index, host->base + WBSD_IDXR);
+       outb(value, host->base + WBSD_DATAR);
+}
+
+static inline u8 wbsd_read_index(struct wbsd_host *host, u8 index)
+{
+       outb(index, host->base + WBSD_IDXR);
+       return inb(host->base + WBSD_DATAR);
+}
+
+/*
+ * Common routines
+ */
+
+static void wbsd_init_device(struct wbsd_host *host)
+{
+       u8 setup, ier;
+
+       /*
+        * Reset chip (SD/MMC part) and fifo.
+        */
+       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
+       setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+
+       /*
+        * Set DAT3 to input
+        */
+       setup &= ~WBSD_DAT3_H;
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+       host->flags &= ~WBSD_FIGNORE_DETECT;
+
+       /*
+        * Read back default clock.
+        */
+       host->clk = wbsd_read_index(host, WBSD_IDX_CLK);
+
+       /*
+        * Power down port.
+        */
+       outb(WBSD_POWER_N, host->base + WBSD_CSR);
+
+       /*
+        * Set maximum timeout.
+        */
+       wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
+
+       /*
+        * Test for card presence
+        */
+       if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)
+               host->flags |= WBSD_FCARD_PRESENT;
+       else
+               host->flags &= ~WBSD_FCARD_PRESENT;
+
+       /*
+        * Enable interesting interrupts.
+        */
+       ier = 0;
+       ier |= WBSD_EINT_CARD;
+       ier |= WBSD_EINT_FIFO_THRE;
+       ier |= WBSD_EINT_CRC;
+       ier |= WBSD_EINT_TIMEOUT;
+       ier |= WBSD_EINT_TC;
+
+       outb(ier, host->base + WBSD_EIR);
+
+       /*
+        * Clear interrupts.
+        */
+       inb(host->base + WBSD_ISR);
+}
+
+static void wbsd_reset(struct wbsd_host *host)
+{
+       u8 setup;
+
+       printk(KERN_ERR "%s: Resetting chip\n", mmc_hostname(host->mmc));
+
+       /*
+        * Soft reset of chip (SD/MMC part).
+        */
+       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
+       setup |= WBSD_SOFT_RESET;
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+}
+
+static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq)
+{
+       unsigned long dmaflags;
+
+       DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
+
+       if (host->dma >= 0) {
+               /*
+                * Release ISA DMA controller.
+                */
+               dmaflags = claim_dma_lock();
+               disable_dma(host->dma);
+               clear_dma_ff(host->dma);
+               release_dma_lock(dmaflags);
+
+               /*
+                * Disable DMA on host.
+                */
+               wbsd_write_index(host, WBSD_IDX_DMA, 0);
+       }
+
+       host->mrq = NULL;
+
+       /*
+        * MMC layer might call back into the driver so first unlock.
+        */
+       spin_unlock(&host->lock);
+       mmc_request_done(host->mmc, mrq);
+       spin_lock(&host->lock);
+}
+
+/*
+ * Scatter/gather functions
+ */
+
+static inline void wbsd_init_sg(struct wbsd_host *host, struct mmc_data *data)
+{
+       /*
+        * Get info. about SG list from data structure.
+        */
+       host->cur_sg = data->sg;
+       host->num_sg = data->sg_len;
+
+       host->offset = 0;
+       host->remain = host->cur_sg->length;
+}
+
+static inline int wbsd_next_sg(struct wbsd_host *host)
+{
+       /*
+        * Skip to next SG entry.
+        */
+       host->cur_sg++;
+       host->num_sg--;
+
+       /*
+        * Any entries left?
+        */
+       if (host->num_sg > 0) {
+               host->offset = 0;
+               host->remain = host->cur_sg->length;
+       }
+
+       return host->num_sg;
+}
+
+static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
+{
+       return page_address(host->cur_sg->page) + host->cur_sg->offset;
+}
+
+static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
+{
+       unsigned int len, i;
+       struct scatterlist *sg;
+       char *dmabuf = host->dma_buffer;
+       char *sgbuf;
+
+       sg = data->sg;
+       len = data->sg_len;
+
+       for (i = 0; i < len; i++) {
+               sgbuf = page_address(sg[i].page) + sg[i].offset;
+               memcpy(dmabuf, sgbuf, sg[i].length);
+               dmabuf += sg[i].length;
+       }
+}
+
+static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
+{
+       unsigned int len, i;
+       struct scatterlist *sg;
+       char *dmabuf = host->dma_buffer;
+       char *sgbuf;
+
+       sg = data->sg;
+       len = data->sg_len;
+
+       for (i = 0; i < len; i++) {
+               sgbuf = page_address(sg[i].page) + sg[i].offset;
+               memcpy(sgbuf, dmabuf, sg[i].length);
+               dmabuf += sg[i].length;
+       }
+}
+
+/*
+ * Command handling
+ */
+
+static inline void wbsd_get_short_reply(struct wbsd_host *host,
+                                       struct mmc_command *cmd)
+{
+       /*
+        * Correct response type?
+        */
+       if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) {
+               cmd->error = MMC_ERR_INVALID;
+               return;
+       }
+
+       cmd->resp[0]  = wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
+       cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
+       cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
+       cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
+       cmd->resp[1]  = wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
+}
+
+static inline void wbsd_get_long_reply(struct wbsd_host *host,
+       struct mmc_command *cmd)
+{
+       int i;
+
+       /*
+        * Correct response type?
+        */
+       if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) {
+               cmd->error = MMC_ERR_INVALID;
+               return;
+       }
+
+       for (i = 0; i < 4; i++) {
+               cmd->resp[i] =
+                       wbsd_read_index(host, WBSD_IDX_RESP1 + i * 4) << 24;
+               cmd->resp[i] |=
+                       wbsd_read_index(host, WBSD_IDX_RESP2 + i * 4) << 16;
+               cmd->resp[i] |=
+                       wbsd_read_index(host, WBSD_IDX_RESP3 + i * 4) << 8;
+               cmd->resp[i] |=
+                       wbsd_read_index(host, WBSD_IDX_RESP4 + i * 4) << 0;
+       }
+}
+
+static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
+{
+       int i;
+       u8 status, isr;
+
+       DBGF("Sending cmd (%x)\n", cmd->opcode);
+
+       /*
+        * Clear accumulated ISR. The interrupt routine
+        * will fill this one with events that occur during
+        * transfer.
+        */
+       host->isr = 0;
+
+       /*
+        * Send the command (CRC calculated by host).
+        */
+       outb(cmd->opcode, host->base + WBSD_CMDR);
+       for (i = 3; i >= 0; i--)
+               outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
+
+       cmd->error = MMC_ERR_NONE;
+
+       /*
+        * Wait for the request to complete.
+        */
+       do {
+               status = wbsd_read_index(host, WBSD_IDX_STATUS);
+       } while (status & WBSD_CARDTRAFFIC);
+
+       /*
+        * Do we expect a reply?
+        */
+       if (cmd->flags & MMC_RSP_PRESENT) {
+               /*
+                * Read back status.
+                */
+               isr = host->isr;
+
+               /* Card removed? */
+               if (isr & WBSD_INT_CARD)
+                       cmd->error = MMC_ERR_TIMEOUT;
+               /* Timeout? */
+               else if (isr & WBSD_INT_TIMEOUT)
+                       cmd->error = MMC_ERR_TIMEOUT;
+               /* CRC? */
+               else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC))
+                       cmd->error = MMC_ERR_BADCRC;
+               /* All ok */
+               else {
+                       if (cmd->flags & MMC_RSP_136)
+                               wbsd_get_long_reply(host, cmd);
+                       else
+                               wbsd_get_short_reply(host, cmd);
+               }
+       }
+
+       DBGF("Sent cmd (%x), res %d\n", cmd->opcode, cmd->error);
+}
+
+/*
+ * Data functions
+ */
+
+static void wbsd_empty_fifo(struct wbsd_host *host)
+{
+       struct mmc_data *data = host->mrq->cmd->data;
+       char *buffer;
+       int i, fsr, fifo;
+
+       /*
+        * Handle excessive data.
+        */
+       if (host->num_sg == 0)
+               return;
+
+       buffer = wbsd_sg_to_buffer(host) + host->offset;
+
+       /*
+        * Drain the fifo. This has a tendency to loop longer
+        * than the FIFO length (usually one block).
+        */
+       while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) {
+               /*
+                * The size field in the FSR is broken so we have to
+                * do some guessing.
+                */
+               if (fsr & WBSD_FIFO_FULL)
+                       fifo = 16;
+               else if (fsr & WBSD_FIFO_FUTHRE)
+                       fifo = 8;
+               else
+                       fifo = 1;
+
+               for (i = 0; i < fifo; i++) {
+                       *buffer = inb(host->base + WBSD_DFR);
+                       buffer++;
+                       host->offset++;
+                       host->remain--;
+
+                       data->bytes_xfered++;
+
+                       /*
+                        * End of scatter list entry?
+                        */
+                       if (host->remain == 0) {
+                               /*
+                                * Get next entry. Check if last.
+                                */
+                               if (!wbsd_next_sg(host))
+                                       return;
+
+                               buffer = wbsd_sg_to_buffer(host);
+                       }
+               }
+       }
+
+       /*
+        * This is a very dirty hack to solve a
+        * hardware problem. The chip doesn't trigger
+        * FIFO threshold interrupts properly.
+        */
+       if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
+               tasklet_schedule(&host->fifo_tasklet);
+}
+
+static void wbsd_fill_fifo(struct wbsd_host *host)
+{
+       struct mmc_data *data = host->mrq->cmd->data;
+       char *buffer;
+       int i, fsr, fifo;
+
+       /*
+        * Check that we aren't being called after the
+        * entire buffer has been transfered.
+        */
+       if (host->num_sg == 0)
+               return;
+
+       buffer = wbsd_sg_to_buffer(host) + host->offset;
+
+       /*
+        * Fill the fifo. This has a tendency to loop longer
+        * than the FIFO length (usually one block).
+        */
+       while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) {
+               /*
+                * The size field in the FSR is broken so we have to
+                * do some guessing.
+                */
+               if (fsr & WBSD_FIFO_EMPTY)
+                       fifo = 0;
+               else if (fsr & WBSD_FIFO_EMTHRE)
+                       fifo = 8;
+               else
+                       fifo = 15;
+
+               for (i = 16; i > fifo; i--) {
+                       outb(*buffer, host->base + WBSD_DFR);
+                       buffer++;
+                       host->offset++;
+                       host->remain--;
+
+                       data->bytes_xfered++;
+
+                       /*
+                        * End of scatter list entry?
+                        */
+                       if (host->remain == 0) {
+                               /*
+                                * Get next entry. Check if last.
+                                */
+                               if (!wbsd_next_sg(host))
+                                       return;
+
+                               buffer = wbsd_sg_to_buffer(host);
+                       }
+               }
+       }
+
+       /*
+        * The controller stops sending interrupts for
+        * 'FIFO empty' under certain conditions. So we
+        * need to be a bit more pro-active.
+        */
+       tasklet_schedule(&host->fifo_tasklet);
+}
+
+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);
+       DBGF("tsac %d ms nsac %d clk\n",
+               data->timeout_ns / 1000000, data->timeout_clks);
+
+       /*
+        * Calculate size.
+        */
+       size = data->blocks * data->blksz;
+
+       /*
+        * Check timeout values for overflow.
+        * (Yes, some cards cause this value to overflow).
+        */
+       if (data->timeout_ns > 127000000)
+               wbsd_write_index(host, WBSD_IDX_TAAC, 127);
+       else {
+               wbsd_write_index(host, WBSD_IDX_TAAC,
+                       data->timeout_ns / 1000000);
+       }
+
+       if (data->timeout_clks > 255)
+               wbsd_write_index(host, WBSD_IDX_NSAC, 255);
+       else
+               wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
+
+       /*
+        * Inform the chip of how large blocks will be
+        * sent. It needs this to determine when to
+        * calculate CRC.
+        *
+        * Space for CRC must be included in the size.
+        * Two bytes are needed for each data line.
+        */
+       if (host->bus_width == MMC_BUS_WIDTH_1) {
+               blksize = data->blksz + 2;
+
+               wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
+               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+       } else if (host->bus_width == MMC_BUS_WIDTH_4) {
+               blksize = data->blksz + 2 * 4;
+
+               wbsd_write_index(host, WBSD_IDX_PBSMSB,
+                       ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
+               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+       } else {
+               data->error = MMC_ERR_INVALID;
+               return;
+       }
+
+       /*
+        * Clear the FIFO. This is needed even for DMA
+        * transfers since the chip still uses the FIFO
+        * internally.
+        */
+       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
+       setup |= WBSD_FIFO_RESET;
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+
+       /*
+        * DMA transfer?
+        */
+       if (host->dma >= 0) {
+               /*
+                * The buffer for DMA is only 64 kB.
+                */
+               BUG_ON(size > 0x10000);
+               if (size > 0x10000) {
+                       data->error = MMC_ERR_INVALID;
+                       return;
+               }
+
+               /*
+                * Transfer data from the SG list to
+                * the DMA buffer.
+                */
+               if (data->flags & MMC_DATA_WRITE)
+                       wbsd_sg_to_dma(host, data);
+
+               /*
+                * Initialise the ISA DMA controller.
+                */
+               dmaflags = claim_dma_lock();
+               disable_dma(host->dma);
+               clear_dma_ff(host->dma);
+               if (data->flags & MMC_DATA_READ)
+                       set_dma_mode(host->dma, DMA_MODE_READ & ~0x40);
+               else
+                       set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40);
+               set_dma_addr(host->dma, host->dma_addr);
+               set_dma_count(host->dma, size);
+
+               enable_dma(host->dma);
+               release_dma_lock(dmaflags);
+
+               /*
+                * Enable DMA on the host.
+                */
+               wbsd_write_index(host, WBSD_IDX_DMA, WBSD_DMA_ENABLE);
+       } else {
+               /*
+                * This flag is used to keep printk
+                * output to a minimum.
+                */
+               host->firsterr = 1;
+
+               /*
+                * Initialise the SG list.
+                */
+               wbsd_init_sg(host, data);
+
+               /*
+                * Turn off DMA.
+                */
+               wbsd_write_index(host, WBSD_IDX_DMA, 0);
+
+               /*
+                * Set up FIFO threshold levels (and fill
+                * buffer if doing a write).
+                */
+               if (data->flags & MMC_DATA_READ) {
+                       wbsd_write_index(host, WBSD_IDX_FIFOEN,
+                               WBSD_FIFOEN_FULL | 8);
+               } else {
+                       wbsd_write_index(host, WBSD_IDX_FIFOEN,
+                               WBSD_FIFOEN_EMPTY | 8);
+                       wbsd_fill_fifo(host);
+               }
+       }
+
+       data->error = MMC_ERR_NONE;
+}
+
+static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
+{
+       unsigned long dmaflags;
+       int count;
+       u8 status;
+
+       WARN_ON(host->mrq == NULL);
+
+       /*
+        * Send a stop command if needed.
+        */
+       if (data->stop)
+               wbsd_send_command(host, data->stop);
+
+       /*
+        * Wait for the controller to leave data
+        * transfer state.
+        */
+       do {
+               status = wbsd_read_index(host, WBSD_IDX_STATUS);
+       } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
+
+       /*
+        * DMA transfer?
+        */
+       if (host->dma >= 0) {
+               /*
+                * Disable DMA on the host.
+                */
+               wbsd_write_index(host, WBSD_IDX_DMA, 0);
+
+               /*
+                * Turn of ISA DMA controller.
+                */
+               dmaflags = claim_dma_lock();
+               disable_dma(host->dma);
+               clear_dma_ff(host->dma);
+               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?
+                */
+               if (count) {
+                       printk(KERN_ERR "%s: Incomplete DMA transfer. "
+                               "%d bytes left.\n",
+                               mmc_hostname(host->mmc), count);
+
+                       if (data->error == MMC_ERR_NONE)
+                               data->error = MMC_ERR_FAILED;
+               } else {
+                       /*
+                        * Transfer data from DMA buffer to
+                        * SG list.
+                        */
+                       if (data->flags & MMC_DATA_READ)
+                               wbsd_dma_to_sg(host, data);
+               }
+
+               if (data->error != MMC_ERR_NONE) {
+                       if (data->bytes_xfered)
+                               data->bytes_xfered -= data->blksz;
+               }
+       }
+
+       DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
+
+       wbsd_request_end(host, host->mrq);
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * MMC layer callbacks                                                       *
+ *                                                                           *
+\*****************************************************************************/
+
+static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct wbsd_host *host = mmc_priv(mmc);
+       struct mmc_command *cmd;
+
+       /*
+        * Disable tasklets to avoid a deadlock.
+        */
+       spin_lock_bh(&host->lock);
+
+       BUG_ON(host->mrq != NULL);
+
+       cmd = mrq->cmd;
+
+       host->mrq = mrq;
+
+       /*
+        * If there is no card in the slot then
+        * timeout immediatly.
+        */
+       if (!(host->flags & WBSD_FCARD_PRESENT)) {
+               cmd->error = MMC_ERR_TIMEOUT;
+               goto done;
+       }
+
+       if (cmd->data) {
+               /*
+                * The hardware is so delightfully stupid that it has a list
+                * of "data" commands. If a command isn't on this list, it'll
+                * just go back to the idle state and won't send any data
+                * interrupts.
+                */
+               switch (cmd->opcode) {
+               case 11:
+               case 17:
+               case 18:
+               case 20:
+               case 24:
+               case 25:
+               case 26:
+               case 27:
+               case 30:
+               case 42:
+               case 56:
+                       break;
+
+               /* ACMDs. We don't keep track of state, so we just treat them
+                * like any other command. */
+               case 51:
+                       break;
+
+               default:
+#ifdef CONFIG_MMC_DEBUG
+                       printk(KERN_WARNING "%s: Data command %d is not "
+                               "supported by this controller.\n",
+                               mmc_hostname(host->mmc), cmd->opcode);
+#endif
+                       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.
+                */
+               if (host->dma == -1)
+                       tasklet_schedule(&host->fifo_tasklet);
+
+               spin_unlock_bh(&host->lock);
+
+               return;
+       }
+
+done:
+       wbsd_request_end(host, mrq);
+
+       spin_unlock_bh(&host->lock);
+}
+
+static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct wbsd_host *host = mmc_priv(mmc);
+       u8 clk, setup, pwr;
+
+       spin_lock_bh(&host->lock);
+
+       /*
+        * Reset the chip on each power off.
+        * Should clear out any weird states.
+        */
+       if (ios->power_mode == MMC_POWER_OFF)
+               wbsd_init_device(host);
+
+       if (ios->clock >= 24000000)
+               clk = WBSD_CLK_24M;
+       else if (ios->clock >= 16000000)
+               clk = WBSD_CLK_16M;
+       else if (ios->clock >= 12000000)
+               clk = WBSD_CLK_12M;
+       else
+               clk = WBSD_CLK_375K;
+
+       /*
+        * Only write to the clock register when
+        * there is an actual change.
+        */
+       if (clk != host->clk) {
+               wbsd_write_index(host, WBSD_IDX_CLK, clk);
+               host->clk = clk;
+       }
+
+       /*
+        * Power up card.
+        */
+       if (ios->power_mode != MMC_POWER_OFF) {
+               pwr = inb(host->base + WBSD_CSR);
+               pwr &= ~WBSD_POWER_N;
+               outb(pwr, host->base + WBSD_CSR);
+       }
+
+       /*
+        * MMC cards need to have pin 1 high during init.
+        * It wreaks havoc with the card detection though so
+        * that needs to be disabled.
+        */
+       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
+       if (ios->chip_select == MMC_CS_HIGH) {
+               BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
+               setup |= WBSD_DAT3_H;
+               host->flags |= WBSD_FIGNORE_DETECT;
+       } else {
+               if (setup & WBSD_DAT3_H) {
+                       setup &= ~WBSD_DAT3_H;
+
+                       /*
+                        * We cannot resume card detection immediatly
+                        * because of capacitance and delays in the chip.
+                        */
+                       mod_timer(&host->ignore_timer, jiffies + HZ / 100);
+               }
+       }
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+
+       /*
+        * Store bus width for later. Will be used when
+        * setting up the data transfer.
+        */
+       host->bus_width = ios->bus_width;
+
+       spin_unlock_bh(&host->lock);
+}
+
+static int wbsd_get_ro(struct mmc_host *mmc)
+{
+       struct wbsd_host *host = mmc_priv(mmc);
+       u8 csr;
+
+       spin_lock_bh(&host->lock);
+
+       csr = inb(host->base + WBSD_CSR);
+       csr |= WBSD_MSLED;
+       outb(csr, host->base + WBSD_CSR);
+
+       mdelay(1);
+
+       csr = inb(host->base + WBSD_CSR);
+       csr &= ~WBSD_MSLED;
+       outb(csr, host->base + WBSD_CSR);
+
+       spin_unlock_bh(&host->lock);
+
+       return csr & WBSD_WRPT;
+}
+
+static const struct mmc_host_ops wbsd_ops = {
+       .request        = wbsd_request,
+       .set_ios        = wbsd_set_ios,
+       .get_ro         = wbsd_get_ro,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Interrupt handling                                                        *
+ *                                                                           *
+\*****************************************************************************/
+
+/*
+ * Helper function to reset detection ignore
+ */
+
+static void wbsd_reset_ignore(unsigned long data)
+{
+       struct wbsd_host *host = (struct wbsd_host *)data;
+
+       BUG_ON(host == NULL);
+
+       DBG("Resetting card detection ignore\n");
+
+       spin_lock_bh(&host->lock);
+
+       host->flags &= ~WBSD_FIGNORE_DETECT;
+
+       /*
+        * Card status might have changed during the
+        * blackout.
+        */
+       tasklet_schedule(&host->card_tasklet);
+
+       spin_unlock_bh(&host->lock);
+}
+
+/*
+ * Tasklets
+ */
+
+static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
+{
+       WARN_ON(!host->mrq);
+       if (!host->mrq)
+               return NULL;
+
+       WARN_ON(!host->mrq->cmd);
+       if (!host->mrq->cmd)
+               return NULL;
+
+       WARN_ON(!host->mrq->cmd->data);
+       if (!host->mrq->cmd->data)
+               return NULL;
+
+       return host->mrq->cmd->data;
+}
+
+static void wbsd_tasklet_card(unsigned long param)
+{
+       struct wbsd_host *host = (struct wbsd_host *)param;
+       u8 csr;
+       int delay = -1;
+
+       spin_lock(&host->lock);
+
+       if (host->flags & WBSD_FIGNORE_DETECT) {
+               spin_unlock(&host->lock);
+               return;
+       }
+
+       csr = inb(host->base + WBSD_CSR);
+       WARN_ON(csr == 0xff);
+
+       if (csr & WBSD_CARDPRESENT) {
+               if (!(host->flags & WBSD_FCARD_PRESENT)) {
+                       DBG("Card inserted\n");
+                       host->flags |= WBSD_FCARD_PRESENT;
+
+                       delay = 500;
+               }
+       } else if (host->flags & WBSD_FCARD_PRESENT) {
+               DBG("Card removed\n");
+               host->flags &= ~WBSD_FCARD_PRESENT;
+
+               if (host->mrq) {
+                       printk(KERN_ERR "%s: Card removed during transfer!\n",
+                               mmc_hostname(host->mmc));
+                       wbsd_reset(host);
+
+                       host->mrq->cmd->error = MMC_ERR_FAILED;
+                       tasklet_schedule(&host->finish_tasklet);
+               }
+
+               delay = 0;
+       }
+
+       /*
+        * Unlock first since we might get a call back.
+        */
+
+       spin_unlock(&host->lock);
+
+       if (delay != -1)
+               mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
+}
+
+static void wbsd_tasklet_fifo(unsigned long param)
+{
+       struct wbsd_host *host = (struct wbsd_host *)param;
+       struct mmc_data *data;
+
+       spin_lock(&host->lock);
+
+       if (!host->mrq)
+               goto end;
+
+       data = wbsd_get_data(host);
+       if (!data)
+               goto end;
+
+       if (data->flags & MMC_DATA_WRITE)
+               wbsd_fill_fifo(host);
+       else
+               wbsd_empty_fifo(host);
+
+       /*
+        * Done?
+        */
+       if (host->num_sg == 0) {
+               wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
+               tasklet_schedule(&host->finish_tasklet);
+       }
+
+end:
+       spin_unlock(&host->lock);
+}
+
+static void wbsd_tasklet_crc(unsigned long param)
+{
+       struct wbsd_host *host = (struct wbsd_host *)param;
+       struct mmc_data *data;
+
+       spin_lock(&host->lock);
+
+       if (!host->mrq)
+               goto end;
+
+       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);
+}
+
+static void wbsd_tasklet_timeout(unsigned long param)
+{
+       struct wbsd_host *host = (struct wbsd_host *)param;
+       struct mmc_data *data;
+
+       spin_lock(&host->lock);
+
+       if (!host->mrq)
+               goto end;
+
+       data = wbsd_get_data(host);
+       if (!data)
+               goto end;
+
+       DBGF("Timeout\n");
+
+       data->error = MMC_ERR_TIMEOUT;
+
+       tasklet_schedule(&host->finish_tasklet);
+
+end:
+       spin_unlock(&host->lock);
+}
+
+static void wbsd_tasklet_finish(unsigned long param)
+{
+       struct wbsd_host *host = (struct wbsd_host *)param;
+       struct mmc_data *data;
+
+       spin_lock(&host->lock);
+
+       WARN_ON(!host->mrq);
+       if (!host->mrq)
+               goto end;
+
+       data = wbsd_get_data(host);
+       if (!data)
+               goto end;
+
+       wbsd_finish_data(host, data);
+
+end:
+       spin_unlock(&host->lock);
+}
+
+/*
+ * Interrupt handling
+ */
+
+static irqreturn_t wbsd_irq(int irq, void *dev_id)
+{
+       struct wbsd_host *host = dev_id;
+       int isr;
+
+       isr = inb(host->base + WBSD_ISR);
+
+       /*
+        * Was it actually our hardware that caused the interrupt?
+        */
+       if (isr == 0xff || isr == 0x00)
+               return IRQ_NONE;
+
+       host->isr |= isr;
+
+       /*
+        * Schedule tasklets as needed.
+        */
+       if (isr & WBSD_INT_CARD)
+               tasklet_schedule(&host->card_tasklet);
+       if (isr & WBSD_INT_FIFO_THRE)
+               tasklet_schedule(&host->fifo_tasklet);
+       if (isr & WBSD_INT_CRC)
+               tasklet_hi_schedule(&host->crc_tasklet);
+       if (isr & WBSD_INT_TIMEOUT)
+               tasklet_hi_schedule(&host->timeout_tasklet);
+       if (isr & WBSD_INT_TC)
+               tasklet_schedule(&host->finish_tasklet);
+
+       return IRQ_HANDLED;
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Device initialisation and shutdown                                        *
+ *                                                                           *
+\*****************************************************************************/
+
+/*
+ * Allocate/free MMC structure.
+ */
+
+static int __devinit wbsd_alloc_mmc(struct device *dev)
+{
+       struct mmc_host *mmc;
+       struct wbsd_host *host;
+
+       /*
+        * Allocate MMC structure.
+        */
+       mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
+       if (!mmc)
+               return -ENOMEM;
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       host->dma = -1;
+
+       /*
+        * Set host parameters.
+        */
+       mmc->ops = &wbsd_ops;
+       mmc->f_min = 375000;
+       mmc->f_max = 24000000;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
+
+       spin_lock_init(&host->lock);
+
+       /*
+        * Set up timers
+        */
+       init_timer(&host->ignore_timer);
+       host->ignore_timer.data = (unsigned long)host;
+       host->ignore_timer.function = wbsd_reset_ignore;
+
+       /*
+        * Maximum number of segments. Worst case is one sector per segment
+        * so this will be 64kB/512.
+        */
+       mmc->max_hw_segs = 128;
+       mmc->max_phys_segs = 128;
+
+       /*
+        * Maximum request size. Also limited by 64KiB buffer.
+        */
+       mmc->max_req_size = 65536;
+
+       /*
+        * Maximum segment size. Could be one segment with the maximum number
+        * of bytes.
+        */
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Maximum block size. We have 12 bits (= 4095) but have to subtract
+        * space for CRC. So the maximum is 4095 - 4*2 = 4087.
+        */
+       mmc->max_blk_size = 4087;
+
+       /*
+        * Maximum block count. There is no real limit so the maximum
+        * request size will be the only restriction.
+        */
+       mmc->max_blk_count = mmc->max_req_size;
+
+       dev_set_drvdata(dev, mmc);
+
+       return 0;
+}
+
+static void __devexit wbsd_free_mmc(struct device *dev)
+{
+       struct mmc_host *mmc;
+       struct wbsd_host *host;
+
+       mmc = dev_get_drvdata(dev);
+       if (!mmc)
+               return;
+
+       host = mmc_priv(mmc);
+       BUG_ON(host == NULL);
+
+       del_timer_sync(&host->ignore_timer);
+
+       mmc_free_host(mmc);
+
+       dev_set_drvdata(dev, NULL);
+}
+
+/*
+ * Scan for known chip id:s
+ */
+
+static int __devinit wbsd_scan(struct wbsd_host *host)
+{
+       int i, j, k;
+       int id;
+
+       /*
+        * Iterate through all ports, all codes to
+        * find hardware that is in our known list.
+        */
+       for (i = 0; i < ARRAY_SIZE(config_ports); i++) {
+               if (!request_region(config_ports[i], 2, DRIVER_NAME))
+                       continue;
+
+               for (j = 0; j < ARRAY_SIZE(unlock_codes); j++) {
+                       id = 0xFFFF;
+
+                       host->config = config_ports[i];
+                       host->unlock_code = unlock_codes[j];
+
+                       wbsd_unlock_config(host);
+
+                       outb(WBSD_CONF_ID_HI, config_ports[i]);
+                       id = inb(config_ports[i] + 1) << 8;
+
+                       outb(WBSD_CONF_ID_LO, config_ports[i]);
+                       id |= inb(config_ports[i] + 1);
+
+                       wbsd_lock_config(host);
+
+                       for (k = 0; k < ARRAY_SIZE(valid_ids); k++) {
+                               if (id == valid_ids[k]) {
+                                       host->chip_id = id;
+
+                                       return 0;
+                               }
+                       }
+
+                       if (id != 0xFFFF) {
+                               DBG("Unknown hardware (id %x) found at %x\n",
+                                       id, config_ports[i]);
+                       }
+               }
+
+               release_region(config_ports[i], 2);
+       }
+
+       host->config = 0;
+       host->unlock_code = 0;
+
+       return -ENODEV;
+}
+
+/*
+ * Allocate/free io port ranges
+ */
+
+static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
+{
+       if (base & 0x7)
+               return -EINVAL;
+
+       if (!request_region(base, 8, DRIVER_NAME))
+               return -EIO;
+
+       host->base = base;
+
+       return 0;
+}
+
+static void __devexit wbsd_release_regions(struct wbsd_host *host)
+{
+       if (host->base)
+               release_region(host->base, 8);
+
+       host->base = 0;
+
+       if (host->config)
+               release_region(host->config, 2);
+
+       host->config = 0;
+}
+
+/*
+ * Allocate/free DMA port and buffer
+ */
+
+static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
+{
+       if (dma < 0)
+               return;
+
+       if (request_dma(dma, DRIVER_NAME))
+               goto err;
+
+       /*
+        * We need to allocate a special buffer in
+        * order for ISA to be able to DMA to it.
+        */
+       host->dma_buffer = kmalloc(WBSD_DMA_SIZE,
+               GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN);
+       if (!host->dma_buffer)
+               goto free;
+
+       /*
+        * Translate the address to a physical address.
+        */
+       host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
+               WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+
+       /*
+        * ISA DMA must be aligned on a 64k basis.
+        */
+       if ((host->dma_addr & 0xffff) != 0)
+               goto kfree;
+       /*
+        * ISA cannot access memory above 16 MB.
+        */
+       else if (host->dma_addr >= 0x1000000)
+               goto kfree;
+
+       host->dma = dma;
+
+       return;
+
+kfree:
+       /*
+        * If we've gotten here then there is some kind of alignment bug
+        */
+       BUG_ON(1);
+
+       dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
+               WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+       host->dma_addr = (dma_addr_t)NULL;
+
+       kfree(host->dma_buffer);
+       host->dma_buffer = NULL;
+
+free:
+       free_dma(dma);
+
+err:
+       printk(KERN_WARNING DRIVER_NAME ": Unable to allocate DMA %d. "
+               "Falling back on FIFO.\n", dma);
+}
+
+static void __devexit wbsd_release_dma(struct wbsd_host *host)
+{
+       if (host->dma_addr) {
+               dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
+                       WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+       }
+       kfree(host->dma_buffer);
+       if (host->dma >= 0)
+               free_dma(host->dma);
+
+       host->dma = -1;
+       host->dma_buffer = NULL;
+       host->dma_addr = (dma_addr_t)NULL;
+}
+
+/*
+ * Allocate/free IRQ.
+ */
+
+static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
+{
+       int ret;
+
+       /*
+        * Allocate interrupt.
+        */
+
+       ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host);
+       if (ret)
+               return ret;
+
+       host->irq = irq;
+
+       /*
+        * Set up tasklets.
+        */
+       tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
+                       (unsigned long)host);
+       tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo,
+                       (unsigned long)host);
+       tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc,
+                       (unsigned long)host);
+       tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout,
+                       (unsigned long)host);
+       tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
+                       (unsigned long)host);
+
+       return 0;
+}
+
+static void __devexit wbsd_release_irq(struct wbsd_host *host)
+{
+       if (!host->irq)
+               return;
+
+       free_irq(host->irq, host);
+
+       host->irq = 0;
+
+       tasklet_kill(&host->card_tasklet);
+       tasklet_kill(&host->fifo_tasklet);
+       tasklet_kill(&host->crc_tasklet);
+       tasklet_kill(&host->timeout_tasklet);
+       tasklet_kill(&host->finish_tasklet);
+}
+
+/*
+ * Allocate all resources for the host.
+ */
+
+static int __devinit wbsd_request_resources(struct wbsd_host *host,
+       int base, int irq, int dma)
+{
+       int ret;
+
+       /*
+        * Allocate I/O ports.
+        */
+       ret = wbsd_request_region(host, base);
+       if (ret)
+               return ret;
+
+       /*
+        * Allocate interrupt.
+        */
+       ret = wbsd_request_irq(host, irq);
+       if (ret)
+               return ret;
+
+       /*
+        * Allocate DMA.
+        */
+       wbsd_request_dma(host, dma);
+
+       return 0;
+}
+
+/*
+ * Release all resources for the host.
+ */
+
+static void __devexit wbsd_release_resources(struct wbsd_host *host)
+{
+       wbsd_release_dma(host);
+       wbsd_release_irq(host);
+       wbsd_release_regions(host);
+}
+
+/*
+ * Configure the resources the chip should use.
+ */
+
+static void wbsd_chip_config(struct wbsd_host *host)
+{
+       wbsd_unlock_config(host);
+
+       /*
+        * Reset the chip.
+        */
+       wbsd_write_config(host, WBSD_CONF_SWRST, 1);
+       wbsd_write_config(host, WBSD_CONF_SWRST, 0);
+
+       /*
+        * Select SD/MMC function.
+        */
+       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+
+       /*
+        * Set up card detection.
+        */
+       wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
+
+       /*
+        * Configure chip
+        */
+       wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
+       wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
+
+       wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
+
+       if (host->dma >= 0)
+               wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
+
+       /*
+        * Enable and power up chip.
+        */
+       wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
+       wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+
+       wbsd_lock_config(host);
+}
+
+/*
+ * Check that configured resources are correct.
+ */
+
+static int wbsd_chip_validate(struct wbsd_host *host)
+{
+       int base, irq, dma;
+
+       wbsd_unlock_config(host);
+
+       /*
+        * Select SD/MMC function.
+        */
+       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+
+       /*
+        * Read configuration.
+        */
+       base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
+       base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
+
+       irq = wbsd_read_config(host, WBSD_CONF_IRQ);
+
+       dma = wbsd_read_config(host, WBSD_CONF_DRQ);
+
+       wbsd_lock_config(host);
+
+       /*
+        * Validate against given configuration.
+        */
+       if (base != host->base)
+               return 0;
+       if (irq != host->irq)
+               return 0;
+       if ((dma != host->dma) && (host->dma != -1))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * Powers down the SD function
+ */
+
+static void wbsd_chip_poweroff(struct wbsd_host *host)
+{
+       wbsd_unlock_config(host);
+
+       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+       wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
+
+       wbsd_lock_config(host);
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Devices setup and shutdown                                                *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
+       int pnp)
+{
+       struct wbsd_host *host = NULL;
+       struct mmc_host *mmc = NULL;
+       int ret;
+
+       ret = wbsd_alloc_mmc(dev);
+       if (ret)
+               return ret;
+
+       mmc = dev_get_drvdata(dev);
+       host = mmc_priv(mmc);
+
+       /*
+        * Scan for hardware.
+        */
+       ret = wbsd_scan(host);
+       if (ret) {
+               if (pnp && (ret == -ENODEV)) {
+                       printk(KERN_WARNING DRIVER_NAME
+                               ": Unable to confirm device presence. You may "
+                               "experience lock-ups.\n");
+               } else {
+                       wbsd_free_mmc(dev);
+                       return ret;
+               }
+       }
+
+       /*
+        * Request resources.
+        */
+       ret = wbsd_request_resources(host, base, irq, dma);
+       if (ret) {
+               wbsd_release_resources(host);
+               wbsd_free_mmc(dev);
+               return ret;
+       }
+
+       /*
+        * See if chip needs to be configured.
+        */
+       if (pnp) {
+               if ((host->config != 0) && !wbsd_chip_validate(host)) {
+                       printk(KERN_WARNING DRIVER_NAME
+                               ": PnP active but chip not configured! "
+                               "You probably have a buggy BIOS. "
+                               "Configuring chip manually.\n");
+                       wbsd_chip_config(host);
+               }
+       } else
+               wbsd_chip_config(host);
+
+       /*
+        * Power Management stuff. No idea how this works.
+        * Not tested.
+        */
+#ifdef CONFIG_PM
+       if (host->config) {
+               wbsd_unlock_config(host);
+               wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
+               wbsd_lock_config(host);
+       }
+#endif
+       /*
+        * Allow device to initialise itself properly.
+        */
+       mdelay(5);
+
+       /*
+        * Reset the chip into a known state.
+        */
+       wbsd_init_device(host);
+
+       mmc_add_host(mmc);
+
+       printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
+       if (host->chip_id != 0)
+               printk(" id %x", (int)host->chip_id);
+       printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
+       if (host->dma >= 0)
+               printk(" dma %d", (int)host->dma);
+       else
+               printk(" FIFO");
+       if (pnp)
+               printk(" PnP");
+       printk("\n");
+
+       return 0;
+}
+
+static void __devexit wbsd_shutdown(struct device *dev, int pnp)
+{
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       struct wbsd_host *host;
+
+       if (!mmc)
+               return;
+
+       host = mmc_priv(mmc);
+
+       mmc_remove_host(mmc);
+
+       /*
+        * Power down the SD/MMC function.
+        */
+       if (!pnp)
+               wbsd_chip_poweroff(host);
+
+       wbsd_release_resources(host);
+
+       wbsd_free_mmc(dev);
+}
+
+/*
+ * Non-PnP
+ */
+
+static int __devinit wbsd_probe(struct platform_device *dev)
+{
+       /* Use the module parameters for resources */
+       return wbsd_init(&dev->dev, io, irq, dma, 0);
+}
+
+static int __devexit wbsd_remove(struct platform_device *dev)
+{
+       wbsd_shutdown(&dev->dev, 0);
+
+       return 0;
+}
+
+/*
+ * PnP
+ */
+
+#ifdef CONFIG_PNP
+
+static int __devinit
+wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
+{
+       int io, irq, dma;
+
+       /*
+        * Get resources from PnP layer.
+        */
+       io = pnp_port_start(pnpdev, 0);
+       irq = pnp_irq(pnpdev, 0);
+       if (pnp_dma_valid(pnpdev, 0))
+               dma = pnp_dma(pnpdev, 0);
+       else
+               dma = -1;
+
+       DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
+
+       return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
+}
+
+static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
+{
+       wbsd_shutdown(&dev->dev, 1);
+}
+
+#endif /* CONFIG_PNP */
+
+/*
+ * Power management
+ */
+
+#ifdef CONFIG_PM
+
+static int wbsd_suspend(struct wbsd_host *host, pm_message_t state)
+{
+       BUG_ON(host == NULL);
+
+       return mmc_suspend_host(host->mmc, state);
+}
+
+static int wbsd_resume(struct wbsd_host *host)
+{
+       BUG_ON(host == NULL);
+
+       wbsd_init_device(host);
+
+       return mmc_resume_host(host->mmc);
+}
+
+static int wbsd_platform_suspend(struct platform_device *dev,
+                                pm_message_t state)
+{
+       struct mmc_host *mmc = platform_get_drvdata(dev);
+       struct wbsd_host *host;
+       int ret;
+
+       if (mmc == NULL)
+               return 0;
+
+       DBGF("Suspending...\n");
+
+       host = mmc_priv(mmc);
+
+       ret = wbsd_suspend(host, state);
+       if (ret)
+               return ret;
+
+       wbsd_chip_poweroff(host);
+
+       return 0;
+}
+
+static int wbsd_platform_resume(struct platform_device *dev)
+{
+       struct mmc_host *mmc = platform_get_drvdata(dev);
+       struct wbsd_host *host;
+
+       if (mmc == NULL)
+               return 0;
+
+       DBGF("Resuming...\n");
+
+       host = mmc_priv(mmc);
+
+       wbsd_chip_config(host);
+
+       /*
+        * Allow device to initialise itself properly.
+        */
+       mdelay(5);
+
+       return wbsd_resume(host);
+}
+
+#ifdef CONFIG_PNP
+
+static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
+{
+       struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
+       struct wbsd_host *host;
+
+       if (mmc == NULL)
+               return 0;
+
+       DBGF("Suspending...\n");
+
+       host = mmc_priv(mmc);
+
+       return wbsd_suspend(host, state);
+}
+
+static int wbsd_pnp_resume(struct pnp_dev *pnp_dev)
+{
+       struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
+       struct wbsd_host *host;
+
+       if (mmc == NULL)
+               return 0;
+
+       DBGF("Resuming...\n");
+
+       host = mmc_priv(mmc);
+
+       /*
+        * See if chip needs to be configured.
+        */
+       if (host->config != 0) {
+               if (!wbsd_chip_validate(host)) {
+                       printk(KERN_WARNING DRIVER_NAME
+                               ": PnP active but chip not configured! "
+                               "You probably have a buggy BIOS. "
+                               "Configuring chip manually.\n");
+                       wbsd_chip_config(host);
+               }
+       }
+
+       /*
+        * Allow device to initialise itself properly.
+        */
+       mdelay(5);
+
+       return wbsd_resume(host);
+}
+
+#endif /* CONFIG_PNP */
+
+#else /* CONFIG_PM */
+
+#define wbsd_platform_suspend NULL
+#define wbsd_platform_resume NULL
+
+#define wbsd_pnp_suspend NULL
+#define wbsd_pnp_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_device *wbsd_device;
+
+static struct platform_driver wbsd_driver = {
+       .probe          = wbsd_probe,
+       .remove         = __devexit_p(wbsd_remove),
+
+       .suspend        = wbsd_platform_suspend,
+       .resume         = wbsd_platform_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+#ifdef CONFIG_PNP
+
+static struct pnp_driver wbsd_pnp_driver = {
+       .name           = DRIVER_NAME,
+       .id_table       = pnp_dev_table,
+       .probe          = wbsd_pnp_probe,
+       .remove         = __devexit_p(wbsd_pnp_remove),
+
+       .suspend        = wbsd_pnp_suspend,
+       .resume         = wbsd_pnp_resume,
+};
+
+#endif /* CONFIG_PNP */
+
+/*
+ * Module loading/unloading
+ */
+
+static int __init wbsd_drv_init(void)
+{
+       int result;
+
+       printk(KERN_INFO DRIVER_NAME
+               ": Winbond W83L51xD SD/MMC card interface driver\n");
+       printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+
+#ifdef CONFIG_PNP
+
+       if (!nopnp) {
+               result = pnp_register_driver(&wbsd_pnp_driver);
+               if (result < 0)
+                       return result;
+       }
+#endif /* CONFIG_PNP */
+
+       if (nopnp) {
+               result = platform_driver_register(&wbsd_driver);
+               if (result < 0)
+                       return result;
+
+               wbsd_device = platform_device_alloc(DRIVER_NAME, -1);
+               if (!wbsd_device) {
+                       platform_driver_unregister(&wbsd_driver);
+                       return -ENOMEM;
+               }
+
+               result = platform_device_add(wbsd_device);
+               if (result) {
+                       platform_device_put(wbsd_device);
+                       platform_driver_unregister(&wbsd_driver);
+                       return result;
+               }
+       }
+
+       return 0;
+}
+
+static void __exit wbsd_drv_exit(void)
+{
+#ifdef CONFIG_PNP
+
+       if (!nopnp)
+               pnp_unregister_driver(&wbsd_pnp_driver);
+
+#endif /* CONFIG_PNP */
+
+       if (nopnp) {
+               platform_device_unregister(wbsd_device);
+
+               platform_driver_unregister(&wbsd_driver);
+       }
+
+       DBG("unloaded\n");
+}
+
+module_init(wbsd_drv_init);
+module_exit(wbsd_drv_exit);
+#ifdef CONFIG_PNP
+module_param(nopnp, uint, 0444);
+#endif
+module_param(io, uint, 0444);
+module_param(irq, uint, 0444);
+module_param(dma, int, 0444);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
+MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
+
+#ifdef CONFIG_PNP
+MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)");
+#endif
+MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)");
+MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)");
+MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)");
diff --git a/drivers/mmc/host/wbsd.h b/drivers/mmc/host/wbsd.h
new file mode 100644 (file)
index 0000000..873bda1
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
+ *
+ *  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
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define LOCK_CODE              0xAA
+
+#define WBSD_CONF_SWRST                0x02
+#define WBSD_CONF_DEVICE       0x07
+#define WBSD_CONF_ID_HI                0x20
+#define WBSD_CONF_ID_LO                0x21
+#define WBSD_CONF_POWER                0x22
+#define WBSD_CONF_PME          0x23
+#define WBSD_CONF_PMES         0x24
+
+#define WBSD_CONF_ENABLE       0x30
+#define WBSD_CONF_PORT_HI      0x60
+#define WBSD_CONF_PORT_LO      0x61
+#define WBSD_CONF_IRQ          0x70
+#define WBSD_CONF_DRQ          0x74
+
+#define WBSD_CONF_PINS         0xF0
+
+#define DEVICE_SD              0x03
+
+#define WBSD_PINS_DAT3_HI      0x20
+#define WBSD_PINS_DAT3_OUT     0x10
+#define WBSD_PINS_GP11_HI      0x04
+#define WBSD_PINS_DETECT_GP11  0x02
+#define WBSD_PINS_DETECT_DAT3  0x01
+
+#define WBSD_CMDR              0x00
+#define WBSD_DFR               0x01
+#define WBSD_EIR               0x02
+#define WBSD_ISR               0x03
+#define WBSD_FSR               0x04
+#define WBSD_IDXR              0x05
+#define WBSD_DATAR             0x06
+#define WBSD_CSR               0x07
+
+#define WBSD_EINT_CARD         0x40
+#define WBSD_EINT_FIFO_THRE    0x20
+#define WBSD_EINT_CRC          0x10
+#define WBSD_EINT_TIMEOUT      0x08
+#define WBSD_EINT_PROGEND      0x04
+#define WBSD_EINT_BUSYEND      0x02
+#define WBSD_EINT_TC           0x01
+
+#define WBSD_INT_PENDING       0x80
+#define WBSD_INT_CARD          0x40
+#define WBSD_INT_FIFO_THRE     0x20
+#define WBSD_INT_CRC           0x10
+#define WBSD_INT_TIMEOUT       0x08
+#define WBSD_INT_PROGEND       0x04
+#define WBSD_INT_BUSYEND       0x02
+#define WBSD_INT_TC            0x01
+
+#define WBSD_FIFO_EMPTY                0x80
+#define WBSD_FIFO_FULL         0x40
+#define WBSD_FIFO_EMTHRE       0x20
+#define WBSD_FIFO_FUTHRE       0x10
+#define WBSD_FIFO_SZMASK       0x0F
+
+#define WBSD_MSLED             0x20
+#define WBSD_POWER_N           0x10
+#define WBSD_WRPT              0x04
+#define WBSD_CARDPRESENT       0x01
+
+#define WBSD_IDX_CLK           0x01
+#define WBSD_IDX_PBSMSB                0x02
+#define WBSD_IDX_TAAC          0x03
+#define WBSD_IDX_NSAC          0x04
+#define WBSD_IDX_PBSLSB                0x05
+#define WBSD_IDX_SETUP         0x06
+#define WBSD_IDX_DMA           0x07
+#define WBSD_IDX_FIFOEN                0x08
+#define WBSD_IDX_STATUS                0x10
+#define WBSD_IDX_RSPLEN                0x1E
+#define WBSD_IDX_RESP0         0x1F
+#define WBSD_IDX_RESP1         0x20
+#define WBSD_IDX_RESP2         0x21
+#define WBSD_IDX_RESP3         0x22
+#define WBSD_IDX_RESP4         0x23
+#define WBSD_IDX_RESP5         0x24
+#define WBSD_IDX_RESP6         0x25
+#define WBSD_IDX_RESP7         0x26
+#define WBSD_IDX_RESP8         0x27
+#define WBSD_IDX_RESP9         0x28
+#define WBSD_IDX_RESP10                0x29
+#define WBSD_IDX_RESP11                0x2A
+#define WBSD_IDX_RESP12                0x2B
+#define WBSD_IDX_RESP13                0x2C
+#define WBSD_IDX_RESP14                0x2D
+#define WBSD_IDX_RESP15                0x2E
+#define WBSD_IDX_RESP16                0x2F
+#define WBSD_IDX_CRCSTATUS     0x30
+#define WBSD_IDX_ISR           0x3F
+
+#define WBSD_CLK_375K          0x00
+#define WBSD_CLK_12M           0x01
+#define WBSD_CLK_16M           0x02
+#define WBSD_CLK_24M           0x03
+
+#define WBSD_DATA_WIDTH                0x01
+
+#define WBSD_DAT3_H            0x08
+#define WBSD_FIFO_RESET                0x04
+#define WBSD_SOFT_RESET                0x02
+#define WBSD_INC_INDEX         0x01
+
+#define WBSD_DMA_SINGLE                0x02
+#define WBSD_DMA_ENABLE                0x01
+
+#define WBSD_FIFOEN_EMPTY      0x20
+#define WBSD_FIFOEN_FULL       0x10
+#define WBSD_FIFO_THREMASK     0x0F
+
+#define WBSD_BLOCK_READ                0x80
+#define WBSD_BLOCK_WRITE       0x40
+#define WBSD_BUSY              0x20
+#define WBSD_CARDTRAFFIC       0x04
+#define WBSD_SENDCMD           0x02
+#define WBSD_RECVRES           0x01
+
+#define WBSD_RSP_SHORT         0x00
+#define WBSD_RSP_LONG          0x01
+
+#define WBSD_CRC_MASK          0x1F
+#define WBSD_CRC_OK            0x05 /* S010E (00101) */
+#define WBSD_CRC_FAIL          0x0B /* S101E (01011) */
+
+#define WBSD_DMA_SIZE          65536
+
+struct wbsd_host
+{
+       struct mmc_host*        mmc;            /* MMC structure */
+
+       spinlock_t              lock;           /* Mutex */
+
+       int                     flags;          /* Driver states */
+
+#define WBSD_FCARD_PRESENT     (1<<0)          /* Card is present */
+#define WBSD_FIGNORE_DETECT    (1<<1)          /* Ignore card detection */
+
+       struct mmc_request*     mrq;            /* Current request */
+
+       u8                      isr;            /* Accumulated ISR */
+
+       struct scatterlist*     cur_sg;         /* Current SG entry */
+       unsigned int            num_sg;         /* Number of entries left */
+
+       unsigned int            offset;         /* Offset into current entry */
+       unsigned int            remain;         /* Data left in curren entry */
+
+       char*                   dma_buffer;     /* ISA DMA buffer */
+       dma_addr_t              dma_addr;       /* Physical address for same */
+
+       int                     firsterr;       /* See fifo functions */
+
+       u8                      clk;            /* Current clock speed */
+       unsigned char           bus_width;      /* Current bus width */
+
+       int                     config;         /* Config port */
+       u8                      unlock_code;    /* Code to unlock config */
+
+       int                     chip_id;        /* ID of controller */
+
+       int                     base;           /* I/O port base */
+       int                     irq;            /* Interrupt */
+       int                     dma;            /* DMA channel */
+
+       struct tasklet_struct   card_tasklet;   /* Tasklet structures */
+       struct tasklet_struct   fifo_tasklet;
+       struct tasklet_struct   crc_tasklet;
+       struct tasklet_struct   timeout_tasklet;
+       struct tasklet_struct   finish_tasklet;
+
+       struct timer_list       ignore_timer;   /* Ignore detection timer */
+};
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
deleted file mode 100644 (file)
index 0de5c9e..0000000
+++ /dev/null
@@ -1,1138 +0,0 @@
-/*
- *  linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
- *
- *  Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
- *  Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
- *
- *  derived from pxamci.c by Russell King
- *
- * 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.
- *
- *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- *             Changed to conform redesigned i.MX scatter gather DMA interface
- *
- *  2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- *             Updated for 2.6.14 kernel
- *
- *  2005-12-13 Jay Monkman <jtm@smoothsmoothie.com>
- *             Found and corrected problems in the write path
- *
- *  2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- *             The event handling rewritten right way in softirq.
- *             Added many ugly hacks and delays to overcome SDHC
- *             deficiencies
- *
- */
-
-#ifdef CONFIG_MMC_DEBUG
-#define DEBUG
-#else
-#undef  DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#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>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/sizes.h>
-#include <asm/arch/mmc.h>
-#include <asm/arch/imx-dma.h>
-
-#include "imxmmc.h"
-
-#define DRIVER_NAME "imx-mmc"
-
-#define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \
-                     INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \
-                     INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO)
-
-struct imxmci_host {
-       struct mmc_host         *mmc;
-       spinlock_t              lock;
-       struct resource         *res;
-       int                     irq;
-       imx_dmach_t             dma;
-       unsigned int            clkrt;
-       unsigned int            cmdat;
-       volatile unsigned int   imask;
-       unsigned int            power_mode;
-       unsigned int            present;
-       struct imxmmc_platform_data *pdata;
-
-       struct mmc_request      *req;
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;
-
-       struct timer_list       timer;
-       struct tasklet_struct   tasklet;
-       unsigned int            status_reg;
-       unsigned long           pending_events;
-       /* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */
-       u16                     *data_ptr;
-       unsigned int            data_cnt;
-       atomic_t                stuck_timeout;
-
-       unsigned int            dma_nents;
-       unsigned int            dma_size;
-       unsigned int            dma_dir;
-       int                     dma_allocated;
-
-       unsigned char           actual_bus_width;
-
-       int                     prev_cmd_code;
-};
-
-#define IMXMCI_PEND_IRQ_b      0
-#define IMXMCI_PEND_DMA_END_b  1
-#define IMXMCI_PEND_DMA_ERR_b  2
-#define IMXMCI_PEND_WAIT_RESP_b        3
-#define IMXMCI_PEND_DMA_DATA_b 4
-#define IMXMCI_PEND_CPU_DATA_b 5
-#define IMXMCI_PEND_CARD_XCHG_b        6
-#define IMXMCI_PEND_SET_INIT_b 7
-#define IMXMCI_PEND_STARTED_b  8
-
-#define IMXMCI_PEND_IRQ_m      (1 << IMXMCI_PEND_IRQ_b)
-#define IMXMCI_PEND_DMA_END_m  (1 << IMXMCI_PEND_DMA_END_b)
-#define IMXMCI_PEND_DMA_ERR_m  (1 << IMXMCI_PEND_DMA_ERR_b)
-#define IMXMCI_PEND_WAIT_RESP_m        (1 << IMXMCI_PEND_WAIT_RESP_b)
-#define IMXMCI_PEND_DMA_DATA_m (1 << IMXMCI_PEND_DMA_DATA_b)
-#define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b)
-#define IMXMCI_PEND_CARD_XCHG_m        (1 << IMXMCI_PEND_CARD_XCHG_b)
-#define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b)
-#define IMXMCI_PEND_STARTED_m  (1 << IMXMCI_PEND_STARTED_b)
-
-static void imxmci_stop_clock(struct imxmci_host *host)
-{
-       int i = 0;
-       MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK;
-       while(i < 0x1000) {
-               if(!(i & 0x7f))
-                       MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK;
-
-               if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) {
-                       /* Check twice before cut */
-                       if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN))
-                               return;
-               }
-
-               i++;
-       }
-       dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
-}
-
-static int imxmci_start_clock(struct imxmci_host *host)
-{
-       unsigned int trials = 0;
-       unsigned int delay_limit = 128;
-       unsigned long flags;
-
-       MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
-
-       clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
-
-       /*
-        * Command start of the clock, this usually succeeds in less
-        * then 6 delay loops, but during card detection (low clockrate)
-        * it takes up to 5000 delay loops and sometimes fails for the first time
-        */
-       MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
-
-       do {
-               unsigned int delay = delay_limit;
-
-               while(delay--){
-                       if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
-                               /* Check twice before cut */
-                               if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
-                                       return 0;
-
-                       if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
-                               return 0;
-               }
-
-               local_irq_save(flags);
-               /*
-                * Ensure, that request is not doubled under all possible circumstances.
-                * It is possible, that cock running state is missed, because some other
-                * IRQ or schedule delays this function execution and the clocks has
-                * been already stopped by other means (response processing, SDHC HW)
-                */
-               if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
-                       MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
-               local_irq_restore(flags);
-
-       } while(++trials<256);
-
-       dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
-
-       return -1;
-}
-
-static void imxmci_softreset(void)
-{
-       /* reset sequence */
-       MMC_STR_STP_CLK = 0x8;
-       MMC_STR_STP_CLK = 0xD;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-       MMC_STR_STP_CLK = 0x5;
-
-       MMC_RES_TO = 0xff;
-       MMC_BLK_LEN = 512;
-       MMC_NOB = 1;
-}
-
-static int imxmci_busy_wait_for_status(struct imxmci_host *host,
-                       unsigned int *pstat, unsigned int stat_mask,
-                       int timeout, const char *where)
-{
-       int loops=0;
-       while(!(*pstat & stat_mask)) {
-               loops+=2;
-               if(loops >= timeout) {
-                       dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n",
-                               where, *pstat, stat_mask);
-                       return -1;
-               }
-               udelay(2);
-               *pstat |= MMC_STATUS;
-       }
-       if(!loops)
-               return 0;
-
-       /* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */
-       if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000))
-               dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
-                       loops, where, *pstat, stat_mask);
-       return loops;
-}
-
-static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
-{
-       unsigned int nob = data->blocks;
-       unsigned int blksz = data->blksz;
-       unsigned int datasz = nob * blksz;
-       int i;
-
-       if (data->flags & MMC_DATA_STREAM)
-               nob = 0xffff;
-
-       host->data = data;
-       data->bytes_xfered = 0;
-
-       MMC_NOB = nob;
-       MMC_BLK_LEN = blksz;
-
-       /*
-        * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise.
-        * We are in big troubles for non-512 byte transfers according to note in the paragraph
-        * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least.
-        * The situation is even more complex in reality. The SDHC in not able to handle wll
-        * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
-        * This is required for SCR read at least.
-        */
-       if (datasz < 512) {
-               host->dma_size = datasz;
-               if (data->flags & MMC_DATA_READ) {
-                       host->dma_dir = DMA_FROM_DEVICE;
-
-                       /* Hack to enable read SCR */
-                       MMC_NOB = 1;
-                       MMC_BLK_LEN = 512;
-               } else {
-                       host->dma_dir = DMA_TO_DEVICE;
-               }
-
-               /* Convert back to virtual address */
-               host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
-               host->data_cnt = 0;
-
-               clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
-               set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
-
-               return;
-       }
-
-       if (data->flags & MMC_DATA_READ) {
-               host->dma_dir = DMA_FROM_DEVICE;
-               host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                                               data->sg_len,  host->dma_dir);
-
-               imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
-                       host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ);
-
-               /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/
-               CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN;
-       } else {
-               host->dma_dir = DMA_TO_DEVICE;
-
-               host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                                               data->sg_len,  host->dma_dir);
-
-               imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
-                       host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE);
-
-               /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/
-               CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN;
-       }
-
-#if 1  /* This code is there only for consistency checking and can be disabled in future */
-       host->dma_size = 0;
-       for(i=0; i<host->dma_nents; i++)
-               host->dma_size+=data->sg[i].length;
-
-       if (datasz > host->dma_size) {
-               dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n",
-                      datasz, host->dma_size);
-       }
-#endif
-
-       host->dma_size = datasz;
-
-       wmb();
-
-       if(host->actual_bus_width == MMC_BUS_WIDTH_4)
-               BLR(host->dma) = 0;     /* burst 64 byte read / 64 bytes write */
-       else
-               BLR(host->dma) = 16;    /* burst 16 byte read / 16 bytes write */
-
-       RSSR(host->dma) = DMA_REQ_SDHC;
-
-       set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
-       clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
-
-       /* start DMA engine for read, write is delayed after initial response */
-       if (host->dma_dir == DMA_FROM_DEVICE) {
-               imx_dma_enable(host->dma);
-       }
-}
-
-static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
-{
-       unsigned long flags;
-       u32 imask;
-
-       WARN_ON(host->cmd != NULL);
-       host->cmd = cmd;
-
-       /* Ensure, that clock are stopped else command programming and start fails */
-       imxmci_stop_clock(host);
-
-       if (cmd->flags & MMC_RSP_BUSY)
-               cmdat |= CMD_DAT_CONT_BUSY;
-
-       switch (mmc_resp_type(cmd)) {
-       case MMC_RSP_R1: /* short CRC, OPCODE */
-       case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
-               cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
-               break;
-       case MMC_RSP_R2: /* long 136 bit + CRC */
-               cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
-               break;
-       case MMC_RSP_R3: /* short */
-               cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
-               break;
-       default:
-               break;
-       }
-
-       if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
-               cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */
-
-       if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
-               cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
-
-       MMC_CMD = cmd->opcode;
-       MMC_ARGH = cmd->arg >> 16;
-       MMC_ARGL = cmd->arg & 0xffff;
-       MMC_CMD_DAT_CONT = cmdat;
-
-       atomic_set(&host->stuck_timeout, 0);
-       set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);
-
-
-       imask = IMXMCI_INT_MASK_DEFAULT;
-       imask &= ~INT_MASK_END_CMD_RES;
-       if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
-               /*imask &= ~INT_MASK_BUF_READY;*/
-               imask &= ~INT_MASK_DATA_TRAN;
-               if ( cmdat & CMD_DAT_CONT_WRITE )
-                       imask &= ~INT_MASK_WRITE_OP_DONE;
-               if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
-                       imask &= ~INT_MASK_BUF_READY;
-       }
-
-       spin_lock_irqsave(&host->lock, flags);
-       host->imask = imask;
-       MMC_INT_MASK = host->imask;
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
-               cmd->opcode, cmd->opcode, imask);
-
-       imxmci_start_clock(host);
-}
-
-static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m |
-                       IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m);
-
-       host->imask = IMXMCI_INT_MASK_DEFAULT;
-       MMC_INT_MASK = host->imask;
-
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       if(req && req->cmd)
-               host->prev_cmd_code = req->cmd->opcode;
-
-       host->req = NULL;
-       host->cmd = NULL;
-       host->data = NULL;
-       mmc_request_done(host->mmc, req);
-}
-
-static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat)
-{
-       struct mmc_data *data = host->data;
-       int data_error;
-
-       if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){
-               imx_dma_disable(host->dma);
-               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
-                            host->dma_dir);
-       }
-
-       if ( stat & STATUS_ERR_MASK ) {
-               dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat);
-               if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR))
-                       data->error = MMC_ERR_BADCRC;
-               else if(stat & STATUS_TIME_OUT_READ)
-                       data->error = MMC_ERR_TIMEOUT;
-               else
-                       data->error = MMC_ERR_FAILED;
-       } else {
-               data->bytes_xfered = host->dma_size;
-       }
-
-       data_error = data->error;
-
-       host->data = NULL;
-
-       return data_error;
-}
-
-static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat)
-{
-       struct mmc_command *cmd = host->cmd;
-       int i;
-       u32 a,b,c;
-       struct mmc_data *data = host->data;
-
-       if (!cmd)
-               return 0;
-
-       host->cmd = NULL;
-
-       if (stat & STATUS_TIME_OUT_RESP) {
-               dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
-               cmd->error = MMC_ERR_TIMEOUT;
-       } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
-               dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
-               cmd->error = MMC_ERR_BADCRC;
-       }
-
-       if(cmd->flags & MMC_RSP_PRESENT) {
-               if(cmd->flags & MMC_RSP_136) {
-                       for (i = 0; i < 4; i++) {
-                               u32 a = MMC_RES_FIFO & 0xffff;
-                               u32 b = MMC_RES_FIFO & 0xffff;
-                               cmd->resp[i] = a<<16 | b;
-                       }
-               } else {
-                       a = MMC_RES_FIFO & 0xffff;
-                       b = MMC_RES_FIFO & 0xffff;
-                       c = MMC_RES_FIFO & 0xffff;
-                       cmd->resp[0] = a<<24 | b<<8 | c>>8;
-               }
-       }
-
-       dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n",
-               cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
-
-       if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) {
-               if (host->req->data->flags & MMC_DATA_WRITE) {
-
-                       /* Wait for FIFO to be empty before starting DMA write */
-
-                       stat = MMC_STATUS;
-                       if(imxmci_busy_wait_for_status(host, &stat,
-                               STATUS_APPL_BUFF_FE,
-                               40, "imxmci_cmd_done DMA WR") < 0) {
-                               cmd->error = MMC_ERR_FIFO;
-                               imxmci_finish_data(host, stat);
-                               if(host->req)
-                                       imxmci_finish_request(host, host->req);
-                               dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n",
-                                      stat);
-                               return 0;
-                       }
-
-                       if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
-                               imx_dma_enable(host->dma);
-                       }
-               }
-       } else {
-               struct mmc_request *req;
-               imxmci_stop_clock(host);
-               req = host->req;
-
-               if(data)
-                       imxmci_finish_data(host, stat);
-
-               if( req ) {
-                       imxmci_finish_request(host, req);
-               } else {
-                       dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n");
-               }
-       }
-
-       return 1;
-}
-
-static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
-{
-       struct mmc_data *data = host->data;
-       int data_error;
-
-       if (!data)
-               return 0;
-
-       data_error = imxmci_finish_data(host, stat);
-
-       if (host->req->stop) {
-               imxmci_stop_clock(host);
-               imxmci_start_cmd(host, host->req->stop, 0);
-       } else {
-               struct mmc_request *req;
-               req = host->req;
-               if( req ) {
-                       imxmci_finish_request(host, req);
-               } else {
-                       dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n");
-               }
-       }
-
-       return 1;
-}
-
-static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
-{
-       int i;
-       int burst_len;
-       int trans_done = 0;
-       unsigned int stat = *pstat;
-
-       if(host->actual_bus_width != MMC_BUS_WIDTH_4)
-               burst_len = 16;
-       else
-               burst_len = 64;
-
-       /* This is unfortunately required */
-       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
-               stat);
-
-       udelay(20);     /* required for clocks < 8MHz*/
-
-       if(host->dma_dir == DMA_FROM_DEVICE) {
-               imxmci_busy_wait_for_status(host, &stat,
-                               STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE |
-                               STATUS_TIME_OUT_READ,
-                               50, "imxmci_cpu_driven_data read");
-
-               while((stat & (STATUS_APPL_BUFF_FF |  STATUS_DATA_TRANS_DONE)) &&
-                     !(stat & STATUS_TIME_OUT_READ) &&
-                     (host->data_cnt < 512)) {
-
-                       udelay(20);     /* required for clocks < 8MHz*/
-
-                       for(i = burst_len; i>=2 ; i-=2) {
-                               u16 data;
-                               data = MMC_BUFFER_ACCESS;
-                               udelay(10);     /* required for clocks < 8MHz*/
-                               if(host->data_cnt+2 <= host->dma_size) {
-                                       *(host->data_ptr++) = data;
-                               } else {
-                                       if(host->data_cnt < host->dma_size)
-                                               *(u8*)(host->data_ptr) = data;
-                               }
-                               host->data_cnt += 2;
-                       }
-
-                       stat = MMC_STATUS;
-
-                       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n",
-                               host->data_cnt, burst_len, stat);
-               }
-
-               if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512))
-                       trans_done = 1;
-
-               if(host->dma_size & 0x1ff)
-                       stat &= ~STATUS_CRC_READ_ERR;
-
-               if(stat & STATUS_TIME_OUT_READ) {
-                       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read timeout STATUS = 0x%x\n",
-                               stat);
-                       trans_done = -1;
-               }
-
-       } else {
-               imxmci_busy_wait_for_status(host, &stat,
-                               STATUS_APPL_BUFF_FE,
-                               20, "imxmci_cpu_driven_data write");
-
-               while((stat & STATUS_APPL_BUFF_FE) &&
-                     (host->data_cnt < host->dma_size)) {
-                       if(burst_len >= host->dma_size - host->data_cnt) {
-                               burst_len = host->dma_size - host->data_cnt;
-                               host->data_cnt = host->dma_size;
-                               trans_done = 1;
-                       } else {
-                               host->data_cnt += burst_len;
-                       }
-
-                       for(i = burst_len; i>0 ; i-=2)
-                               MMC_BUFFER_ACCESS = *(host->data_ptr++);
-
-                       stat = MMC_STATUS;
-
-                       dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n",
-                               burst_len, stat);
-               }
-       }
-
-       *pstat = stat;
-
-       return trans_done;
-}
-
-static void imxmci_dma_irq(int dma, void *devid)
-{
-       struct imxmci_host *host = devid;
-       uint32_t stat = MMC_STATUS;
-
-       atomic_set(&host->stuck_timeout, 0);
-       host->status_reg = stat;
-       set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
-       tasklet_schedule(&host->tasklet);
-}
-
-static irqreturn_t imxmci_irq(int irq, void *devid)
-{
-       struct imxmci_host *host = devid;
-       uint32_t stat = MMC_STATUS;
-       int handled = 1;
-
-       MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT;
-
-       atomic_set(&host->stuck_timeout, 0);
-       host->status_reg = stat;
-       set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
-       set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
-       tasklet_schedule(&host->tasklet);
-
-       return IRQ_RETVAL(handled);;
-}
-
-static void imxmci_tasklet_fnc(unsigned long data)
-{
-       struct imxmci_host *host = (struct imxmci_host *)data;
-       u32 stat;
-       unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */
-       int timeout = 0;
-
-       if(atomic_read(&host->stuck_timeout) > 4) {
-               char *what;
-               timeout = 1;
-               stat = MMC_STATUS;
-               host->status_reg = stat;
-               if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
-                       if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
-                               what = "RESP+DMA";
-                       else
-                               what = "RESP";
-               else
-                       if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
-                               if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
-                                       what = "DATA";
-                               else
-                                       what = "DMA";
-                       else
-                               what = "???";
-
-               dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
-                      what, stat, MMC_INT_MASK);
-               dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
-                      MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
-               dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n",
-                      host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size);
-       }
-
-       if(!host->present || timeout)
-               host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
-                                   STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;
-
-       if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
-               clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
-
-               stat = MMC_STATUS;
-               /*
-                * This is not required in theory, but there is chance to miss some flag
-                * which clears automatically by mask write, FreeScale original code keeps
-                * stat from IRQ time so do I
-                */
-               stat |= host->status_reg;
-
-               if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
-                       stat &= ~STATUS_CRC_READ_ERR;
-
-               if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
-                       imxmci_busy_wait_for_status(host, &stat,
-                                       STATUS_END_CMD_RESP | STATUS_ERR_MASK,
-                                       20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
-               }
-
-               if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
-                       if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
-                               imxmci_cmd_done(host, stat);
-                       if(host->data && (stat & STATUS_ERR_MASK))
-                               imxmci_data_done(host, stat);
-               }
-
-               if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
-                       stat |= MMC_STATUS;
-                       if(imxmci_cpu_driven_data(host, &stat)){
-                               if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
-                                       imxmci_cmd_done(host, stat);
-                               atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
-                                                       &host->pending_events);
-                               imxmci_data_done(host, stat);
-                       }
-               }
-       }
-
-       if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
-          !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
-
-               stat = MMC_STATUS;
-               /* Same as above */
-               stat |= host->status_reg;
-
-               if(host->dma_dir == DMA_TO_DEVICE) {
-                       data_dir_mask = STATUS_WRITE_OP_DONE;
-               } else {
-                       data_dir_mask = STATUS_DATA_TRANS_DONE;
-               }
-
-               if(stat & data_dir_mask) {
-                       clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
-                       imxmci_data_done(host, stat);
-               }
-       }
-
-       if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {
-
-               if(host->cmd)
-                       imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);
-
-               if(host->data)
-                       imxmci_data_done(host, STATUS_TIME_OUT_READ |
-                                        STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);
-
-               if(host->req)
-                       imxmci_finish_request(host, host->req);
-
-               mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-
-       }
-}
-
-static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req)
-{
-       struct imxmci_host *host = mmc_priv(mmc);
-       unsigned int cmdat;
-
-       WARN_ON(host->req != NULL);
-
-       host->req = req;
-
-       cmdat = 0;
-
-       if (req->data) {
-               imxmci_setup_data(host, req->data);
-
-               cmdat |= CMD_DAT_CONT_DATA_ENABLE;
-
-               if (req->data->flags & MMC_DATA_WRITE)
-                       cmdat |= CMD_DAT_CONT_WRITE;
-
-               if (req->data->flags & MMC_DATA_STREAM) {
-                       cmdat |= CMD_DAT_CONT_STREAM_BLOCK;
-               }
-       }
-
-       imxmci_start_cmd(host, req->cmd, cmdat);
-}
-
-#define CLK_RATE 19200000
-
-static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct imxmci_host *host = mmc_priv(mmc);
-       int prescaler;
-
-       if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
-               host->actual_bus_width = MMC_BUS_WIDTH_4;
-               imx_gpio_mode(PB11_PF_SD_DAT3);
-       }else{
-               host->actual_bus_width = MMC_BUS_WIDTH_1;
-               imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
-       }
-
-       if ( host->power_mode != ios->power_mode ) {
-               switch (ios->power_mode) {
-               case MMC_POWER_OFF:
-                       break;
-               case MMC_POWER_UP:
-                       set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
-                       break;
-               case MMC_POWER_ON:
-                       break;
-               }
-               host->power_mode = ios->power_mode;
-       }
-
-       if ( ios->clock ) {
-               unsigned int clk;
-
-               /* The prescaler is 5 for PERCLK2 equal to 96MHz
-                * then 96MHz / 5 = 19.2 MHz
-                */
-               clk=imx_get_perclk2();
-               prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE;
-               switch(prescaler) {
-               case 0:
-               case 1: prescaler = 0;
-                       break;
-               case 2: prescaler = 1;
-                       break;
-               case 3: prescaler = 2;
-                       break;
-               case 4: prescaler = 4;
-                       break;
-               default:
-               case 5: prescaler = 5;
-                       break;
-               }
-
-               dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n",
-                       clk, prescaler);
-
-               for(clk=0; clk<8; clk++) {
-                       int x;
-                       x = CLK_RATE / (1<<clk);
-                       if( x <= ios->clock)
-                               break;
-               }
-
-               MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */
-
-               imxmci_stop_clock(host);
-               MMC_CLK_RATE = (prescaler<<3) | clk;
-               /*
-                * Under my understanding, clock should not be started there, because it would
-                * initiate SDHC sequencer and send last or random command into card
-                */
-               /*imxmci_start_clock(host);*/
-
-               dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
-       } else {
-               imxmci_stop_clock(host);
-       }
-}
-
-static const struct mmc_host_ops imxmci_ops = {
-       .request        = imxmci_request,
-       .set_ios        = imxmci_set_ios,
-};
-
-static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
-{
-       int i;
-
-       for (i = 0; i < dev->num_resources; i++)
-               if (dev->resource[i].flags == mask && nr-- == 0)
-                       return &dev->resource[i];
-       return NULL;
-}
-
-static int platform_device_irq(struct platform_device *dev, int nr)
-{
-       int i;
-
-       for (i = 0; i < dev->num_resources; i++)
-               if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
-                       return dev->resource[i].start;
-       return NO_IRQ;
-}
-
-static void imxmci_check_status(unsigned long data)
-{
-       struct imxmci_host *host = (struct imxmci_host *)data;
-
-       if( host->pdata->card_present() != host->present ) {
-               host->present ^= 1;
-               dev_info(mmc_dev(host->mmc), "card %s\n",
-                     host->present ? "inserted" : "removed");
-
-               set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events);
-               tasklet_schedule(&host->tasklet);
-       }
-
-       if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) ||
-          test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
-               atomic_inc(&host->stuck_timeout);
-               if(atomic_read(&host->stuck_timeout) > 4)
-                       tasklet_schedule(&host->tasklet);
-       } else {
-               atomic_set(&host->stuck_timeout, 0);
-
-       }
-
-       mod_timer(&host->timer, jiffies + (HZ>>1));
-}
-
-static int imxmci_probe(struct platform_device *pdev)
-{
-       struct mmc_host *mmc;
-       struct imxmci_host *host = NULL;
-       struct resource *r;
-       int ret = 0, irq;
-
-       printk(KERN_INFO "i.MX mmc driver\n");
-
-       r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
-       irq = platform_device_irq(pdev, 0);
-       if (!r || irq == NO_IRQ)
-               return -ENXIO;
-
-       r = request_mem_region(r->start, 0x100, "IMXMCI");
-       if (!r)
-               return -EBUSY;
-
-       mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
-       if (!mmc) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       mmc->ops = &imxmci_ops;
-       mmc->f_min = 150000;
-       mmc->f_max = CLK_RATE/2;
-       mmc->ocr_avail = MMC_VDD_32_33;
-       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_BYTEBLOCK;
-
-       /* MMC core transfer sizes tunable parameters */
-       mmc->max_hw_segs = 64;
-       mmc->max_phys_segs = 64;
-       mmc->max_seg_size = 64*512;     /* default PAGE_CACHE_SIZE */
-       mmc->max_req_size = 64*512;     /* default PAGE_CACHE_SIZE */
-       mmc->max_blk_size = 2048;
-       mmc->max_blk_count = 65535;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-       host->dma_allocated = 0;
-       host->pdata = pdev->dev.platform_data;
-
-       spin_lock_init(&host->lock);
-       host->res = r;
-       host->irq = irq;
-
-       imx_gpio_mode(PB8_PF_SD_DAT0);
-       imx_gpio_mode(PB9_PF_SD_DAT1);
-       imx_gpio_mode(PB10_PF_SD_DAT2);
-       /* Configured as GPIO with pull-up to ensure right MCC card mode */
-       /* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */
-       imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
-       /* imx_gpio_mode(PB11_PF_SD_DAT3); */
-       imx_gpio_mode(PB12_PF_SD_CLK);
-       imx_gpio_mode(PB13_PF_SD_CMD);
-
-       imxmci_softreset();
-
-       if ( MMC_REV_NO != 0x390 ) {
-               dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
-                       MMC_REV_NO);
-               goto out;
-       }
-
-       MMC_READ_TO = 0x2db4; /* recommended in data sheet */
-
-       host->imask = IMXMCI_INT_MASK_DEFAULT;
-       MMC_INT_MASK = host->imask;
-
-
-       if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){
-               dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
-               ret = -EBUSY;
-               goto out;
-       }
-       host->dma_allocated=1;
-       imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
-
-       tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
-       host->status_reg=0;
-       host->pending_events=0;
-
-       ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host);
-       if (ret)
-               goto out;
-
-       host->present = host->pdata->card_present();
-       init_timer(&host->timer);
-       host->timer.data = (unsigned long)host;
-       host->timer.function = imxmci_check_status;
-       add_timer(&host->timer);
-       mod_timer(&host->timer, jiffies + (HZ>>1));
-
-       platform_set_drvdata(pdev, mmc);
-
-       mmc_add_host(mmc);
-
-       return 0;
-
-out:
-       if (host) {
-               if(host->dma_allocated){
-                       imx_dma_free(host->dma);
-                       host->dma_allocated=0;
-               }
-       }
-       if (mmc)
-               mmc_free_host(mmc);
-       release_resource(r);
-       return ret;
-}
-
-static int imxmci_remove(struct platform_device *pdev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-
-       platform_set_drvdata(pdev, NULL);
-
-       if (mmc) {
-               struct imxmci_host *host = mmc_priv(mmc);
-
-               tasklet_disable(&host->tasklet);
-
-               del_timer_sync(&host->timer);
-               mmc_remove_host(mmc);
-
-               free_irq(host->irq, host);
-               if(host->dma_allocated){
-                       imx_dma_free(host->dma);
-                       host->dma_allocated=0;
-               }
-
-               tasklet_kill(&host->tasklet);
-
-               release_resource(host->res);
-
-               mmc_free_host(mmc);
-       }
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-       int ret = 0;
-
-       if (mmc)
-               ret = mmc_suspend_host(mmc, state);
-
-       return ret;
-}
-
-static int imxmci_resume(struct platform_device *dev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-       struct imxmci_host *host;
-       int ret = 0;
-
-       if (mmc) {
-               host = mmc_priv(mmc);
-               if(host)
-                       set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
-               ret = mmc_resume_host(mmc);
-       }
-
-       return ret;
-}
-#else
-#define imxmci_suspend  NULL
-#define imxmci_resume   NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver imxmci_driver = {
-       .probe          = imxmci_probe,
-       .remove         = imxmci_remove,
-       .suspend        = imxmci_suspend,
-       .resume         = imxmci_resume,
-       .driver         = {
-               .name           = DRIVER_NAME,
-       }
-};
-
-static int __init imxmci_init(void)
-{
-       return platform_driver_register(&imxmci_driver);
-}
-
-static void __exit imxmci_exit(void)
-{
-       platform_driver_unregister(&imxmci_driver);
-}
-
-module_init(imxmci_init);
-module_exit(imxmci_exit);
-
-MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/imxmmc.h
deleted file mode 100644 (file)
index e5339e3..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-
-# define __REG16(x)    (*((volatile u16 *)IO_ADDRESS(x)))
-
-#define MMC_STR_STP_CLK  __REG16(IMX_MMC_BASE + 0x00)
-#define MMC_STATUS       __REG16(IMX_MMC_BASE + 0x04)
-#define MMC_CLK_RATE     __REG16(IMX_MMC_BASE + 0x08)
-#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C)
-#define MMC_RES_TO       __REG16(IMX_MMC_BASE + 0x10)
-#define MMC_READ_TO      __REG16(IMX_MMC_BASE + 0x14)
-#define MMC_BLK_LEN      __REG16(IMX_MMC_BASE + 0x18)
-#define MMC_NOB          __REG16(IMX_MMC_BASE + 0x1C)
-#define MMC_REV_NO       __REG16(IMX_MMC_BASE + 0x20)
-#define MMC_INT_MASK     __REG16(IMX_MMC_BASE + 0x24)
-#define MMC_CMD          __REG16(IMX_MMC_BASE + 0x28)
-#define MMC_ARGH         __REG16(IMX_MMC_BASE + 0x2C)
-#define MMC_ARGL         __REG16(IMX_MMC_BASE + 0x30)
-#define MMC_RES_FIFO     __REG16(IMX_MMC_BASE + 0x34)
-#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38)
-#define MMC_BUFFER_ACCESS_OFS 0x38
-
-
-#define STR_STP_CLK_ENDIAN              (1<<5)
-#define STR_STP_CLK_RESET               (1<<3)
-#define STR_STP_CLK_ENABLE              (1<<2)
-#define STR_STP_CLK_START_CLK           (1<<1)
-#define STR_STP_CLK_STOP_CLK            (1<<0)
-#define STATUS_CARD_PRESENCE            (1<<15)
-#define STATUS_SDIO_INT_ACTIVE          (1<<14)
-#define STATUS_END_CMD_RESP             (1<<13)
-#define STATUS_WRITE_OP_DONE            (1<<12)
-#define STATUS_DATA_TRANS_DONE          (1<<11)
-#define STATUS_WR_CRC_ERROR_CODE_MASK   (3<<10)
-#define STATUS_CARD_BUS_CLK_RUN         (1<<8)
-#define STATUS_APPL_BUFF_FF             (1<<7)
-#define STATUS_APPL_BUFF_FE             (1<<6)
-#define STATUS_RESP_CRC_ERR             (1<<5)
-#define STATUS_CRC_READ_ERR             (1<<3)
-#define STATUS_CRC_WRITE_ERR            (1<<2)
-#define STATUS_TIME_OUT_RESP            (1<<1)
-#define STATUS_TIME_OUT_READ            (1<<0)
-#define STATUS_ERR_MASK                 0x2f
-#define CLK_RATE_PRESCALER(x)           ((x) & 0x7)
-#define CLK_RATE_CLK_RATE(x)            (((x) & 0x7) << 3)
-#define CMD_DAT_CONT_CMD_RESP_LONG_OFF  (1<<12)
-#define CMD_DAT_CONT_STOP_READWAIT      (1<<11)
-#define CMD_DAT_CONT_START_READWAIT     (1<<10)
-#define CMD_DAT_CONT_BUS_WIDTH_1        (0<<8)
-#define CMD_DAT_CONT_BUS_WIDTH_4        (2<<8)
-#define CMD_DAT_CONT_INIT               (1<<7)
-#define CMD_DAT_CONT_BUSY               (1<<6)
-#define CMD_DAT_CONT_STREAM_BLOCK       (1<<5)
-#define CMD_DAT_CONT_WRITE              (1<<4)
-#define CMD_DAT_CONT_DATA_ENABLE        (1<<3)
-#define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1)
-#define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2)
-#define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3)
-#define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4)
-#define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5)
-#define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6)
-#define INT_MASK_AUTO_CARD_DETECT       (1<<6)
-#define INT_MASK_DAT0_EN                (1<<5)
-#define INT_MASK_SDIO                   (1<<4)
-#define INT_MASK_BUF_READY              (1<<3)
-#define INT_MASK_END_CMD_RES            (1<<2)
-#define INT_MASK_WRITE_OP_DONE          (1<<1)
-#define INT_MASK_DATA_TRAN              (1<<0)
-#define INT_ALL                         (0x7f)
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/mmc.h b/drivers/mmc/mmc.h
deleted file mode 100644 (file)
index 149affe..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  linux/drivers/mmc/mmc.h
- *
- *  Copyright (C) 2003 Russell King, 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.
- */
-#ifndef _MMC_H
-#define _MMC_H
-/* core-internal functions */
-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);
-
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
-int mmc_add_host_sysfs(struct mmc_host *host);
-void mmc_remove_host_sysfs(struct mmc_host *host);
-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/mmc_block.c b/drivers/mmc/mmc_block.c
deleted file mode 100644 (file)
index 86439a0..0000000
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * Block driver for media (i.e., flash cards)
- *
- * 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!
- *
- * Author:  Andrew Christian
- *          28 May 2002
- */
-#include <linux/moduleparam.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/kdev_t.h>
-#include <linux/blkdev.h>
-#include <linux/mutex.h>
-#include <linux/scatterlist.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "mmc_queue.h"
-
-/*
- * max 8 partitions per card
- */
-#define MMC_SHIFT      3
-
-static int major;
-
-/*
- * There is one mmc_blk_data per slot.
- */
-struct mmc_blk_data {
-       spinlock_t      lock;
-       struct gendisk  *disk;
-       struct mmc_queue queue;
-
-       unsigned int    usage;
-       unsigned int    block_bits;
-       unsigned int    read_only;
-};
-
-static DEFINE_MUTEX(open_lock);
-
-static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
-{
-       struct mmc_blk_data *md;
-
-       mutex_lock(&open_lock);
-       md = disk->private_data;
-       if (md && md->usage == 0)
-               md = NULL;
-       if (md)
-               md->usage++;
-       mutex_unlock(&open_lock);
-
-       return md;
-}
-
-static void mmc_blk_put(struct mmc_blk_data *md)
-{
-       mutex_lock(&open_lock);
-       md->usage--;
-       if (md->usage == 0) {
-               put_disk(md->disk);
-               kfree(md);
-       }
-       mutex_unlock(&open_lock);
-}
-
-static int mmc_blk_open(struct inode *inode, struct file *filp)
-{
-       struct mmc_blk_data *md;
-       int ret = -ENXIO;
-
-       md = mmc_blk_get(inode->i_bdev->bd_disk);
-       if (md) {
-               if (md->usage == 2)
-                       check_disk_change(inode->i_bdev);
-               ret = 0;
-
-               if ((filp->f_mode & FMODE_WRITE) && md->read_only)
-                       ret = -EROFS;
-       }
-
-       return ret;
-}
-
-static int mmc_blk_release(struct inode *inode, struct file *filp)
-{
-       struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data;
-
-       mmc_blk_put(md);
-       return 0;
-}
-
-static int
-mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
-       geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
-       geo->heads = 4;
-       geo->sectors = 16;
-       return 0;
-}
-
-static struct block_device_operations mmc_bdops = {
-       .open                   = mmc_blk_open,
-       .release                = mmc_blk_release,
-       .getgeo                 = mmc_blk_getgeo,
-       .owner                  = THIS_MODULE,
-};
-
-struct mmc_blk_request {
-       struct mmc_request      mrq;
-       struct mmc_command      cmd;
-       struct mmc_command      stop;
-       struct mmc_data         data;
-};
-
-static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
-{
-       struct mmc_blk_data *md = mq->data;
-       int stat = BLKPREP_OK;
-
-       /*
-        * If we have no device, we haven't finished initialising.
-        */
-       if (!md || !mq->card) {
-               printk(KERN_ERR "%s: killing request - no device/host\n",
-                      req->rq_disk->disk_name);
-               stat = BLKPREP_KILL;
-       }
-
-       return stat;
-}
-
-static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
-{
-       int err;
-       u32 blocks;
-
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
-       unsigned int timeout_us;
-
-       struct scatterlist sg;
-
-       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(card->host, &cmd, 0);
-       if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD))
-               return (u32)-1;
-
-       memset(&cmd, 0, sizeof(struct mmc_command));
-
-       cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-       memset(&data, 0, sizeof(struct mmc_data));
-
-       data.timeout_ns = card->csd.tacc_ns * 100;
-       data.timeout_clks = card->csd.tacc_clks * 100;
-
-       timeout_us = data.timeout_ns / 1000;
-       timeout_us += data.timeout_clks * 1000 /
-               (card->host->ios.clock / 1000);
-
-       if (timeout_us > 100000) {
-               data.timeout_ns = 100000000;
-               data.timeout_clks = 0;
-       }
-
-       data.blksz = 4;
-       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, &blocks, 4);
-
-       mmc_wait_for_req(card->host, &mrq);
-
-       if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE)
-               return (u32)-1;
-
-       blocks = ntohl(blocks);
-
-       return blocks;
-}
-
-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;
-
-       if (mmc_card_claim_host(card))
-               goto flush_queue;
-
-       do {
-               struct mmc_command cmd;
-               u32 readcmd, writecmd;
-
-               memset(&brq, 0, sizeof(struct mmc_blk_request));
-               brq.mrq.cmd = &brq.cmd;
-               brq.mrq.data = &brq.data;
-
-               brq.cmd.arg = req->sector;
-               if (!mmc_card_blockaddr(card))
-                       brq.cmd.arg <<= 9;
-               brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-               brq.data.blksz = 1 << md->block_bits;
-               brq.stop.opcode = MMC_STOP_TRANSMISSION;
-               brq.stop.arg = 0;
-               brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
-               brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
-               if (brq.data.blocks > card->host->max_blk_count)
-                       brq.data.blocks = card->host->max_blk_count;
-
-               mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
-
-               /*
-                * If the host doesn't support multiple block writes, force
-                * block writes to single block. SD cards are excepted from
-                * this rule as they support querying the number of
-                * successfully written sectors.
-                */
-               if (rq_data_dir(req) != READ &&
-                   !(card->host->caps & MMC_CAP_MULTIWRITE) &&
-                   !mmc_card_sd(card))
-                       brq.data.blocks = 1;
-
-               if (brq.data.blocks > 1) {
-                       brq.data.flags |= MMC_DATA_MULTI;
-                       brq.mrq.stop = &brq.stop;
-                       readcmd = MMC_READ_MULTIPLE_BLOCK;
-                       writecmd = MMC_WRITE_MULTIPLE_BLOCK;
-               } else {
-                       brq.mrq.stop = NULL;
-                       readcmd = MMC_READ_SINGLE_BLOCK;
-                       writecmd = MMC_WRITE_BLOCK;
-               }
-
-               if (rq_data_dir(req) == READ) {
-                       brq.cmd.opcode = readcmd;
-                       brq.data.flags |= MMC_DATA_READ;
-               } else {
-                       brq.cmd.opcode = writecmd;
-                       brq.data.flags |= MMC_DATA_WRITE;
-               }
-
-               brq.data.sg = mq->sg;
-               brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
-
-               mmc_wait_for_req(card->host, &brq.mrq);
-               if (brq.cmd.error) {
-                       printk(KERN_ERR "%s: error %d sending read/write command\n",
-                              req->rq_disk->disk_name, brq.cmd.error);
-                       goto cmd_err;
-               }
-
-               if (brq.data.error) {
-                       printk(KERN_ERR "%s: error %d transferring data\n",
-                              req->rq_disk->disk_name, brq.data.error);
-                       goto cmd_err;
-               }
-
-               if (brq.stop.error) {
-                       printk(KERN_ERR "%s: error %d sending stop command\n",
-                              req->rq_disk->disk_name, brq.stop.error);
-                       goto cmd_err;
-               }
-
-               if (rq_data_dir(req) != READ) {
-                       do {
-                               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(card->host, &cmd, 5);
-                               if (err) {
-                                       printk(KERN_ERR "%s: error %d requesting status\n",
-                                              req->rq_disk->disk_name, err);
-                                       goto cmd_err;
-                               }
-                       } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
-
-#if 0
-                       if (cmd.resp[0] & ~0x00000900)
-                               printk(KERN_ERR "%s: status = %08x\n",
-                                      req->rq_disk->disk_name, cmd.resp[0]);
-                       if (mmc_decode_status(cmd.resp))
-                               goto cmd_err;
-#endif
-               }
-
-               /*
-                * A block was successfully transferred.
-                */
-               spin_lock_irq(&md->lock);
-               ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
-               if (!ret) {
-                       /*
-                        * The whole request completed successfully.
-                        */
-                       add_disk_randomness(req->rq_disk);
-                       blkdev_dequeue_request(req);
-                       end_that_request_last(req, 1);
-               }
-               spin_unlock_irq(&md->lock);
-       } while (ret);
-
-       mmc_card_release_host(card);
-
-       return 1;
-
- cmd_err:
-       /*
-        * If this is an SD card and we're writing, we can first
-        * mark the known good sectors as ok.
-        *
-        * If the card is not SD, we can still ok written sectors
-        * if the controller can do proper error reporting.
-        *
-        * For reads we just fail the entire chunk as that should
-        * be safe in all cases.
-        */
-       if (rq_data_dir(req) != READ && mmc_card_sd(card)) {
-               u32 blocks;
-               unsigned int bytes;
-
-               blocks = mmc_sd_num_wr_blocks(card);
-               if (blocks != (u32)-1) {
-                       if (card->csd.write_partial)
-                               bytes = blocks << md->block_bits;
-                       else
-                               bytes = blocks << 9;
-                       spin_lock_irq(&md->lock);
-                       ret = end_that_request_chunk(req, 1, bytes);
-                       spin_unlock_irq(&md->lock);
-               }
-       } else if (rq_data_dir(req) != READ &&
-                  (card->host->caps & MMC_CAP_MULTIWRITE)) {
-               spin_lock_irq(&md->lock);
-               ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
-               spin_unlock_irq(&md->lock);
-       }
-
-flush_queue:
-
-       mmc_card_release_host(card);
-
-       spin_lock_irq(&md->lock);
-       while (ret) {
-               ret = end_that_request_chunk(req, 0,
-                               req->current_nr_sectors << 9);
-       }
-
-       add_disk_randomness(req->rq_disk);
-       blkdev_dequeue_request(req);
-       end_that_request_last(req, 0);
-       spin_unlock_irq(&md->lock);
-
-       return 0;
-}
-
-#define MMC_NUM_MINORS (256 >> MMC_SHIFT)
-
-static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
-
-static inline int mmc_blk_readonly(struct mmc_card *card)
-{
-       return mmc_card_readonly(card) ||
-              !(card->csd.cmdclass & CCC_BLOCK_WRITE);
-}
-
-static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
-{
-       struct mmc_blk_data *md;
-       int devidx, ret;
-
-       devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);
-       if (devidx >= MMC_NUM_MINORS)
-               return ERR_PTR(-ENOSPC);
-       __set_bit(devidx, dev_use);
-
-       md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
-       if (!md) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memset(md, 0, sizeof(struct mmc_blk_data));
-
-       /*
-        * Set the read-only status based on the supported commands
-        * and the write protect switch.
-        */
-       md->read_only = mmc_blk_readonly(card);
-
-       /*
-        * Both SD and MMC specifications state (although a bit
-        * unclearly in the MMC case) that a block size of 512
-        * bytes must always be supported by the card.
-        */
-       md->block_bits = 9;
-
-       md->disk = alloc_disk(1 << MMC_SHIFT);
-       if (md->disk == NULL) {
-               ret = -ENOMEM;
-               goto err_kfree;
-       }
-
-       spin_lock_init(&md->lock);
-       md->usage = 1;
-
-       ret = mmc_init_queue(&md->queue, card, &md->lock);
-       if (ret)
-               goto err_putdisk;
-
-       md->queue.prep_fn = mmc_blk_prep_rq;
-       md->queue.issue_fn = mmc_blk_issue_rq;
-       md->queue.data = md;
-
-       md->disk->major = major;
-       md->disk->first_minor = devidx << MMC_SHIFT;
-       md->disk->fops = &mmc_bdops;
-       md->disk->private_data = md;
-       md->disk->queue = md->queue.queue;
-       md->disk->driverfs_dev = &card->dev;
-
-       /*
-        * As discussed on lkml, GENHD_FL_REMOVABLE should:
-        *
-        * - be set for removable media with permanent block devices
-        * - be unset for removable block devices with permanent media
-        *
-        * Since MMC block devices clearly fall under the second
-        * case, we do not set GENHD_FL_REMOVABLE.  Userspace
-        * should use the block device creation/destruction hotplug
-        * messages to tell when the card is present.
-        */
-
-       sprintf(md->disk->disk_name, "mmcblk%d", devidx);
-
-       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));
-       return md;
-
- err_putdisk:
-       put_disk(md->disk);
- err_kfree:
-       kfree(md);
- out:
-       return ERR_PTR(ret);
-}
-
-static int
-mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
-{
-       struct mmc_command cmd;
-       int err;
-
-       /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
-       if (mmc_card_blockaddr(card))
-               return 0;
-
-       mmc_card_claim_host(card);
-       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);
-
-       if (err) {
-               printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
-                       md->disk->disk_name, cmd.arg, err);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int mmc_blk_probe(struct mmc_card *card)
-{
-       struct mmc_blk_data *md;
-       int err;
-
-       /*
-        * Check that the card supports the command class(es) we need.
-        */
-       if (!(card->csd.cmdclass & CCC_BLOCK_READ))
-               return -ENODEV;
-
-       md = mmc_blk_alloc(card);
-       if (IS_ERR(md))
-               return PTR_ERR(md);
-
-       err = mmc_blk_set_blksize(md, card);
-       if (err)
-               goto out;
-
-       printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
-               md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
-               (unsigned long long)(get_capacity(md->disk) >> 1),
-               md->read_only ? "(ro)" : "");
-
-       mmc_set_drvdata(card, md);
-       add_disk(md->disk);
-       return 0;
-
- out:
-       mmc_blk_put(md);
-
-       return err;
-}
-
-static void mmc_blk_remove(struct mmc_card *card)
-{
-       struct mmc_blk_data *md = mmc_get_drvdata(card);
-
-       if (md) {
-               int devidx;
-
-               /* Stop new requests from getting into the queue */
-               del_gendisk(md->disk);
-
-               /* Then flush out any already in there */
-               mmc_cleanup_queue(&md->queue);
-
-               devidx = md->disk->first_minor >> MMC_SHIFT;
-               __clear_bit(devidx, dev_use);
-
-               mmc_blk_put(md);
-       }
-       mmc_set_drvdata(card, NULL);
-}
-
-#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
-{
-       struct mmc_blk_data *md = mmc_get_drvdata(card);
-
-       if (md) {
-               mmc_queue_suspend(&md->queue);
-       }
-       return 0;
-}
-
-static int mmc_blk_resume(struct mmc_card *card)
-{
-       struct mmc_blk_data *md = mmc_get_drvdata(card);
-
-       if (md) {
-               mmc_blk_set_blksize(md, card);
-               mmc_queue_resume(&md->queue);
-       }
-       return 0;
-}
-#else
-#define        mmc_blk_suspend NULL
-#define mmc_blk_resume NULL
-#endif
-
-static struct mmc_driver mmc_driver = {
-       .drv            = {
-               .name   = "mmcblk",
-       },
-       .probe          = mmc_blk_probe,
-       .remove         = mmc_blk_remove,
-       .suspend        = mmc_blk_suspend,
-       .resume         = mmc_blk_resume,
-};
-
-static int __init mmc_blk_init(void)
-{
-       int res = -ENOMEM;
-
-       res = register_blkdev(major, "mmc");
-       if (res < 0) {
-               printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",
-                      major, res);
-               goto out;
-       }
-       if (major == 0)
-               major = res;
-
-       return mmc_register_driver(&mmc_driver);
-
- out:
-       return res;
-}
-
-static void __exit mmc_blk_exit(void)
-{
-       mmc_unregister_driver(&mmc_driver);
-       unregister_blkdev(major, "mmc");
-}
-
-module_init(mmc_blk_init);
-module_exit(mmc_blk_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
-
-module_param(major, int, 0444);
-MODULE_PARM_DESC(major, "specify the major device number for MMC block driver");
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
deleted file mode 100644 (file)
index c27e426..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- *  linux/drivers/mmc/mmc_queue.c
- *
- *  Copyright (C) 2003 Russell King, 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/blkdev.h>
-#include <linux/kthread.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include "mmc_queue.h"
-
-#define MMC_QUEUE_SUSPENDED    (1 << 0)
-
-/*
- * Prepare a MMC request.  Essentially, this means passing the
- * preparation off to the media driver.  The media driver will
- * create a mmc_io_request in req->special.
- */
-static int mmc_prep_request(struct request_queue *q, struct request *req)
-{
-       struct mmc_queue *mq = q->queuedata;
-       int ret = BLKPREP_KILL;
-
-       if (blk_special_request(req)) {
-               /*
-                * Special commands already have the command
-                * blocks already setup in req->special.
-                */
-               BUG_ON(!req->special);
-
-               ret = BLKPREP_OK;
-       } else if (blk_fs_request(req) || blk_pc_request(req)) {
-               /*
-                * Block I/O requests need translating according
-                * to the protocol.
-                */
-               ret = mq->prep_fn(mq, req);
-       } else {
-               /*
-                * Everything else is invalid.
-                */
-               blk_dump_rq_flags(req, "MMC bad request");
-       }
-
-       if (ret == BLKPREP_OK)
-               req->cmd_flags |= REQ_DONTPREP;
-
-       return ret;
-}
-
-static int mmc_queue_thread(void *d)
-{
-       struct mmc_queue *mq = d;
-       struct request_queue *q = mq->queue;
-
-       /*
-        * Set iothread to ensure that we aren't put to sleep by
-        * the process freezing.  We handle suspension ourselves.
-        */
-       current->flags |= PF_MEMALLOC|PF_NOFREEZE;
-
-       down(&mq->thread_sem);
-       do {
-               struct request *req = NULL;
-
-               spin_lock_irq(q->queue_lock);
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (!blk_queue_plugged(q))
-                       req = elv_next_request(q);
-               mq->req = req;
-               spin_unlock_irq(q->queue_lock);
-
-               if (!req) {
-                       if (kthread_should_stop()) {
-                               set_current_state(TASK_RUNNING);
-                               break;
-                       }
-                       up(&mq->thread_sem);
-                       schedule();
-                       down(&mq->thread_sem);
-                       continue;
-               }
-               set_current_state(TASK_RUNNING);
-
-               mq->issue_fn(mq, req);
-       } while (1);
-       up(&mq->thread_sem);
-
-       return 0;
-}
-
-/*
- * Generic MMC request handler.  This is called for any queue on a
- * particular host.  When the host is not busy, we look for a request
- * on any queue on this host, and attempt to issue it.  This may
- * not be the queue we were asked to process.
- */
-static void mmc_request(request_queue_t *q)
-{
-       struct mmc_queue *mq = q->queuedata;
-       struct request *req;
-       int ret;
-
-       if (!mq) {
-               printk(KERN_ERR "MMC: killing requests for dead queue\n");
-               while ((req = elv_next_request(q)) != NULL) {
-                       do {
-                               ret = end_that_request_chunk(req, 0,
-                                       req->current_nr_sectors << 9);
-                       } while (ret);
-               }
-               return;
-       }
-
-       if (!mq->req)
-               wake_up_process(mq->thread);
-}
-
-/**
- * mmc_init_queue - initialise a queue structure.
- * @mq: mmc queue
- * @card: mmc card to attach this queue
- * @lock: queue lock
- *
- * Initialise a MMC card request queue.
- */
-int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)
-{
-       struct mmc_host *host = card->host;
-       u64 limit = BLK_BOUNCE_HIGH;
-       int ret;
-
-       if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-               limit = *mmc_dev(host)->dma_mask;
-
-       mq->card = card;
-       mq->queue = blk_init_queue(mmc_request, lock);
-       if (!mq->queue)
-               return -ENOMEM;
-
-       blk_queue_prep_rq(mq->queue, mmc_prep_request);
-       blk_queue_bounce_limit(mq->queue, limit);
-       blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
-       blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
-       blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
-       blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-
-       mq->queue->queuedata = mq;
-       mq->req = NULL;
-
-       mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
-                        GFP_KERNEL);
-       if (!mq->sg) {
-               ret = -ENOMEM;
-               goto cleanup_queue;
-       }
-
-       init_MUTEX(&mq->thread_sem);
-
-       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
-       if (IS_ERR(mq->thread)) {
-               ret = PTR_ERR(mq->thread);
-               goto free_sg;
-       }
-
-       return 0;
-
- free_sg:
-       kfree(mq->sg);
-       mq->sg = NULL;
- cleanup_queue:
-       blk_cleanup_queue(mq->queue);
-       return ret;
-}
-EXPORT_SYMBOL(mmc_init_queue);
-
-void mmc_cleanup_queue(struct mmc_queue *mq)
-{
-       request_queue_t *q = mq->queue;
-       unsigned long flags;
-
-       /* Mark that we should start throwing out stragglers */
-       spin_lock_irqsave(q->queue_lock, flags);
-       q->queuedata = NULL;
-       spin_unlock_irqrestore(q->queue_lock, flags);
-
-       /* Then terminate our worker thread */
-       kthread_stop(mq->thread);
-
-       kfree(mq->sg);
-       mq->sg = NULL;
-
-       blk_cleanup_queue(mq->queue);
-
-       mq->card = NULL;
-}
-EXPORT_SYMBOL(mmc_cleanup_queue);
-
-/**
- * mmc_queue_suspend - suspend a MMC request queue
- * @mq: MMC queue to suspend
- *
- * Stop the block request queue, and wait for our thread to
- * complete any outstanding requests.  This ensures that we
- * won't suspend while a request is being processed.
- */
-void mmc_queue_suspend(struct mmc_queue *mq)
-{
-       request_queue_t *q = mq->queue;
-       unsigned long flags;
-
-       if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
-               mq->flags |= MMC_QUEUE_SUSPENDED;
-
-               spin_lock_irqsave(q->queue_lock, flags);
-               blk_stop_queue(q);
-               spin_unlock_irqrestore(q->queue_lock, flags);
-
-               down(&mq->thread_sem);
-       }
-}
-EXPORT_SYMBOL(mmc_queue_suspend);
-
-/**
- * mmc_queue_resume - resume a previously suspended MMC request queue
- * @mq: MMC queue to resume
- */
-void mmc_queue_resume(struct mmc_queue *mq)
-{
-       request_queue_t *q = mq->queue;
-       unsigned long flags;
-
-       if (mq->flags & MMC_QUEUE_SUSPENDED) {
-               mq->flags &= ~MMC_QUEUE_SUSPENDED;
-
-               up(&mq->thread_sem);
-
-               spin_lock_irqsave(q->queue_lock, flags);
-               blk_start_queue(q);
-               spin_unlock_irqrestore(q->queue_lock, flags);
-       }
-}
-EXPORT_SYMBOL(mmc_queue_resume);
diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h
deleted file mode 100644 (file)
index c9f139e..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef MMC_QUEUE_H
-#define MMC_QUEUE_H
-
-struct request;
-struct task_struct;
-
-struct mmc_queue {
-       struct mmc_card         *card;
-       struct task_struct      *thread;
-       struct semaphore        thread_sem;
-       unsigned int            flags;
-       struct request          *req;
-       int                     (*prep_fn)(struct mmc_queue *, struct request *);
-       int                     (*issue_fn)(struct mmc_queue *, struct request *);
-       void                    *data;
-       struct request_queue    *queue;
-       struct scatterlist      *sg;
-};
-
-struct mmc_io_request {
-       struct request          *rq;
-       int                     num;
-       struct mmc_command      selcmd;         /* mmc_queue private */
-       struct mmc_command      cmd[4];         /* max 4 commands */
-};
-
-extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
-extern void mmc_cleanup_queue(struct mmc_queue *);
-extern void mmc_queue_suspend(struct mmc_queue *);
-extern void mmc_queue_resume(struct mmc_queue *);
-
-#endif
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
deleted file mode 100644 (file)
index e0e82d8..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- *  linux/drivers/mmc/mmc_sysfs.c
- *
- *  Copyright (C) 2003 Russell King, 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.
- *
- *  MMC sysfs/driver model support.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/workqueue.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include "mmc.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)
-#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
-
-#define MMC_ATTR(name, fmt, args...)                                   \
-static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)        \
-{                                                                      \
-       struct mmc_card *card = dev_to_mmc_card(dev);                   \
-       return sprintf(buf, fmt, args);                                 \
-}
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
-       card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
-       card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-
-static struct device_attribute mmc_dev_attrs[] = {
-       MMC_ATTR_RO(cid),
-       MMC_ATTR_RO(csd),
-       MMC_ATTR_RO(date),
-       MMC_ATTR_RO(fwrev),
-       MMC_ATTR_RO(hwrev),
-       MMC_ATTR_RO(manfid),
-       MMC_ATTR_RO(name),
-       MMC_ATTR_RO(oemid),
-       MMC_ATTR_RO(serial),
-       __ATTR_NULL
-};
-
-static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
-
-
-static void mmc_release_card(struct device *dev)
-{
-       struct mmc_card *card = dev_to_mmc_card(dev);
-
-       kfree(card);
-}
-
-/*
- * 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.
- */
-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);
-}
-
-static int
-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
-               int buf_size)
-{
-       struct mmc_card *card = dev_to_mmc_card(dev);
-       char ccc[13];
-       int retval = 0, i = 0, length = 0;
-
-#define add_env(fmt,val) do {                                  \
-       retval = add_uevent_var(envp, num_envp, &i,             \
-                               buf, buf_size, &length,         \
-                               fmt, val);                      \
-       if (retval)                                             \
-               return retval;                                  \
-} while (0);
-
-       for (i = 0; i < 12; i++)
-               ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
-       ccc[12] = '\0';
-
-       add_env("MMC_CCC=%s", ccc);
-       add_env("MMC_MANFID=%06x", card->cid.manfid);
-       add_env("MMC_NAME=%s", mmc_card_name(card));
-       add_env("MMC_OEMID=%04x", card->cid.oemid);
-#undef add_env
-       envp[i] = NULL;
-
-       return 0;
-}
-
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-{
-       struct mmc_driver *drv = to_mmc_driver(dev->driver);
-       struct mmc_card *card = dev_to_mmc_card(dev);
-       int ret = 0;
-
-       if (dev->driver && drv->suspend)
-               ret = drv->suspend(card, state);
-       return ret;
-}
-
-static int mmc_bus_resume(struct device *dev)
-{
-       struct mmc_driver *drv = to_mmc_driver(dev->driver);
-       struct mmc_card *card = dev_to_mmc_card(dev);
-       int ret = 0;
-
-       if (dev->driver && drv->resume)
-               ret = drv->resume(card);
-       return ret;
-}
-
-static int mmc_bus_probe(struct device *dev)
-{
-       struct mmc_driver *drv = to_mmc_driver(dev->driver);
-       struct mmc_card *card = dev_to_mmc_card(dev);
-
-       return drv->probe(card);
-}
-
-static int mmc_bus_remove(struct device *dev)
-{
-       struct mmc_driver *drv = to_mmc_driver(dev->driver);
-       struct mmc_card *card = dev_to_mmc_card(dev);
-
-       drv->remove(card);
-
-       return 0;
-}
-
-static struct bus_type mmc_bus_type = {
-       .name           = "mmc",
-       .dev_attrs      = mmc_dev_attrs,
-       .match          = mmc_bus_match,
-       .uevent         = mmc_bus_uevent,
-       .probe          = mmc_bus_probe,
-       .remove         = mmc_bus_remove,
-       .suspend        = mmc_bus_suspend,
-       .resume         = mmc_bus_resume,
-};
-
-/**
- *     mmc_register_driver - register a media driver
- *     @drv: MMC media driver
- */
-int mmc_register_driver(struct mmc_driver *drv)
-{
-       drv->drv.bus = &mmc_bus_type;
-       return driver_register(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_register_driver);
-
-/**
- *     mmc_unregister_driver - unregister a media driver
- *     @drv: MMC media driver
- */
-void mmc_unregister_driver(struct mmc_driver *drv)
-{
-       drv->drv.bus = &mmc_bus_type;
-       driver_unregister(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_unregister_driver);
-
-
-/*
- * Internal function.  Initialise a MMC card structure.
- */
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
-{
-       memset(card, 0, sizeof(struct mmc_card));
-       card->host = host;
-       device_initialize(&card->dev);
-       card->dev.parent = mmc_classdev(host);
-       card->dev.bus = &mmc_bus_type;
-       card->dev.release = mmc_release_card;
-}
-
-/*
- * Internal function.  Register a new MMC card with the driver model.
- */
-int mmc_register_card(struct mmc_card *card)
-{
-       int ret;
-
-       snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
-                "%s:%04x", mmc_hostname(card->host), card->rca);
-
-       ret = device_add(&card->dev);
-       if (ret == 0) {
-               if (mmc_card_sd(card)) {
-                       ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
-                       if (ret)
-                               device_del(&card->dev);
-               }
-       }
-       return ret;
-}
-
-/*
- * Internal function.  Unregister a new MMC card with the
- * driver model, and (eventually) free it.
- */
-void mmc_remove_card(struct mmc_card *card)
-{
-       if (mmc_card_present(card)) {
-               if (mmc_card_sd(card))
-                       device_remove_file(&card->dev, &mmc_dev_attr_scr);
-
-               device_del(&card->dev);
-       }
-
-       put_device(&card->dev);
-}
-
-
-static void mmc_host_classdev_release(struct device *dev)
-{
-       struct mmc_host *host = cls_dev_to_mmc_host(dev);
-       kfree(host);
-}
-
-static struct class mmc_host_class = {
-       .name           = "mmc_host",
-       .dev_release    = mmc_host_classdev_release,
-};
-
-static DEFINE_IDR(mmc_host_idr);
-static DEFINE_SPINLOCK(mmc_host_lock);
-
-/*
- * Internal function. Allocate a new MMC host.
- */
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
-{
-       struct mmc_host *host;
-
-       host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
-       if (host) {
-               memset(host, 0, sizeof(struct mmc_host) + extra);
-
-               host->parent = dev;
-               host->class_dev.parent = dev;
-               host->class_dev.class = &mmc_host_class;
-               device_initialize(&host->class_dev);
-       }
-
-       return host;
-}
-
-/*
- * Internal function. Register a new MMC host with the MMC class.
- */
-int mmc_add_host_sysfs(struct mmc_host *host)
-{
-       int err;
-
-       if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
-               return -ENOMEM;
-
-       spin_lock(&mmc_host_lock);
-       err = idr_get_new(&mmc_host_idr, host, &host->index);
-       spin_unlock(&mmc_host_lock);
-       if (err)
-               return err;
-
-       snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
-                "mmc%d", host->index);
-
-       return device_add(&host->class_dev);
-}
-
-/*
- * Internal function. Unregister a MMC host with the MMC class.
- */
-void mmc_remove_host_sysfs(struct mmc_host *host)
-{
-       device_del(&host->class_dev);
-
-       spin_lock(&mmc_host_lock);
-       idr_remove(&mmc_host_idr, host->index);
-       spin_unlock(&mmc_host_lock);
-}
-
-/*
- * Internal function. Free a MMC host.
- */
-void mmc_free_host_sysfs(struct mmc_host *host)
-{
-       put_device(&host->class_dev);
-}
-
-static struct workqueue_struct *workqueue;
-
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
-{
-       return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-void mmc_flush_scheduled_work(void)
-{
-       flush_workqueue(workqueue);
-}
-
-static int __init mmc_init(void)
-{
-       int ret;
-
-       workqueue = create_singlethread_workqueue("kmmcd");
-       if (!workqueue)
-               return -ENOMEM;
-
-       ret = bus_register(&mmc_bus_type);
-       if (ret == 0) {
-               ret = class_register(&mmc_host_class);
-               if (ret)
-                       bus_unregister(&mmc_bus_type);
-       }
-       return ret;
-}
-
-static void __exit mmc_exit(void)
-{
-       class_unregister(&mmc_host_class);
-       bus_unregister(&mmc_bus_type);
-       destroy_workqueue(workqueue);
-}
-
-module_init(mmc_init);
-module_exit(mmc_exit);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
deleted file mode 100644 (file)
index 5941dd9..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- *  linux/drivers/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver
- *
- *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#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>
-
-#include <asm/cacheflush.h>
-#include <asm/div64.h>
-#include <asm/io.h>
-#include <asm/scatterlist.h>
-#include <asm/sizes.h>
-#include <asm/mach/mmc.h>
-
-#include "mmci.h"
-
-#define DRIVER_NAME "mmci-pl18x"
-
-#define DBG(host,fmt,args...)  \
-       pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
-
-static unsigned int fmax = 515633;
-
-static void
-mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
-{
-       writel(0, host->base + MMCICOMMAND);
-
-       BUG_ON(host->data);
-
-       host->mrq = NULL;
-       host->cmd = NULL;
-
-       if (mrq->data)
-               mrq->data->bytes_xfered = host->data_xfered;
-
-       /*
-        * Need to drop the host lock here; mmc_request_done may call
-        * back into the driver...
-        */
-       spin_unlock(&host->lock);
-       mmc_request_done(host->mmc, mrq);
-       spin_lock(&host->lock);
-}
-
-static void mmci_stop_data(struct mmci_host *host)
-{
-       writel(0, host->base + MMCIDATACTRL);
-       writel(0, host->base + MMCIMASK1);
-       host->data = NULL;
-}
-
-static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
-{
-       unsigned int datactrl, timeout, irqmask;
-       unsigned long long clks;
-       void __iomem *base;
-       int blksz_bits;
-
-       DBG(host, "blksz %04x blks %04x flags %08x\n",
-           data->blksz, data->blocks, data->flags);
-
-       host->data = data;
-       host->size = data->blksz;
-       host->data_xfered = 0;
-
-       mmci_init_sg(host, data);
-
-       clks = (unsigned long long)data->timeout_ns * host->cclk;
-       do_div(clks, 1000000000UL);
-
-       timeout = data->timeout_clks + (unsigned int)clks;
-
-       base = host->base;
-       writel(timeout, base + MMCIDATATIMER);
-       writel(host->size, base + MMCIDATALENGTH);
-
-       blksz_bits = ffs(data->blksz) - 1;
-       BUG_ON(1 << blksz_bits != data->blksz);
-
-       datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
-       if (data->flags & MMC_DATA_READ) {
-               datactrl |= MCI_DPSM_DIRECTION;
-               irqmask = MCI_RXFIFOHALFFULLMASK;
-
-               /*
-                * If we have less than a FIFOSIZE of bytes to transfer,
-                * trigger a PIO interrupt as soon as any data is available.
-                */
-               if (host->size < MCI_FIFOSIZE)
-                       irqmask |= MCI_RXDATAAVLBLMASK;
-       } else {
-               /*
-                * We don't actually need to include "FIFO empty" here
-                * since its implicit in "FIFO half empty".
-                */
-               irqmask = MCI_TXFIFOHALFEMPTYMASK;
-       }
-
-       writel(datactrl, base + MMCIDATACTRL);
-       writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
-       writel(irqmask, base + MMCIMASK1);
-}
-
-static void
-mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
-{
-       void __iomem *base = host->base;
-
-       DBG(host, "op %02x arg %08x flags %08x\n",
-           cmd->opcode, cmd->arg, cmd->flags);
-
-       if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
-               writel(0, base + MMCICOMMAND);
-               udelay(1);
-       }
-
-       c |= cmd->opcode | MCI_CPSM_ENABLE;
-       if (cmd->flags & MMC_RSP_PRESENT) {
-               if (cmd->flags & MMC_RSP_136)
-                       c |= MCI_CPSM_LONGRSP;
-               c |= MCI_CPSM_RESPONSE;
-       }
-       if (/*interrupt*/0)
-               c |= MCI_CPSM_INTERRUPT;
-
-       host->cmd = cmd;
-
-       writel(cmd->arg, base + MMCIARGUMENT);
-       writel(c, base + MMCICOMMAND);
-}
-
-static void
-mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
-             unsigned int status)
-{
-       if (status & MCI_DATABLOCKEND) {
-               host->data_xfered += data->blksz;
-       }
-       if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
-               if (status & MCI_DATACRCFAIL)
-                       data->error = MMC_ERR_BADCRC;
-               else if (status & MCI_DATATIMEOUT)
-                       data->error = MMC_ERR_TIMEOUT;
-               else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
-                       data->error = MMC_ERR_FIFO;
-               status |= MCI_DATAEND;
-
-               /*
-                * We hit an error condition.  Ensure that any data
-                * partially written to a page is properly coherent.
-                */
-               if (host->sg_len && data->flags & MMC_DATA_READ)
-                       flush_dcache_page(host->sg_ptr->page);
-       }
-       if (status & MCI_DATAEND) {
-               mmci_stop_data(host);
-
-               if (!data->stop) {
-                       mmci_request_end(host, data->mrq);
-               } else {
-                       mmci_start_command(host, data->stop, 0);
-               }
-       }
-}
-
-static void
-mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
-            unsigned int status)
-{
-       void __iomem *base = host->base;
-
-       host->cmd = NULL;
-
-       cmd->resp[0] = readl(base + MMCIRESPONSE0);
-       cmd->resp[1] = readl(base + MMCIRESPONSE1);
-       cmd->resp[2] = readl(base + MMCIRESPONSE2);
-       cmd->resp[3] = readl(base + MMCIRESPONSE3);
-
-       if (status & MCI_CMDTIMEOUT) {
-               cmd->error = MMC_ERR_TIMEOUT;
-       } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {
-               cmd->error = MMC_ERR_BADCRC;
-       }
-
-       if (!cmd->data || cmd->error != MMC_ERR_NONE) {
-               if (host->data)
-                       mmci_stop_data(host);
-               mmci_request_end(host, cmd->mrq);
-       } else if (!(cmd->data->flags & MMC_DATA_READ)) {
-               mmci_start_data(host, cmd->data);
-       }
-}
-
-static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain)
-{
-       void __iomem *base = host->base;
-       char *ptr = buffer;
-       u32 status;
-
-       do {
-               int count = host->size - (readl(base + MMCIFIFOCNT) << 2);
-
-               if (count > remain)
-                       count = remain;
-
-               if (count <= 0)
-                       break;
-
-               readsl(base + MMCIFIFO, ptr, count >> 2);
-
-               ptr += count;
-               remain -= count;
-
-               if (remain == 0)
-                       break;
-
-               status = readl(base + MMCISTATUS);
-       } while (status & MCI_RXDATAAVLBL);
-
-       return ptr - buffer;
-}
-
-static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
-{
-       void __iomem *base = host->base;
-       char *ptr = buffer;
-
-       do {
-               unsigned int count, maxcnt;
-
-               maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;
-               count = min(remain, maxcnt);
-
-               writesl(base + MMCIFIFO, ptr, count >> 2);
-
-               ptr += count;
-               remain -= count;
-
-               if (remain == 0)
-                       break;
-
-               status = readl(base + MMCISTATUS);
-       } while (status & MCI_TXFIFOHALFEMPTY);
-
-       return ptr - buffer;
-}
-
-/*
- * PIO data transfer IRQ handler.
- */
-static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
-{
-       struct mmci_host *host = dev_id;
-       void __iomem *base = host->base;
-       u32 status;
-
-       status = readl(base + MMCISTATUS);
-
-       DBG(host, "irq1 %08x\n", status);
-
-       do {
-               unsigned long flags;
-               unsigned int remain, len;
-               char *buffer;
-
-               /*
-                * For write, we only need to test the half-empty flag
-                * here - if the FIFO is completely empty, then by
-                * definition it is more than half empty.
-                *
-                * For read, check for data available.
-                */
-               if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
-                       break;
-
-               /*
-                * Map the current scatter buffer.
-                */
-               buffer = mmci_kmap_atomic(host, &flags) + host->sg_off;
-               remain = host->sg_ptr->length - host->sg_off;
-
-               len = 0;
-               if (status & MCI_RXACTIVE)
-                       len = mmci_pio_read(host, buffer, remain);
-               if (status & MCI_TXACTIVE)
-                       len = mmci_pio_write(host, buffer, remain, status);
-
-               /*
-                * Unmap the buffer.
-                */
-               mmci_kunmap_atomic(host, buffer, &flags);
-
-               host->sg_off += len;
-               host->size -= len;
-               remain -= len;
-
-               if (remain)
-                       break;
-
-               /*
-                * If we were reading, and we have completed this
-                * page, ensure that the data cache is coherent.
-                */
-               if (status & MCI_RXACTIVE)
-                       flush_dcache_page(host->sg_ptr->page);
-
-               if (!mmci_next_sg(host))
-                       break;
-
-               status = readl(base + MMCISTATUS);
-       } while (1);
-
-       /*
-        * If we're nearing the end of the read, switch to
-        * "any data available" mode.
-        */
-       if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE)
-               writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
-
-       /*
-        * If we run out of data, disable the data IRQs; this
-        * prevents a race where the FIFO becomes empty before
-        * the chip itself has disabled the data path, and
-        * stops us racing with our data end IRQ.
-        */
-       if (host->size == 0) {
-               writel(0, base + MMCIMASK1);
-               writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
-       }
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Handle completion of command and data transfers.
- */
-static irqreturn_t mmci_irq(int irq, void *dev_id)
-{
-       struct mmci_host *host = dev_id;
-       u32 status;
-       int ret = 0;
-
-       spin_lock(&host->lock);
-
-       do {
-               struct mmc_command *cmd;
-               struct mmc_data *data;
-
-               status = readl(host->base + MMCISTATUS);
-               status &= readl(host->base + MMCIMASK0);
-               writel(status, host->base + MMCICLEAR);
-
-               DBG(host, "irq0 %08x\n", status);
-
-               data = host->data;
-               if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
-                             MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
-                       mmci_data_irq(host, data, status);
-
-               cmd = host->cmd;
-               if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
-                       mmci_cmd_irq(host, cmd, status);
-
-               ret = 1;
-       } while (status);
-
-       spin_unlock(&host->lock);
-
-       return IRQ_RETVAL(ret);
-}
-
-static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct mmci_host *host = mmc_priv(mmc);
-
-       WARN_ON(host->mrq != NULL);
-
-       spin_lock_irq(&host->lock);
-
-       host->mrq = mrq;
-
-       if (mrq->data && mrq->data->flags & MMC_DATA_READ)
-               mmci_start_data(host, mrq->data);
-
-       mmci_start_command(host, mrq->cmd, 0);
-
-       spin_unlock_irq(&host->lock);
-}
-
-static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct mmci_host *host = mmc_priv(mmc);
-       u32 clk = 0, pwr = 0;
-
-       if (ios->clock) {
-               if (ios->clock >= host->mclk) {
-                       clk = MCI_CLK_BYPASS;
-                       host->cclk = host->mclk;
-               } else {
-                       clk = host->mclk / (2 * ios->clock) - 1;
-                       if (clk > 256)
-                               clk = 255;
-                       host->cclk = host->mclk / (2 * (clk + 1));
-               }
-               clk |= MCI_CLK_ENABLE;
-       }
-
-       if (host->plat->translate_vdd)
-               pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
-
-       switch (ios->power_mode) {
-       case MMC_POWER_OFF:
-               break;
-       case MMC_POWER_UP:
-               pwr |= MCI_PWR_UP;
-               break;
-       case MMC_POWER_ON:
-               pwr |= MCI_PWR_ON;
-               break;
-       }
-
-       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-               pwr |= MCI_ROD;
-
-       writel(clk, host->base + MMCICLOCK);
-
-       if (host->pwr != pwr) {
-               host->pwr = pwr;
-               writel(pwr, host->base + MMCIPOWER);
-       }
-}
-
-static const struct mmc_host_ops mmci_ops = {
-       .request        = mmci_request,
-       .set_ios        = mmci_set_ios,
-};
-
-static void mmci_check_status(unsigned long data)
-{
-       struct mmci_host *host = (struct mmci_host *)data;
-       unsigned int status;
-
-       status = host->plat->status(mmc_dev(host->mmc));
-       if (status ^ host->oldstat)
-               mmc_detect_change(host->mmc, 0);
-
-       host->oldstat = status;
-       mod_timer(&host->timer, jiffies + HZ);
-}
-
-static int mmci_probe(struct amba_device *dev, void *id)
-{
-       struct mmc_platform_data *plat = dev->dev.platform_data;
-       struct mmci_host *host;
-       struct mmc_host *mmc;
-       int ret;
-
-       /* must have platform data */
-       if (!plat) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = amba_request_regions(dev, DRIVER_NAME);
-       if (ret)
-               goto out;
-
-       mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
-       if (!mmc) {
-               ret = -ENOMEM;
-               goto rel_regions;
-       }
-
-       host = mmc_priv(mmc);
-       host->clk = clk_get(&dev->dev, "MCLK");
-       if (IS_ERR(host->clk)) {
-               ret = PTR_ERR(host->clk);
-               host->clk = NULL;
-               goto host_free;
-       }
-
-       ret = clk_enable(host->clk);
-       if (ret)
-               goto clk_free;
-
-       host->plat = plat;
-       host->mclk = clk_get_rate(host->clk);
-       host->mmc = mmc;
-       host->base = ioremap(dev->res.start, SZ_4K);
-       if (!host->base) {
-               ret = -ENOMEM;
-               goto clk_disable;
-       }
-
-       mmc->ops = &mmci_ops;
-       mmc->f_min = (host->mclk + 511) / 512;
-       mmc->f_max = min(host->mclk, fmax);
-       mmc->ocr_avail = plat->ocr_mask;
-       mmc->caps = MMC_CAP_MULTIWRITE;
-
-       /*
-        * We can do SGIO
-        */
-       mmc->max_hw_segs = 16;
-       mmc->max_phys_segs = NR_SG;
-
-       /*
-        * Since we only have a 16-bit data length register, we must
-        * ensure that we don't exceed 2^16-1 bytes in a single request.
-        */
-       mmc->max_req_size = 65535;
-
-       /*
-        * Set the maximum segment size.  Since we aren't doing DMA
-        * (yet) we are only limited by the data length register.
-        */
-       mmc->max_seg_size = mmc->max_req_size;
-
-       /*
-        * Block size can be up to 2048 bytes, but must be a power of two.
-        */
-       mmc->max_blk_size = 2048;
-
-       /*
-        * No limit on the number of blocks transferred.
-        */
-       mmc->max_blk_count = mmc->max_req_size;
-
-       spin_lock_init(&host->lock);
-
-       writel(0, host->base + MMCIMASK0);
-       writel(0, host->base + MMCIMASK1);
-       writel(0xfff, host->base + MMCICLEAR);
-
-       ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
-       if (ret)
-               goto unmap;
-
-       ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host);
-       if (ret)
-               goto irq0_free;
-
-       writel(MCI_IRQENABLE, host->base + MMCIMASK0);
-
-       amba_set_drvdata(dev, mmc);
-
-       mmc_add_host(mmc);
-
-       printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n",
-               mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
-               (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
-
-       init_timer(&host->timer);
-       host->timer.data = (unsigned long)host;
-       host->timer.function = mmci_check_status;
-       host->timer.expires = jiffies + HZ;
-       add_timer(&host->timer);
-
-       return 0;
-
- irq0_free:
-       free_irq(dev->irq[0], host);
- unmap:
-       iounmap(host->base);
- clk_disable:
-       clk_disable(host->clk);
- clk_free:
-       clk_put(host->clk);
- host_free:
-       mmc_free_host(mmc);
- rel_regions:
-       amba_release_regions(dev);
- out:
-       return ret;
-}
-
-static int mmci_remove(struct amba_device *dev)
-{
-       struct mmc_host *mmc = amba_get_drvdata(dev);
-
-       amba_set_drvdata(dev, NULL);
-
-       if (mmc) {
-               struct mmci_host *host = mmc_priv(mmc);
-
-               del_timer_sync(&host->timer);
-
-               mmc_remove_host(mmc);
-
-               writel(0, host->base + MMCIMASK0);
-               writel(0, host->base + MMCIMASK1);
-
-               writel(0, host->base + MMCICOMMAND);
-               writel(0, host->base + MMCIDATACTRL);
-
-               free_irq(dev->irq[0], host);
-               free_irq(dev->irq[1], host);
-
-               iounmap(host->base);
-               clk_disable(host->clk);
-               clk_put(host->clk);
-
-               mmc_free_host(mmc);
-
-               amba_release_regions(dev);
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int mmci_suspend(struct amba_device *dev, pm_message_t state)
-{
-       struct mmc_host *mmc = amba_get_drvdata(dev);
-       int ret = 0;
-
-       if (mmc) {
-               struct mmci_host *host = mmc_priv(mmc);
-
-               ret = mmc_suspend_host(mmc, state);
-               if (ret == 0)
-                       writel(0, host->base + MMCIMASK0);
-       }
-
-       return ret;
-}
-
-static int mmci_resume(struct amba_device *dev)
-{
-       struct mmc_host *mmc = amba_get_drvdata(dev);
-       int ret = 0;
-
-       if (mmc) {
-               struct mmci_host *host = mmc_priv(mmc);
-
-               writel(MCI_IRQENABLE, host->base + MMCIMASK0);
-
-               ret = mmc_resume_host(mmc);
-       }
-
-       return ret;
-}
-#else
-#define mmci_suspend   NULL
-#define mmci_resume    NULL
-#endif
-
-static struct amba_id mmci_ids[] = {
-       {
-               .id     = 0x00041180,
-               .mask   = 0x000fffff,
-       },
-       {
-               .id     = 0x00041181,
-               .mask   = 0x000fffff,
-       },
-       { 0, 0 },
-};
-
-static struct amba_driver mmci_driver = {
-       .drv            = {
-               .name   = DRIVER_NAME,
-       },
-       .probe          = mmci_probe,
-       .remove         = mmci_remove,
-       .suspend        = mmci_suspend,
-       .resume         = mmci_resume,
-       .id_table       = mmci_ids,
-};
-
-static int __init mmci_init(void)
-{
-       return amba_driver_register(&mmci_driver);
-}
-
-static void __exit mmci_exit(void)
-{
-       amba_driver_unregister(&mmci_driver);
-}
-
-module_init(mmci_init);
-module_exit(mmci_exit);
-module_param(fmax, uint, 0444);
-
-MODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/mmci.h b/drivers/mmc/mmci.h
deleted file mode 100644 (file)
index 6d7eadc..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- *  linux/drivers/mmc/mmci.h - ARM PrimeCell MMCI PL180/1 driver
- *
- *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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.
- */
-#define MMCIPOWER              0x000
-#define MCI_PWR_OFF            0x00
-#define MCI_PWR_UP             0x02
-#define MCI_PWR_ON             0x03
-#define MCI_OD                 (1 << 6)
-#define MCI_ROD                        (1 << 7)
-
-#define MMCICLOCK              0x004
-#define MCI_CLK_ENABLE         (1 << 8)
-#define MCI_CLK_PWRSAVE                (1 << 9)
-#define MCI_CLK_BYPASS         (1 << 10)
-
-#define MMCIARGUMENT           0x008
-#define MMCICOMMAND            0x00c
-#define MCI_CPSM_RESPONSE      (1 << 6)
-#define MCI_CPSM_LONGRSP       (1 << 7)
-#define MCI_CPSM_INTERRUPT     (1 << 8)
-#define MCI_CPSM_PENDING       (1 << 9)
-#define MCI_CPSM_ENABLE                (1 << 10)
-
-#define MMCIRESPCMD            0x010
-#define MMCIRESPONSE0          0x014
-#define MMCIRESPONSE1          0x018
-#define MMCIRESPONSE2          0x01c
-#define MMCIRESPONSE3          0x020
-#define MMCIDATATIMER          0x024
-#define MMCIDATALENGTH         0x028
-#define MMCIDATACTRL           0x02c
-#define MCI_DPSM_ENABLE                (1 << 0)
-#define MCI_DPSM_DIRECTION     (1 << 1)
-#define MCI_DPSM_MODE          (1 << 2)
-#define MCI_DPSM_DMAENABLE     (1 << 3)
-
-#define MMCIDATACNT            0x030
-#define MMCISTATUS             0x034
-#define MCI_CMDCRCFAIL         (1 << 0)
-#define MCI_DATACRCFAIL                (1 << 1)
-#define MCI_CMDTIMEOUT         (1 << 2)
-#define MCI_DATATIMEOUT                (1 << 3)
-#define MCI_TXUNDERRUN         (1 << 4)
-#define MCI_RXOVERRUN          (1 << 5)
-#define MCI_CMDRESPEND         (1 << 6)
-#define MCI_CMDSENT            (1 << 7)
-#define MCI_DATAEND            (1 << 8)
-#define MCI_DATABLOCKEND       (1 << 10)
-#define MCI_CMDACTIVE          (1 << 11)
-#define MCI_TXACTIVE           (1 << 12)
-#define MCI_RXACTIVE           (1 << 13)
-#define MCI_TXFIFOHALFEMPTY    (1 << 14)
-#define MCI_RXFIFOHALFFULL     (1 << 15)
-#define MCI_TXFIFOFULL         (1 << 16)
-#define MCI_RXFIFOFULL         (1 << 17)
-#define MCI_TXFIFOEMPTY                (1 << 18)
-#define MCI_RXFIFOEMPTY                (1 << 19)
-#define MCI_TXDATAAVLBL                (1 << 20)
-#define MCI_RXDATAAVLBL                (1 << 21)
-
-#define MMCICLEAR              0x038
-#define MCI_CMDCRCFAILCLR      (1 << 0)
-#define MCI_DATACRCFAILCLR     (1 << 1)
-#define MCI_CMDTIMEOUTCLR      (1 << 2)
-#define MCI_DATATIMEOUTCLR     (1 << 3)
-#define MCI_TXUNDERRUNCLR      (1 << 4)
-#define MCI_RXOVERRUNCLR       (1 << 5)
-#define MCI_CMDRESPENDCLR      (1 << 6)
-#define MCI_CMDSENTCLR         (1 << 7)
-#define MCI_DATAENDCLR         (1 << 8)
-#define MCI_DATABLOCKENDCLR    (1 << 10)
-
-#define MMCIMASK0              0x03c
-#define MCI_CMDCRCFAILMASK     (1 << 0)
-#define MCI_DATACRCFAILMASK    (1 << 1)
-#define MCI_CMDTIMEOUTMASK     (1 << 2)
-#define MCI_DATATIMEOUTMASK    (1 << 3)
-#define MCI_TXUNDERRUNMASK     (1 << 4)
-#define MCI_RXOVERRUNMASK      (1 << 5)
-#define MCI_CMDRESPENDMASK     (1 << 6)
-#define MCI_CMDSENTMASK                (1 << 7)
-#define MCI_DATAENDMASK                (1 << 8)
-#define MCI_DATABLOCKENDMASK   (1 << 10)
-#define MCI_CMDACTIVEMASK      (1 << 11)
-#define MCI_TXACTIVEMASK       (1 << 12)
-#define MCI_RXACTIVEMASK       (1 << 13)
-#define MCI_TXFIFOHALFEMPTYMASK        (1 << 14)
-#define MCI_RXFIFOHALFFULLMASK (1 << 15)
-#define MCI_TXFIFOFULLMASK     (1 << 16)
-#define MCI_RXFIFOFULLMASK     (1 << 17)
-#define MCI_TXFIFOEMPTYMASK    (1 << 18)
-#define MCI_RXFIFOEMPTYMASK    (1 << 19)
-#define MCI_TXDATAAVLBLMASK    (1 << 20)
-#define MCI_RXDATAAVLBLMASK    (1 << 21)
-
-#define MMCIMASK1              0x040
-#define MMCIFIFOCNT            0x048
-#define MMCIFIFO               0x080 /* to 0x0bc */
-
-#define MCI_IRQENABLE  \
-       (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK|     \
-       MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|       \
-       MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
-
-/*
- * The size of the FIFO in bytes.
- */
-#define MCI_FIFOSIZE   (16*4)
-       
-#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
-
-#define NR_SG          16
-
-struct clk;
-
-struct mmci_host {
-       void __iomem            *base;
-       struct mmc_request      *mrq;
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;
-       struct mmc_host         *mmc;
-       struct clk              *clk;
-
-       unsigned int            data_xfered;
-
-       spinlock_t              lock;
-
-       unsigned int            mclk;
-       unsigned int            cclk;
-       u32                     pwr;
-       struct mmc_platform_data *plat;
-
-       struct timer_list       timer;
-       unsigned int            oldstat;
-
-       unsigned int            sg_len;
-
-       /* pio stuff */
-       struct scatterlist      *sg_ptr;
-       unsigned int            sg_off;
-       unsigned int            size;
-};
-
-static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
-{
-       /*
-        * Ideally, we want the higher levels to pass us a scatter list.
-        */
-       host->sg_len = data->sg_len;
-       host->sg_ptr = data->sg;
-       host->sg_off = 0;
-}
-
-static inline int mmci_next_sg(struct mmci_host *host)
-{
-       host->sg_ptr++;
-       host->sg_off = 0;
-       return --host->sg_len;
-}
-
-static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags)
-{
-       struct scatterlist *sg = host->sg_ptr;
-
-       local_irq_save(*flags);
-       return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
-}
-
-static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
-{
-       kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
-       local_irq_restore(*flags);
-}
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
deleted file mode 100644 (file)
index 1e96a2f..0000000
+++ /dev/null
@@ -1,1289 +0,0 @@
-/*
- *  linux/drivers/media/mmc/omap.c
- *
- *  Copyright (C) 2004 Nokia Corporation
- *  Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com>
- *  Misc hacks here and there by Tony Lindgren <tony@atomide.com>
- *  Other hacks (DMA, SD, etc) by David Brownell
- *
- * 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/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#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>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/scatterlist.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/dma.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/fpga.h>
-#include <asm/arch/tps65010.h>
-
-#define        OMAP_MMC_REG_CMD        0x00
-#define        OMAP_MMC_REG_ARGL       0x04
-#define        OMAP_MMC_REG_ARGH       0x08
-#define        OMAP_MMC_REG_CON        0x0c
-#define        OMAP_MMC_REG_STAT       0x10
-#define        OMAP_MMC_REG_IE         0x14
-#define        OMAP_MMC_REG_CTO        0x18
-#define        OMAP_MMC_REG_DTO        0x1c
-#define        OMAP_MMC_REG_DATA       0x20
-#define        OMAP_MMC_REG_BLEN       0x24
-#define        OMAP_MMC_REG_NBLK       0x28
-#define        OMAP_MMC_REG_BUF        0x2c
-#define OMAP_MMC_REG_SDIO      0x34
-#define        OMAP_MMC_REG_REV        0x3c
-#define        OMAP_MMC_REG_RSP0       0x40
-#define        OMAP_MMC_REG_RSP1       0x44
-#define        OMAP_MMC_REG_RSP2       0x48
-#define        OMAP_MMC_REG_RSP3       0x4c
-#define        OMAP_MMC_REG_RSP4       0x50
-#define        OMAP_MMC_REG_RSP5       0x54
-#define        OMAP_MMC_REG_RSP6       0x58
-#define        OMAP_MMC_REG_RSP7       0x5c
-#define        OMAP_MMC_REG_IOSR       0x60
-#define        OMAP_MMC_REG_SYSC       0x64
-#define        OMAP_MMC_REG_SYSS       0x68
-
-#define        OMAP_MMC_STAT_CARD_ERR          (1 << 14)
-#define        OMAP_MMC_STAT_CARD_IRQ          (1 << 13)
-#define        OMAP_MMC_STAT_OCR_BUSY          (1 << 12)
-#define        OMAP_MMC_STAT_A_EMPTY           (1 << 11)
-#define        OMAP_MMC_STAT_A_FULL            (1 << 10)
-#define        OMAP_MMC_STAT_CMD_CRC           (1 <<  8)
-#define        OMAP_MMC_STAT_CMD_TOUT          (1 <<  7)
-#define        OMAP_MMC_STAT_DATA_CRC          (1 <<  6)
-#define        OMAP_MMC_STAT_DATA_TOUT         (1 <<  5)
-#define        OMAP_MMC_STAT_END_BUSY          (1 <<  4)
-#define        OMAP_MMC_STAT_END_OF_DATA       (1 <<  3)
-#define        OMAP_MMC_STAT_CARD_BUSY         (1 <<  2)
-#define        OMAP_MMC_STAT_END_OF_CMD        (1 <<  0)
-
-#define OMAP_MMC_READ(host, reg)       __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg)
-#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg)
-
-/*
- * Command types
- */
-#define OMAP_MMC_CMDTYPE_BC    0
-#define OMAP_MMC_CMDTYPE_BCR   1
-#define OMAP_MMC_CMDTYPE_AC    2
-#define OMAP_MMC_CMDTYPE_ADTC  3
-
-
-#define DRIVER_NAME "mmci-omap"
-
-/* Specifies how often in millisecs to poll for card status changes
- * when the cover switch is open */
-#define OMAP_MMC_SWITCH_POLL_DELAY     500
-
-static int mmc_omap_enable_poll = 1;
-
-struct mmc_omap_host {
-       int                     initialized;
-       int                     suspended;
-       struct mmc_request *    mrq;
-       struct mmc_command *    cmd;
-       struct mmc_data *       data;
-       struct mmc_host *       mmc;
-       struct device *         dev;
-       unsigned char           id; /* 16xx chips have 2 MMC blocks */
-       struct clk *            iclk;
-       struct clk *            fclk;
-       struct resource         *mem_res;
-       void __iomem            *virt_base;
-       unsigned int            phys_base;
-       int                     irq;
-       unsigned char           bus_mode;
-       unsigned char           hw_bus_mode;
-
-       unsigned int            sg_len;
-       int                     sg_idx;
-       u16 *                   buffer;
-       u32                     buffer_bytes_left;
-       u32                     total_bytes_left;
-
-       unsigned                use_dma:1;
-       unsigned                brs_received:1, dma_done:1;
-       unsigned                dma_is_read:1;
-       unsigned                dma_in_use:1;
-       int                     dma_ch;
-       spinlock_t              dma_lock;
-       struct timer_list       dma_timer;
-       unsigned                dma_len;
-
-       short                   power_pin;
-       short                   wp_pin;
-
-       int                     switch_pin;
-       struct work_struct      switch_work;
-       struct timer_list       switch_timer;
-       int                     switch_last_state;
-};
-
-static inline int
-mmc_omap_cover_is_open(struct mmc_omap_host *host)
-{
-       if (host->switch_pin < 0)
-               return 0;
-       return omap_get_gpio_datain(host->switch_pin);
-}
-
-static ssize_t
-mmc_omap_show_cover_switch(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       struct mmc_omap_host *host = dev_get_drvdata(dev);
-
-       return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" :
-                       "closed");
-}
-
-static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
-
-static ssize_t
-mmc_omap_show_enable_poll(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
-}
-
-static ssize_t
-mmc_omap_store_enable_poll(struct device *dev,
-       struct device_attribute *attr, const char *buf,
-       size_t size)
-{
-       int enable_poll;
-
-       if (sscanf(buf, "%10d", &enable_poll) != 1)
-               return -EINVAL;
-
-       if (enable_poll != mmc_omap_enable_poll) {
-               struct mmc_omap_host *host = dev_get_drvdata(dev);
-
-               mmc_omap_enable_poll = enable_poll;
-               if (enable_poll && host->switch_pin >= 0)
-                       schedule_work(&host->switch_work);
-       }
-       return size;
-}
-
-static DEVICE_ATTR(enable_poll, 0664,
-                  mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
-
-static void
-mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
-{
-       u32 cmdreg;
-       u32 resptype;
-       u32 cmdtype;
-
-       host->cmd = cmd;
-
-       resptype = 0;
-       cmdtype = 0;
-
-       /* Our hardware needs to know exact type */
-       switch (mmc_resp_type(cmd)) {
-       case MMC_RSP_NONE:
-               break;
-       case MMC_RSP_R1:
-       case MMC_RSP_R1B:
-               /* resp 1, 1b, 6, 7 */
-               resptype = 1;
-               break;
-       case MMC_RSP_R2:
-               resptype = 2;
-               break;
-       case MMC_RSP_R3:
-               resptype = 3;
-               break;
-       default:
-               dev_err(mmc_dev(host->mmc), "Invalid response type: %04x\n", mmc_resp_type(cmd));
-               break;
-       }
-
-       if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) {
-               cmdtype = OMAP_MMC_CMDTYPE_ADTC;
-       } else if (mmc_cmd_type(cmd) == MMC_CMD_BC) {
-               cmdtype = OMAP_MMC_CMDTYPE_BC;
-       } else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) {
-               cmdtype = OMAP_MMC_CMDTYPE_BCR;
-       } else {
-               cmdtype = OMAP_MMC_CMDTYPE_AC;
-       }
-
-       cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
-
-       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
-               cmdreg |= 1 << 6;
-
-       if (cmd->flags & MMC_RSP_BUSY)
-               cmdreg |= 1 << 11;
-
-       if (host->data && !(host->data->flags & MMC_DATA_WRITE))
-               cmdreg |= 1 << 15;
-
-       clk_enable(host->fclk);
-
-       OMAP_MMC_WRITE(host, CTO, 200);
-       OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
-       OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
-       OMAP_MMC_WRITE(host, IE,
-                      OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
-                      OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
-                      OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
-                      OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
-                      OMAP_MMC_STAT_END_OF_DATA);
-       OMAP_MMC_WRITE(host, CMD, cmdreg);
-}
-
-static void
-mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
-{
-       if (host->dma_in_use) {
-               enum dma_data_direction dma_data_dir;
-
-               BUG_ON(host->dma_ch < 0);
-               if (data->error != MMC_ERR_NONE)
-                       omap_stop_dma(host->dma_ch);
-               /* Release DMA channel lazily */
-               mod_timer(&host->dma_timer, jiffies + HZ);
-               if (data->flags & MMC_DATA_WRITE)
-                       dma_data_dir = DMA_TO_DEVICE;
-               else
-                       dma_data_dir = DMA_FROM_DEVICE;
-               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
-                            dma_data_dir);
-       }
-       host->data = NULL;
-       host->sg_len = 0;
-       clk_disable(host->fclk);
-
-       /* NOTE:  MMC layer will sometimes poll-wait CMD13 next, issuing
-        * dozens of requests until the card finishes writing data.
-        * It'd be cheaper to just wait till an EOFB interrupt arrives...
-        */
-
-       if (!data->stop) {
-               host->mrq = NULL;
-               mmc_request_done(host->mmc, data->mrq);
-               return;
-       }
-
-       mmc_omap_start_command(host, data->stop);
-}
-
-static void
-mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
-{
-       unsigned long flags;
-       int done;
-
-       if (!host->dma_in_use) {
-               mmc_omap_xfer_done(host, data);
-               return;
-       }
-       done = 0;
-       spin_lock_irqsave(&host->dma_lock, flags);
-       if (host->dma_done)
-               done = 1;
-       else
-               host->brs_received = 1;
-       spin_unlock_irqrestore(&host->dma_lock, flags);
-       if (done)
-               mmc_omap_xfer_done(host, data);
-}
-
-static void
-mmc_omap_dma_timer(unsigned long data)
-{
-       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
-
-       BUG_ON(host->dma_ch < 0);
-       omap_free_dma(host->dma_ch);
-       host->dma_ch = -1;
-}
-
-static void
-mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
-{
-       unsigned long flags;
-       int done;
-
-       done = 0;
-       spin_lock_irqsave(&host->dma_lock, flags);
-       if (host->brs_received)
-               done = 1;
-       else
-               host->dma_done = 1;
-       spin_unlock_irqrestore(&host->dma_lock, flags);
-       if (done)
-               mmc_omap_xfer_done(host, data);
-}
-
-static void
-mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
-{
-       host->cmd = NULL;
-
-       if (cmd->flags & MMC_RSP_PRESENT) {
-               if (cmd->flags & MMC_RSP_136) {
-                       /* response type 2 */
-                       cmd->resp[3] =
-                               OMAP_MMC_READ(host, RSP0) |
-                               (OMAP_MMC_READ(host, RSP1) << 16);
-                       cmd->resp[2] =
-                               OMAP_MMC_READ(host, RSP2) |
-                               (OMAP_MMC_READ(host, RSP3) << 16);
-                       cmd->resp[1] =
-                               OMAP_MMC_READ(host, RSP4) |
-                               (OMAP_MMC_READ(host, RSP5) << 16);
-                       cmd->resp[0] =
-                               OMAP_MMC_READ(host, RSP6) |
-                               (OMAP_MMC_READ(host, RSP7) << 16);
-               } else {
-                       /* response types 1, 1b, 3, 4, 5, 6 */
-                       cmd->resp[0] =
-                               OMAP_MMC_READ(host, RSP6) |
-                               (OMAP_MMC_READ(host, RSP7) << 16);
-               }
-       }
-
-       if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
-               host->mrq = NULL;
-               clk_disable(host->fclk);
-               mmc_request_done(host->mmc, cmd->mrq);
-       }
-}
-
-/* PIO only */
-static void
-mmc_omap_sg_to_buf(struct mmc_omap_host *host)
-{
-       struct scatterlist *sg;
-
-       sg = host->data->sg + host->sg_idx;
-       host->buffer_bytes_left = sg->length;
-       host->buffer = page_address(sg->page) + sg->offset;
-       if (host->buffer_bytes_left > host->total_bytes_left)
-               host->buffer_bytes_left = host->total_bytes_left;
-}
-
-/* PIO only */
-static void
-mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
-{
-       int n;
-
-       if (host->buffer_bytes_left == 0) {
-               host->sg_idx++;
-               BUG_ON(host->sg_idx == host->sg_len);
-               mmc_omap_sg_to_buf(host);
-       }
-       n = 64;
-       if (n > host->buffer_bytes_left)
-               n = host->buffer_bytes_left;
-       host->buffer_bytes_left -= n;
-       host->total_bytes_left -= n;
-       host->data->bytes_xfered += n;
-
-       if (write) {
-               __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
-       } else {
-               __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
-       }
-}
-
-static inline void mmc_omap_report_irq(u16 status)
-{
-       static const char *mmc_omap_status_bits[] = {
-               "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
-               "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
-       };
-       int i, c = 0;
-
-       for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
-               if (status & (1 << i)) {
-                       if (c)
-                               printk(" ");
-                       printk("%s", mmc_omap_status_bits[i]);
-                       c++;
-               }
-}
-
-static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
-{
-       struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
-       u16 status;
-       int end_command;
-       int end_transfer;
-       int transfer_error;
-
-       if (host->cmd == NULL && host->data == NULL) {
-               status = OMAP_MMC_READ(host, STAT);
-               dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
-               if (status != 0) {
-                       OMAP_MMC_WRITE(host, STAT, status);
-                       OMAP_MMC_WRITE(host, IE, 0);
-               }
-               return IRQ_HANDLED;
-       }
-
-       end_command = 0;
-       end_transfer = 0;
-       transfer_error = 0;
-
-       while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
-               OMAP_MMC_WRITE(host, STAT, status);
-#ifdef CONFIG_MMC_DEBUG
-               dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
-                       status, host->cmd != NULL ? host->cmd->opcode : -1);
-               mmc_omap_report_irq(status);
-               printk("\n");
-#endif
-               if (host->total_bytes_left) {
-                       if ((status & OMAP_MMC_STAT_A_FULL) ||
-                           (status & OMAP_MMC_STAT_END_OF_DATA))
-                               mmc_omap_xfer_data(host, 0);
-                       if (status & OMAP_MMC_STAT_A_EMPTY)
-                               mmc_omap_xfer_data(host, 1);
-               }
-
-               if (status & OMAP_MMC_STAT_END_OF_DATA) {
-                       end_transfer = 1;
-               }
-
-               if (status & OMAP_MMC_STAT_DATA_TOUT) {
-                       dev_dbg(mmc_dev(host->mmc), "data timeout\n");
-                       if (host->data) {
-                               host->data->error |= MMC_ERR_TIMEOUT;
-                               transfer_error = 1;
-                       }
-               }
-
-               if (status & OMAP_MMC_STAT_DATA_CRC) {
-                       if (host->data) {
-                               host->data->error |= MMC_ERR_BADCRC;
-                               dev_dbg(mmc_dev(host->mmc),
-                                        "data CRC error, bytes left %d\n",
-                                       host->total_bytes_left);
-                               transfer_error = 1;
-                       } else {
-                               dev_dbg(mmc_dev(host->mmc), "data CRC error\n");
-                       }
-               }
-
-               if (status & OMAP_MMC_STAT_CMD_TOUT) {
-                       /* Timeouts are routine with some commands */
-                       if (host->cmd) {
-                               if (host->cmd->opcode != MMC_ALL_SEND_CID &&
-                                               host->cmd->opcode !=
-                                               MMC_SEND_OP_COND &&
-                                               host->cmd->opcode !=
-                                               MMC_APP_CMD &&
-                                               !mmc_omap_cover_is_open(host))
-                                       dev_err(mmc_dev(host->mmc),
-                                               "command timeout, CMD %d\n",
-                                               host->cmd->opcode);
-                               host->cmd->error = MMC_ERR_TIMEOUT;
-                               end_command = 1;
-                       }
-               }
-
-               if (status & OMAP_MMC_STAT_CMD_CRC) {
-                       if (host->cmd) {
-                               dev_err(mmc_dev(host->mmc),
-                                       "command CRC error (CMD%d, arg 0x%08x)\n",
-                                       host->cmd->opcode, host->cmd->arg);
-                               host->cmd->error = MMC_ERR_BADCRC;
-                               end_command = 1;
-                       } else
-                               dev_err(mmc_dev(host->mmc),
-                                       "command CRC error without cmd?\n");
-               }
-
-               if (status & OMAP_MMC_STAT_CARD_ERR) {
-                       if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
-                               u32 response = OMAP_MMC_READ(host, RSP6)
-                                       | (OMAP_MMC_READ(host, RSP7) << 16);
-                               /* STOP sometimes sets must-ignore bits */
-                               if (!(response & (R1_CC_ERROR
-                                                               | R1_ILLEGAL_COMMAND
-                                                               | R1_COM_CRC_ERROR))) {
-                                       end_command = 1;
-                                       continue;
-                               }
-                       }
-
-                       dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
-                               host->cmd->opcode);
-                       if (host->cmd) {
-                               host->cmd->error = MMC_ERR_FAILED;
-                               end_command = 1;
-                       }
-                       if (host->data) {
-                               host->data->error = MMC_ERR_FAILED;
-                               transfer_error = 1;
-                       }
-               }
-
-               /*
-                * NOTE: On 1610 the END_OF_CMD may come too early when
-                * starting a write 
-                */
-               if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
-                   (!(status & OMAP_MMC_STAT_A_EMPTY))) {
-                       end_command = 1;
-               }
-       }
-
-       if (end_command) {
-               mmc_omap_cmd_done(host, host->cmd);
-       }
-       if (transfer_error)
-               mmc_omap_xfer_done(host, host->data);
-       else if (end_transfer)
-               mmc_omap_end_of_data(host, host->data);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id)
-{
-       struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
-
-       schedule_work(&host->switch_work);
-
-       return IRQ_HANDLED;
-}
-
-static void mmc_omap_switch_timer(unsigned long arg)
-{
-       struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
-
-       schedule_work(&host->switch_work);
-}
-
-static void mmc_omap_switch_handler(struct work_struct *work)
-{
-       struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work);
-       struct mmc_card *card;
-       static int complained = 0;
-       int cards = 0, cover_open;
-
-       if (host->switch_pin == -1)
-               return;
-       cover_open = mmc_omap_cover_is_open(host);
-       if (cover_open != host->switch_last_state) {
-               kobject_uevent(&host->dev->kobj, KOBJ_CHANGE);
-               host->switch_last_state = cover_open;
-       }
-       mmc_detect_change(host->mmc, 0);
-       list_for_each_entry(card, &host->mmc->cards, node) {
-               if (mmc_card_present(card))
-                       cards++;
-       }
-       if (mmc_omap_cover_is_open(host)) {
-               if (!complained) {
-                       dev_info(mmc_dev(host->mmc), "cover is open");
-                       complained = 1;
-               }
-               if (mmc_omap_enable_poll)
-                       mod_timer(&host->switch_timer, jiffies +
-                               msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
-       } else {
-               complained = 0;
-       }
-}
-
-/* Prepare to transfer the next segment of a scatterlist */
-static void
-mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
-{
-       int dma_ch = host->dma_ch;
-       unsigned long data_addr;
-       u16 buf, frame;
-       u32 count;
-       struct scatterlist *sg = &data->sg[host->sg_idx];
-       int src_port = 0;
-       int dst_port = 0;
-       int sync_dev = 0;
-
-       data_addr = host->phys_base + OMAP_MMC_REG_DATA;
-       frame = data->blksz;
-       count = sg_dma_len(sg);
-
-       if ((data->blocks == 1) && (count > data->blksz))
-               count = frame;
-
-       host->dma_len = count;
-
-       /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx.
-        * Use 16 or 32 word frames when the blocksize is at least that large.
-        * Blocksize is usually 512 bytes; but not for some SD reads.
-        */
-       if (cpu_is_omap15xx() && frame > 32)
-               frame = 32;
-       else if (frame > 64)
-               frame = 64;
-       count /= frame;
-       frame >>= 1;
-
-       if (!(data->flags & MMC_DATA_WRITE)) {
-               buf = 0x800f | ((frame - 1) << 8);
-
-               if (cpu_class_is_omap1()) {
-                       src_port = OMAP_DMA_PORT_TIPB;
-                       dst_port = OMAP_DMA_PORT_EMIFF;
-               }
-               if (cpu_is_omap24xx())
-                       sync_dev = OMAP24XX_DMA_MMC1_RX;
-
-               omap_set_dma_src_params(dma_ch, src_port,
-                                       OMAP_DMA_AMODE_CONSTANT,
-                                       data_addr, 0, 0);
-               omap_set_dma_dest_params(dma_ch, dst_port,
-                                        OMAP_DMA_AMODE_POST_INC,
-                                        sg_dma_address(sg), 0, 0);
-               omap_set_dma_dest_data_pack(dma_ch, 1);
-               omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
-       } else {
-               buf = 0x0f80 | ((frame - 1) << 0);
-
-               if (cpu_class_is_omap1()) {
-                       src_port = OMAP_DMA_PORT_EMIFF;
-                       dst_port = OMAP_DMA_PORT_TIPB;
-               }
-               if (cpu_is_omap24xx())
-                       sync_dev = OMAP24XX_DMA_MMC1_TX;
-
-               omap_set_dma_dest_params(dma_ch, dst_port,
-                                        OMAP_DMA_AMODE_CONSTANT,
-                                        data_addr, 0, 0);
-               omap_set_dma_src_params(dma_ch, src_port,
-                                       OMAP_DMA_AMODE_POST_INC,
-                                       sg_dma_address(sg), 0, 0);
-               omap_set_dma_src_data_pack(dma_ch, 1);
-               omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
-       }
-
-       /* Max limit for DMA frame count is 0xffff */
-       BUG_ON(count > 0xffff);
-
-       OMAP_MMC_WRITE(host, BUF, buf);
-       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
-                                    frame, count, OMAP_DMA_SYNC_FRAME,
-                                    sync_dev, 0);
-}
-
-/* A scatterlist segment completed */
-static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
-{
-       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
-       struct mmc_data *mmcdat = host->data;
-
-       if (unlikely(host->dma_ch < 0)) {
-               dev_err(mmc_dev(host->mmc),
-                       "DMA callback while DMA not enabled\n");
-               return;
-       }
-       /* FIXME: We really should do something to _handle_ the errors */
-       if (ch_status & OMAP1_DMA_TOUT_IRQ) {
-               dev_err(mmc_dev(host->mmc),"DMA timeout\n");
-               return;
-       }
-       if (ch_status & OMAP_DMA_DROP_IRQ) {
-               dev_err(mmc_dev(host->mmc), "DMA sync error\n");
-               return;
-       }
-       if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
-               return;
-       }
-       mmcdat->bytes_xfered += host->dma_len;
-       host->sg_idx++;
-       if (host->sg_idx < host->sg_len) {
-               mmc_omap_prepare_dma(host, host->data);
-               omap_start_dma(host->dma_ch);
-       } else
-               mmc_omap_dma_done(host, host->data);
-}
-
-static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data)
-{
-       const char *dev_name;
-       int sync_dev, dma_ch, is_read, r;
-
-       is_read = !(data->flags & MMC_DATA_WRITE);
-       del_timer_sync(&host->dma_timer);
-       if (host->dma_ch >= 0) {
-               if (is_read == host->dma_is_read)
-                       return 0;
-               omap_free_dma(host->dma_ch);
-               host->dma_ch = -1;
-       }
-
-       if (is_read) {
-               if (host->id == 1) {
-                       sync_dev = OMAP_DMA_MMC_RX;
-                       dev_name = "MMC1 read";
-               } else {
-                       sync_dev = OMAP_DMA_MMC2_RX;
-                       dev_name = "MMC2 read";
-               }
-       } else {
-               if (host->id == 1) {
-                       sync_dev = OMAP_DMA_MMC_TX;
-                       dev_name = "MMC1 write";
-               } else {
-                       sync_dev = OMAP_DMA_MMC2_TX;
-                       dev_name = "MMC2 write";
-               }
-       }
-       r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb,
-                            host, &dma_ch);
-       if (r != 0) {
-               dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r);
-               return r;
-       }
-       host->dma_ch = dma_ch;
-       host->dma_is_read = is_read;
-
-       return 0;
-}
-
-static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
-{
-       u16 reg;
-
-       reg = OMAP_MMC_READ(host, SDIO);
-       reg &= ~(1 << 5);
-       OMAP_MMC_WRITE(host, SDIO, reg);
-       /* Set maximum timeout */
-       OMAP_MMC_WRITE(host, CTO, 0xff);
-}
-
-static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
-{
-       int timeout;
-       u16 reg;
-
-       /* Convert ns to clock cycles by assuming 20MHz frequency
-        * 1 cycle at 20MHz = 500 ns
-        */
-       timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
-
-       /* Check if we need to use timeout multiplier register */
-       reg = OMAP_MMC_READ(host, SDIO);
-       if (timeout > 0xffff) {
-               reg |= (1 << 5);
-               timeout /= 1024;
-       } else
-               reg &= ~(1 << 5);
-       OMAP_MMC_WRITE(host, SDIO, reg);
-       OMAP_MMC_WRITE(host, DTO, timeout);
-}
-
-static void
-mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
-{
-       struct mmc_data *data = req->data;
-       int i, use_dma, block_size;
-       unsigned sg_len;
-
-       host->data = data;
-       if (data == NULL) {
-               OMAP_MMC_WRITE(host, BLEN, 0);
-               OMAP_MMC_WRITE(host, NBLK, 0);
-               OMAP_MMC_WRITE(host, BUF, 0);
-               host->dma_in_use = 0;
-               set_cmd_timeout(host, req);
-               return;
-       }
-
-       block_size = data->blksz;
-
-       OMAP_MMC_WRITE(host, NBLK, data->blocks - 1);
-       OMAP_MMC_WRITE(host, BLEN, block_size - 1);
-       set_data_timeout(host, req);
-
-       /* cope with calling layer confusion; it issues "single
-        * block" writes using multi-block scatterlists.
-        */
-       sg_len = (data->blocks == 1) ? 1 : data->sg_len;
-
-       /* Only do DMA for entire blocks */
-       use_dma = host->use_dma;
-       if (use_dma) {
-               for (i = 0; i < sg_len; i++) {
-                       if ((data->sg[i].length % block_size) != 0) {
-                               use_dma = 0;
-                               break;
-                       }
-               }
-       }
-
-       host->sg_idx = 0;
-       if (use_dma) {
-               if (mmc_omap_get_dma_channel(host, data) == 0) {
-                       enum dma_data_direction dma_data_dir;
-
-                       if (data->flags & MMC_DATA_WRITE)
-                               dma_data_dir = DMA_TO_DEVICE;
-                       else
-                               dma_data_dir = DMA_FROM_DEVICE;
-
-                       host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                                               sg_len, dma_data_dir);
-                       host->total_bytes_left = 0;
-                       mmc_omap_prepare_dma(host, req->data);
-                       host->brs_received = 0;
-                       host->dma_done = 0;
-                       host->dma_in_use = 1;
-               } else
-                       use_dma = 0;
-       }
-
-       /* Revert to PIO? */
-       if (!use_dma) {
-               OMAP_MMC_WRITE(host, BUF, 0x1f1f);
-               host->total_bytes_left = data->blocks * block_size;
-               host->sg_len = sg_len;
-               mmc_omap_sg_to_buf(host);
-               host->dma_in_use = 0;
-       }
-}
-
-static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
-{
-       struct mmc_omap_host *host = mmc_priv(mmc);
-
-       WARN_ON(host->mrq != NULL);
-
-       host->mrq = req;
-
-       /* only touch fifo AFTER the controller readies it */
-       mmc_omap_prepare_data(host, req);
-       mmc_omap_start_command(host, req->cmd);
-       if (host->dma_in_use)
-               omap_start_dma(host->dma_ch);
-}
-
-static void innovator_fpga_socket_power(int on)
-{
-#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
-       if (on) {
-               fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
-                    OMAP1510_FPGA_POWER);
-       } else {
-               fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
-                    OMAP1510_FPGA_POWER);
-       }
-#endif
-}
-
-/*
- * Turn the socket power on/off. Innovator uses FPGA, most boards
- * probably use GPIO.
- */
-static void mmc_omap_power(struct mmc_omap_host *host, int on)
-{
-       if (on) {
-               if (machine_is_omap_innovator())
-                       innovator_fpga_socket_power(1);
-               else if (machine_is_omap_h2())
-                       tps65010_set_gpio_out_value(GPIO3, HIGH);
-               else if (machine_is_omap_h3())
-                       /* GPIO 4 of TPS65010 sends SD_EN signal */
-                       tps65010_set_gpio_out_value(GPIO4, HIGH);
-               else if (cpu_is_omap24xx()) {
-                       u16 reg = OMAP_MMC_READ(host, CON);
-                       OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
-               } else
-                       if (host->power_pin >= 0)
-                               omap_set_gpio_dataout(host->power_pin, 1);
-       } else {
-               if (machine_is_omap_innovator())
-                       innovator_fpga_socket_power(0);
-               else if (machine_is_omap_h2())
-                       tps65010_set_gpio_out_value(GPIO3, LOW);
-               else if (machine_is_omap_h3())
-                       tps65010_set_gpio_out_value(GPIO4, LOW);
-               else if (cpu_is_omap24xx()) {
-                       u16 reg = OMAP_MMC_READ(host, CON);
-                       OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
-               } else
-                       if (host->power_pin >= 0)
-                               omap_set_gpio_dataout(host->power_pin, 0);
-       }
-}
-
-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 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;
-
-               if (func_clk_rate / dsor > realclock)
-                       dsor++;
-
-               if (dsor > 250)
-                       dsor = 250;
-               dsor++;
-
-               if (ios->bus_width == MMC_BUS_WIDTH_4)
-                       dsor |= 1 << 15;
-       }
-
-       switch (ios->power_mode) {
-       case MMC_POWER_OFF:
-               mmc_omap_power(host, 0);
-               break;
-       case MMC_POWER_UP:
-       case MMC_POWER_ON:
-               mmc_omap_power(host, 1);
-               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
-        * goes somehow out of sync, and the POW bit is not being set,
-        * which results in the while loop below getting stuck.
-        * 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) {
-               /* Send clock cycles, poll completion */
-               OMAP_MMC_WRITE(host, IE, 0);
-               OMAP_MMC_WRITE(host, STAT, 0xffff);
-               OMAP_MMC_WRITE(host, CMD, 1 << 7);
-               while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
-               OMAP_MMC_WRITE(host, STAT, 1);
-       }
-       clk_disable(host->fclk);
-}
-
-static int mmc_omap_get_ro(struct mmc_host *mmc)
-{
-       struct mmc_omap_host *host = mmc_priv(mmc);
-
-       return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
-}
-
-static const struct mmc_host_ops mmc_omap_ops = {
-       .request        = mmc_omap_request,
-       .set_ios        = mmc_omap_set_ios,
-       .get_ro         = mmc_omap_get_ro,
-};
-
-static int __init mmc_omap_probe(struct platform_device *pdev)
-{
-       struct omap_mmc_conf *minfo = pdev->dev.platform_data;
-       struct mmc_host *mmc;
-       struct mmc_omap_host *host = NULL;
-       struct resource *res;
-       int ret = 0;
-       int irq;
-
-       if (minfo == NULL) {
-               dev_err(&pdev->dev, "platform data missing\n");
-               return -ENXIO;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       irq = platform_get_irq(pdev, 0);
-       if (res == NULL || irq < 0)
-               return -ENXIO;
-
-       res = request_mem_region(res->start, res->end - res->start + 1,
-                                pdev->name);
-       if (res == NULL)
-               return -EBUSY;
-
-       mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
-       if (mmc == NULL) {
-               ret = -ENOMEM;
-               goto err_free_mem_region;
-       }
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-
-       spin_lock_init(&host->dma_lock);
-       init_timer(&host->dma_timer);
-       host->dma_timer.function = mmc_omap_dma_timer;
-       host->dma_timer.data = (unsigned long) host;
-
-       host->id = pdev->id;
-       host->mem_res = res;
-       host->irq = irq;
-
-       if (cpu_is_omap24xx()) {
-               host->iclk = clk_get(&pdev->dev, "mmc_ick");
-               if (IS_ERR(host->iclk))
-                       goto err_free_mmc_host;
-               clk_enable(host->iclk);
-       }
-
-       if (!cpu_is_omap24xx())
-               host->fclk = clk_get(&pdev->dev, "mmc_ck");
-       else
-               host->fclk = clk_get(&pdev->dev, "mmc_fck");
-
-       if (IS_ERR(host->fclk)) {
-               ret = PTR_ERR(host->fclk);
-               goto err_free_iclk;
-       }
-
-       /* REVISIT:
-        * Also, use minfo->cover to decide how to manage
-        * the card detect sensing.
-        */
-       host->power_pin = minfo->power_pin;
-       host->switch_pin = minfo->switch_pin;
-       host->wp_pin = minfo->wp_pin;
-       host->use_dma = 1;
-       host->dma_ch = -1;
-
-       host->irq = irq;
-       host->phys_base = host->mem_res->start;
-       host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
-
-       mmc->ops = &mmc_omap_ops;
-       mmc->f_min = 400000;
-       mmc->f_max = 24000000;
-       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
-
-       if (minfo->wire4)
-                mmc->caps |= MMC_CAP_4_BIT_DATA;
-
-       /* Use scatterlist DMA to reduce per-transfer costs.
-        * NOTE max_seg_size assumption that small blocks aren't
-        * normally used (except e.g. for reading SD registers).
-        */
-       mmc->max_phys_segs = 32;
-       mmc->max_hw_segs = 32;
-       mmc->max_blk_size = 2048;       /* BLEN is 11 bits (+1) */
-       mmc->max_blk_count = 2048;      /* NBLK is 11 bits (+1) */
-       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-       mmc->max_seg_size = mmc->max_req_size;
-
-       if (host->power_pin >= 0) {
-               if ((ret = omap_request_gpio(host->power_pin)) != 0) {
-                       dev_err(mmc_dev(host->mmc),
-                               "Unable to get GPIO pin for MMC power\n");
-                       goto err_free_fclk;
-               }
-               omap_set_gpio_direction(host->power_pin, 0);
-       }
-
-       ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
-       if (ret)
-               goto err_free_power_gpio;
-
-       host->dev = &pdev->dev;
-       platform_set_drvdata(pdev, host);
-
-       if (host->switch_pin >= 0) {
-               INIT_WORK(&host->switch_work, mmc_omap_switch_handler);
-               init_timer(&host->switch_timer);
-               host->switch_timer.function = mmc_omap_switch_timer;
-               host->switch_timer.data = (unsigned long) host;
-               if (omap_request_gpio(host->switch_pin) != 0) {
-                       dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n");
-                       host->switch_pin = -1;
-                       goto no_switch;
-               }
-
-               omap_set_gpio_direction(host->switch_pin, 1);
-               ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
-                                 mmc_omap_switch_irq, IRQF_TRIGGER_RISING, DRIVER_NAME, host);
-               if (ret) {
-                       dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n");
-                       omap_free_gpio(host->switch_pin);
-                       host->switch_pin = -1;
-                       goto no_switch;
-               }
-               ret = device_create_file(&pdev->dev, &dev_attr_cover_switch);
-               if (ret == 0) {
-                       ret = device_create_file(&pdev->dev, &dev_attr_enable_poll);
-                       if (ret != 0)
-                               device_remove_file(&pdev->dev, &dev_attr_cover_switch);
-               }
-               if (ret) {
-                       dev_warn(mmc_dev(host->mmc), "Unable to create sysfs attributes\n");
-                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
-                       omap_free_gpio(host->switch_pin);
-                       host->switch_pin = -1;
-                       goto no_switch;
-               }
-               if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
-                       schedule_work(&host->switch_work);
-       }
-
-       mmc_add_host(mmc);
-
-       return 0;
-
-no_switch:
-       /* FIXME: Free other resources too. */
-       if (host) {
-               if (host->iclk && !IS_ERR(host->iclk))
-                       clk_put(host->iclk);
-               if (host->fclk && !IS_ERR(host->fclk))
-                       clk_put(host->fclk);
-               mmc_free_host(host->mmc);
-       }
-err_free_power_gpio:
-       if (host->power_pin >= 0)
-               omap_free_gpio(host->power_pin);
-err_free_fclk:
-       clk_put(host->fclk);
-err_free_iclk:
-       if (host->iclk != NULL) {
-               clk_disable(host->iclk);
-               clk_put(host->iclk);
-       }
-err_free_mmc_host:
-       mmc_free_host(host->mmc);
-err_free_mem_region:
-       release_mem_region(res->start, res->end - res->start + 1);
-       return ret;
-}
-
-static int mmc_omap_remove(struct platform_device *pdev)
-{
-       struct mmc_omap_host *host = platform_get_drvdata(pdev);
-
-       platform_set_drvdata(pdev, NULL);
-
-       BUG_ON(host == NULL);
-
-       mmc_remove_host(host->mmc);
-       free_irq(host->irq, host);
-
-       if (host->power_pin >= 0)
-               omap_free_gpio(host->power_pin);
-       if (host->switch_pin >= 0) {
-               device_remove_file(&pdev->dev, &dev_attr_enable_poll);
-               device_remove_file(&pdev->dev, &dev_attr_cover_switch);
-               free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
-               omap_free_gpio(host->switch_pin);
-               host->switch_pin = -1;
-               del_timer_sync(&host->switch_timer);
-               flush_scheduled_work();
-       }
-       if (host->iclk && !IS_ERR(host->iclk))
-               clk_put(host->iclk);
-       if (host->fclk && !IS_ERR(host->fclk))
-               clk_put(host->fclk);
-
-       release_mem_region(pdev->resource[0].start,
-                          pdev->resource[0].end - pdev->resource[0].start + 1);
-
-       mmc_free_host(host->mmc);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       int ret = 0;
-       struct mmc_omap_host *host = platform_get_drvdata(pdev);
-
-       if (host && host->suspended)
-               return 0;
-
-       if (host) {
-               ret = mmc_suspend_host(host->mmc, mesg);
-               if (ret == 0)
-                       host->suspended = 1;
-       }
-       return ret;
-}
-
-static int mmc_omap_resume(struct platform_device *pdev)
-{
-       int ret = 0;
-       struct mmc_omap_host *host = platform_get_drvdata(pdev);
-
-       if (host && !host->suspended)
-               return 0;
-
-       if (host) {
-               ret = mmc_resume_host(host->mmc);
-               if (ret == 0)
-                       host->suspended = 0;
-       }
-
-       return ret;
-}
-#else
-#define mmc_omap_suspend       NULL
-#define mmc_omap_resume                NULL
-#endif
-
-static struct platform_driver mmc_omap_driver = {
-       .probe          = mmc_omap_probe,
-       .remove         = mmc_omap_remove,
-       .suspend        = mmc_omap_suspend,
-       .resume         = mmc_omap_resume,
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-};
-
-static int __init mmc_omap_init(void)
-{
-       return platform_driver_register(&mmc_omap_driver);
-}
-
-static void __exit mmc_omap_exit(void)
-{
-       platform_driver_unregister(&mmc_omap_driver);
-}
-
-module_init(mmc_omap_init);
-module_exit(mmc_omap_exit);
-
-MODULE_DESCRIPTION("OMAP Multimedia Card driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS(DRIVER_NAME);
-MODULE_AUTHOR("Juha Yrjölä");
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
deleted file mode 100644 (file)
index 9774fc6..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- *  linux/drivers/mmc/pxa.c - PXA MMCI driver
- *
- *  Copyright (C) 2003 Russell King, 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.
- *
- *  This hardware is really sick:
- *   - No way to clear interrupts.
- *   - Have to turn off the clock whenever we touch the device.
- *   - Doesn't tell you how many data blocks were transferred.
- *  Yuck!
- *
- *     1 and 3 byte data transfers not supported
- *     max block length up to 1023
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#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>
-#include <asm/scatterlist.h>
-#include <asm/sizes.h>
-
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/mmc.h>
-
-#include "pxamci.h"
-
-#define DRIVER_NAME    "pxa2xx-mci"
-
-#define NR_SG  1
-
-struct pxamci_host {
-       struct mmc_host         *mmc;
-       spinlock_t              lock;
-       struct resource         *res;
-       void __iomem            *base;
-       int                     irq;
-       int                     dma;
-       unsigned int            clkrt;
-       unsigned int            cmdat;
-       unsigned int            imask;
-       unsigned int            power_mode;
-       struct pxamci_platform_data *pdata;
-
-       struct mmc_request      *mrq;
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;
-
-       dma_addr_t              sg_dma;
-       struct pxa_dma_desc     *sg_cpu;
-       unsigned int            dma_len;
-
-       unsigned int            dma_dir;
-};
-
-static void pxamci_stop_clock(struct pxamci_host *host)
-{
-       if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
-               unsigned long timeout = 10000;
-               unsigned int v;
-
-               writel(STOP_CLOCK, host->base + MMC_STRPCL);
-
-               do {
-                       v = readl(host->base + MMC_STAT);
-                       if (!(v & STAT_CLK_EN))
-                               break;
-                       udelay(1);
-               } while (timeout--);
-
-               if (v & STAT_CLK_EN)
-                       dev_err(mmc_dev(host->mmc), "unable to stop clock\n");
-       }
-}
-
-static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-       host->imask &= ~mask;
-       writel(host->imask, host->base + MMC_I_MASK);
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-       host->imask |= mask;
-       writel(host->imask, host->base + MMC_I_MASK);
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
-{
-       unsigned int nob = data->blocks;
-       unsigned long long clks;
-       unsigned int timeout;
-       u32 dcmd;
-       int i;
-
-       host->data = data;
-
-       if (data->flags & MMC_DATA_STREAM)
-               nob = 0xffff;
-
-       writel(nob, host->base + MMC_NOB);
-       writel(data->blksz, host->base + MMC_BLKLEN);
-
-       clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
-       do_div(clks, 1000000000UL);
-       timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
-       writel((timeout + 255) / 256, host->base + MMC_RDTO);
-
-       if (data->flags & MMC_DATA_READ) {
-               host->dma_dir = DMA_FROM_DEVICE;
-               dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
-               DRCMRTXMMC = 0;
-               DRCMRRXMMC = host->dma | DRCMR_MAPVLD;
-       } else {
-               host->dma_dir = DMA_TO_DEVICE;
-               dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
-               DRCMRRXMMC = 0;
-               DRCMRTXMMC = host->dma | DRCMR_MAPVLD;
-       }
-
-       dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
-
-       host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-                                  host->dma_dir);
-
-       for (i = 0; i < host->dma_len; i++) {
-               if (data->flags & MMC_DATA_READ) {
-                       host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
-                       host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
-               } else {
-                       host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);
-                       host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
-               }
-               host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]);
-               host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
-                                       sizeof(struct pxa_dma_desc);
-       }
-       host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;
-       wmb();
-
-       DDADR(host->dma) = host->sg_dma;
-       DCSR(host->dma) = DCSR_RUN;
-}
-
-static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
-{
-       WARN_ON(host->cmd != NULL);
-       host->cmd = cmd;
-
-       if (cmd->flags & MMC_RSP_BUSY)
-               cmdat |= CMDAT_BUSY;
-
-#define RSP_TYPE(x)    ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
-       switch (RSP_TYPE(mmc_resp_type(cmd))) {
-       case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */
-               cmdat |= CMDAT_RESP_SHORT;
-               break;
-       case RSP_TYPE(MMC_RSP_R3):
-               cmdat |= CMDAT_RESP_R3;
-               break;
-       case RSP_TYPE(MMC_RSP_R2):
-               cmdat |= CMDAT_RESP_R2;
-               break;
-       default:
-               break;
-       }
-
-       writel(cmd->opcode, host->base + MMC_CMD);
-       writel(cmd->arg >> 16, host->base + MMC_ARGH);
-       writel(cmd->arg & 0xffff, host->base + MMC_ARGL);
-       writel(cmdat, host->base + MMC_CMDAT);
-       writel(host->clkrt, host->base + MMC_CLKRT);
-
-       writel(START_CLOCK, host->base + MMC_STRPCL);
-
-       pxamci_enable_irq(host, END_CMD_RES);
-}
-
-static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
-{
-       host->mrq = NULL;
-       host->cmd = NULL;
-       host->data = NULL;
-       mmc_request_done(host->mmc, mrq);
-}
-
-static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
-{
-       struct mmc_command *cmd = host->cmd;
-       int i;
-       u32 v;
-
-       if (!cmd)
-               return 0;
-
-       host->cmd = NULL;
-
-       /*
-        * Did I mention this is Sick.  We always need to
-        * discard the upper 8 bits of the first 16-bit word.
-        */
-       v = readl(host->base + MMC_RES) & 0xffff;
-       for (i = 0; i < 4; i++) {
-               u32 w1 = readl(host->base + MMC_RES) & 0xffff;
-               u32 w2 = readl(host->base + MMC_RES) & 0xffff;
-               cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8;
-               v = w2;
-       }
-
-       if (stat & STAT_TIME_OUT_RESPONSE) {
-               cmd->error = MMC_ERR_TIMEOUT;
-       } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
-#ifdef CONFIG_PXA27x
-               /*
-                * workaround for erratum #42:
-                * Intel PXA27x Family Processor Specification Update Rev 001
-                */
-               if (cmd->opcode == MMC_ALL_SEND_CID ||
-                   cmd->opcode == MMC_SEND_CSD ||
-                   cmd->opcode == MMC_SEND_CID) {
-                       /* a bogus CRC error can appear if the msb of
-                          the 15 byte response is a one */
-                       if ((cmd->resp[0] & 0x80000000) == 0)
-                               cmd->error = MMC_ERR_BADCRC;
-               } else {
-                       pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode);
-               }
-#else
-               cmd->error = MMC_ERR_BADCRC;
-#endif
-       }
-
-       pxamci_disable_irq(host, END_CMD_RES);
-       if (host->data && cmd->error == MMC_ERR_NONE) {
-               pxamci_enable_irq(host, DATA_TRAN_DONE);
-       } else {
-               pxamci_finish_request(host, host->mrq);
-       }
-
-       return 1;
-}
-
-static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
-{
-       struct mmc_data *data = host->data;
-
-       if (!data)
-               return 0;
-
-       DCSR(host->dma) = 0;
-       dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
-                    host->dma_dir);
-
-       if (stat & STAT_READ_TIME_OUT)
-               data->error = MMC_ERR_TIMEOUT;
-       else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR))
-               data->error = MMC_ERR_BADCRC;
-
-       /*
-        * There appears to be a hardware design bug here.  There seems to
-        * be no way to find out how much data was transferred to the card.
-        * This means that if there was an error on any block, we mark all
-        * data blocks as being in error.
-        */
-       if (data->error == MMC_ERR_NONE)
-               data->bytes_xfered = data->blocks * data->blksz;
-       else
-               data->bytes_xfered = 0;
-
-       pxamci_disable_irq(host, DATA_TRAN_DONE);
-
-       host->data = NULL;
-       if (host->mrq->stop) {
-               pxamci_stop_clock(host);
-               pxamci_start_cmd(host, host->mrq->stop, 0);
-       } else {
-               pxamci_finish_request(host, host->mrq);
-       }
-
-       return 1;
-}
-
-static irqreturn_t pxamci_irq(int irq, void *devid)
-{
-       struct pxamci_host *host = devid;
-       unsigned int ireg;
-       int handled = 0;
-
-       ireg = readl(host->base + MMC_I_REG);
-
-       if (ireg) {
-               unsigned stat = readl(host->base + MMC_STAT);
-
-               pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
-
-               if (ireg & END_CMD_RES)
-                       handled |= pxamci_cmd_done(host, stat);
-               if (ireg & DATA_TRAN_DONE)
-                       handled |= pxamci_data_done(host, stat);
-       }
-
-       return IRQ_RETVAL(handled);
-}
-
-static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct pxamci_host *host = mmc_priv(mmc);
-       unsigned int cmdat;
-
-       WARN_ON(host->mrq != NULL);
-
-       host->mrq = mrq;
-
-       pxamci_stop_clock(host);
-
-       cmdat = host->cmdat;
-       host->cmdat &= ~CMDAT_INIT;
-
-       if (mrq->data) {
-               pxamci_setup_data(host, mrq->data);
-
-               cmdat &= ~CMDAT_BUSY;
-               cmdat |= CMDAT_DATAEN | CMDAT_DMAEN;
-               if (mrq->data->flags & MMC_DATA_WRITE)
-                       cmdat |= CMDAT_WRITE;
-
-               if (mrq->data->flags & MMC_DATA_STREAM)
-                       cmdat |= CMDAT_STREAM;
-       }
-
-       pxamci_start_cmd(host, mrq->cmd, cmdat);
-}
-
-static int pxamci_get_ro(struct mmc_host *mmc)
-{
-       struct pxamci_host *host = mmc_priv(mmc);
-
-       if (host->pdata && host->pdata->get_ro)
-               return host->pdata->get_ro(mmc_dev(mmc));
-       /* Host doesn't support read only detection so assume writeable */
-       return 0;
-}
-
-static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct pxamci_host *host = mmc_priv(mmc);
-
-       if (ios->clock) {
-               unsigned int clk = CLOCKRATE / ios->clock;
-               if (CLOCKRATE / clk > ios->clock)
-                       clk <<= 1;
-               host->clkrt = fls(clk) - 1;
-               pxa_set_cken(CKEN12_MMC, 1);
-
-               /*
-                * we write clkrt on the next command
-                */
-       } else {
-               pxamci_stop_clock(host);
-               pxa_set_cken(CKEN12_MMC, 0);
-       }
-
-       if (host->power_mode != ios->power_mode) {
-               host->power_mode = ios->power_mode;
-
-               if (host->pdata && host->pdata->setpower)
-                       host->pdata->setpower(mmc_dev(mmc), ios->vdd);
-
-               if (ios->power_mode == MMC_POWER_ON)
-                       host->cmdat |= CMDAT_INIT;
-       }
-
-       pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
-                host->clkrt, host->cmdat);
-}
-
-static const struct mmc_host_ops pxamci_ops = {
-       .request        = pxamci_request,
-       .get_ro         = pxamci_get_ro,
-       .set_ios        = pxamci_set_ios,
-};
-
-static void pxamci_dma_irq(int dma, void *devid)
-{
-       printk(KERN_ERR "DMA%d: IRQ???\n", dma);
-       DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-}
-
-static irqreturn_t pxamci_detect_irq(int irq, void *devid)
-{
-       struct pxamci_host *host = mmc_priv(devid);
-
-       mmc_detect_change(devid, host->pdata->detect_delay);
-       return IRQ_HANDLED;
-}
-
-static int pxamci_probe(struct platform_device *pdev)
-{
-       struct mmc_host *mmc;
-       struct pxamci_host *host = NULL;
-       struct resource *r;
-       int ret, irq;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       irq = platform_get_irq(pdev, 0);
-       if (!r || irq < 0)
-               return -ENXIO;
-
-       r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
-       if (!r)
-               return -EBUSY;
-
-       mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev);
-       if (!mmc) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       mmc->ops = &pxamci_ops;
-       mmc->f_min = CLOCKRATE_MIN;
-       mmc->f_max = CLOCKRATE_MAX;
-
-       /*
-        * We can do SG-DMA, but we don't because we never know how much
-        * data we successfully wrote to the card.
-        */
-       mmc->max_phys_segs = NR_SG;
-
-       /*
-        * Our hardware DMA can handle a maximum of one page per SG entry.
-        */
-       mmc->max_seg_size = PAGE_SIZE;
-
-       /*
-        * Block length register is 10 bits.
-        */
-       mmc->max_blk_size = 1023;
-
-       /*
-        * Block count register is 16 bits.
-        */
-       mmc->max_blk_count = 65535;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-       host->dma = -1;
-       host->pdata = pdev->dev.platform_data;
-       mmc->ocr_avail = host->pdata ?
-                        host->pdata->ocr_mask :
-                        MMC_VDD_32_33|MMC_VDD_33_34;
-
-       host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);
-       if (!host->sg_cpu) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       spin_lock_init(&host->lock);
-       host->res = r;
-       host->irq = irq;
-       host->imask = MMC_I_MASK_ALL;
-
-       host->base = ioremap(r->start, SZ_4K);
-       if (!host->base) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       /*
-        * Ensure that the host controller is shut down, and setup
-        * with our defaults.
-        */
-       pxamci_stop_clock(host);
-       writel(0, host->base + MMC_SPI);
-       writel(64, host->base + MMC_RESTO);
-       writel(host->imask, host->base + MMC_I_MASK);
-
-       host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,
-                                   pxamci_dma_irq, host);
-       if (host->dma < 0) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
-       if (ret)
-               goto out;
-
-       platform_set_drvdata(pdev, mmc);
-
-       if (host->pdata && host->pdata->init)
-               host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc);
-
-       mmc_add_host(mmc);
-
-       return 0;
-
- out:
-       if (host) {
-               if (host->dma >= 0)
-                       pxa_free_dma(host->dma);
-               if (host->base)
-                       iounmap(host->base);
-               if (host->sg_cpu)
-                       dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
-       }
-       if (mmc)
-               mmc_free_host(mmc);
-       release_resource(r);
-       return ret;
-}
-
-static int pxamci_remove(struct platform_device *pdev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-
-       platform_set_drvdata(pdev, NULL);
-
-       if (mmc) {
-               struct pxamci_host *host = mmc_priv(mmc);
-
-               if (host->pdata && host->pdata->exit)
-                       host->pdata->exit(&pdev->dev, mmc);
-
-               mmc_remove_host(mmc);
-
-               pxamci_stop_clock(host);
-               writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
-                      END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
-                      host->base + MMC_I_MASK);
-
-               DRCMRRXMMC = 0;
-               DRCMRTXMMC = 0;
-
-               free_irq(host->irq, host);
-               pxa_free_dma(host->dma);
-               iounmap(host->base);
-               dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
-
-               release_resource(host->res);
-
-               mmc_free_host(mmc);
-       }
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int pxamci_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-       int ret = 0;
-
-       if (mmc)
-               ret = mmc_suspend_host(mmc, state);
-
-       return ret;
-}
-
-static int pxamci_resume(struct platform_device *dev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-       int ret = 0;
-
-       if (mmc)
-               ret = mmc_resume_host(mmc);
-
-       return ret;
-}
-#else
-#define pxamci_suspend NULL
-#define pxamci_resume  NULL
-#endif
-
-static struct platform_driver pxamci_driver = {
-       .probe          = pxamci_probe,
-       .remove         = pxamci_remove,
-       .suspend        = pxamci_suspend,
-       .resume         = pxamci_resume,
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-};
-
-static int __init pxamci_init(void)
-{
-       return platform_driver_register(&pxamci_driver);
-}
-
-static void __exit pxamci_exit(void)
-{
-       platform_driver_unregister(&pxamci_driver);
-}
-
-module_init(pxamci_init);
-module_exit(pxamci_exit);
-
-MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/pxamci.h b/drivers/mmc/pxamci.h
deleted file mode 100644 (file)
index 1b16322..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#undef MMC_STRPCL
-#undef MMC_STAT
-#undef MMC_CLKRT
-#undef MMC_SPI
-#undef MMC_CMDAT
-#undef MMC_RESTO
-#undef MMC_RDTO
-#undef MMC_BLKLEN
-#undef MMC_NOB
-#undef MMC_PRTBUF
-#undef MMC_I_MASK
-#undef END_CMD_RES
-#undef PRG_DONE
-#undef DATA_TRAN_DONE
-#undef MMC_I_REG
-#undef MMC_CMD
-#undef MMC_ARGH
-#undef MMC_ARGL
-#undef MMC_RES
-#undef MMC_RXFIFO
-#undef MMC_TXFIFO
-
-#define MMC_STRPCL     0x0000
-#define STOP_CLOCK             (1 << 0)
-#define START_CLOCK            (2 << 0)
-
-#define MMC_STAT       0x0004
-#define STAT_END_CMD_RES               (1 << 13)
-#define STAT_PRG_DONE                  (1 << 12)
-#define STAT_DATA_TRAN_DONE            (1 << 11)
-#define STAT_CLK_EN                    (1 << 8)
-#define STAT_RECV_FIFO_FULL            (1 << 7)
-#define STAT_XMIT_FIFO_EMPTY           (1 << 6)
-#define STAT_RES_CRC_ERR               (1 << 5)
-#define STAT_SPI_READ_ERROR_TOKEN      (1 << 4)
-#define STAT_CRC_READ_ERROR            (1 << 3)
-#define STAT_CRC_WRITE_ERROR           (1 << 2)
-#define STAT_TIME_OUT_RESPONSE         (1 << 1)
-#define STAT_READ_TIME_OUT             (1 << 0)
-
-#define MMC_CLKRT      0x0008          /* 3 bit */
-
-#define MMC_SPI                0x000c
-#define SPI_CS_ADDRESS         (1 << 3)
-#define SPI_CS_EN              (1 << 2)
-#define CRC_ON                 (1 << 1)
-#define SPI_EN                 (1 << 0)
-
-#define MMC_CMDAT      0x0010
-#define CMDAT_DMAEN            (1 << 7)
-#define CMDAT_INIT             (1 << 6)
-#define CMDAT_BUSY             (1 << 5)
-#define CMDAT_STREAM           (1 << 4)        /* 1 = stream */
-#define CMDAT_WRITE            (1 << 3)        /* 1 = write */
-#define CMDAT_DATAEN           (1 << 2)
-#define CMDAT_RESP_NONE                (0 << 0)
-#define CMDAT_RESP_SHORT       (1 << 0)
-#define CMDAT_RESP_R2          (2 << 0)
-#define CMDAT_RESP_R3          (3 << 0)
-
-#define MMC_RESTO      0x0014  /* 7 bit */
-
-#define MMC_RDTO       0x0018  /* 16 bit */
-
-#define MMC_BLKLEN     0x001c  /* 10 bit */
-
-#define MMC_NOB                0x0020  /* 16 bit */
-
-#define MMC_PRTBUF     0x0024
-#define BUF_PART_FULL          (1 << 0)
-
-#define MMC_I_MASK     0x0028
-
-/*PXA27x MMC interrupts*/
-#define SDIO_SUSPEND_ACK       (1 << 12)
-#define SDIO_INT               (1 << 11)
-#define RD_STALLED             (1 << 10)
-#define RES_ERR                (1 << 9)
-#define DAT_ERR                (1 << 8)
-#define TINT                   (1 << 7)
-
-/*PXA2xx MMC interrupts*/
-#define TXFIFO_WR_REQ          (1 << 6)
-#define RXFIFO_RD_REQ          (1 << 5)
-#define CLK_IS_OFF             (1 << 4)
-#define STOP_CMD               (1 << 3)
-#define END_CMD_RES            (1 << 2)
-#define PRG_DONE               (1 << 1)
-#define DATA_TRAN_DONE         (1 << 0)
-
-#ifdef CONFIG_PXA27x
-#define MMC_I_MASK_ALL          0x00001fff
-#else
-#define MMC_I_MASK_ALL          0x0000007f
-#endif
-
-#define MMC_I_REG      0x002c
-/* same as MMC_I_MASK */
-
-#define MMC_CMD                0x0030
-
-#define MMC_ARGH       0x0034  /* 16 bit */
-
-#define MMC_ARGL       0x0038  /* 16 bit */
-
-#define MMC_RES                0x003c  /* 16 bit */
-
-#define MMC_RXFIFO     0x0040  /* 8 bit */
-
-#define MMC_TXFIFO     0x0044  /* 8 bit */
-
-/*
- * The base MMC clock rate
- */
-#ifdef CONFIG_PXA27x
-#define CLOCKRATE_MIN  304688
-#define CLOCKRATE_MAX  19500000
-#else
-#define CLOCKRATE_MIN  312500
-#define CLOCKRATE_MAX  20000000
-#endif
-
-#define CLOCKRATE      CLOCKRATE_MAX
-
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
deleted file mode 100644 (file)
index d749f08..0000000
+++ /dev/null
@@ -1,1550 +0,0 @@
-/*
- *  linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
- *
- *  Copyright (C) 2005-2006 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.
- */
-
-#include <linux/delay.h>
-#include <linux/highmem.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-
-#include <asm/scatterlist.h>
-
-#include "sdhci.h"
-
-#define DRIVER_NAME "sdhci"
-
-#define DBG(f, x...) \
-       pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
-
-static unsigned int debug_nodma = 0;
-static unsigned int debug_forcedma = 0;
-static unsigned int debug_quirks = 0;
-
-#define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
-#define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
-/* Controller doesn't like some resets when there is no card inserted. */
-#define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
-#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
-
-static const struct pci_device_id pci_ids[] __devinitdata = {
-       {
-               .vendor         = PCI_VENDOR_ID_RICOH,
-               .device         = PCI_DEVICE_ID_RICOH_R5C822,
-               .subvendor      = PCI_VENDOR_ID_IBM,
-               .subdevice      = PCI_ANY_ID,
-               .driver_data    = SDHCI_QUIRK_CLOCK_BEFORE_RESET |
-                                 SDHCI_QUIRK_FORCE_DMA,
-       },
-
-       {
-               .vendor         = PCI_VENDOR_ID_RICOH,
-               .device         = PCI_DEVICE_ID_RICOH_R5C822,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .driver_data    = SDHCI_QUIRK_FORCE_DMA |
-                                 SDHCI_QUIRK_NO_CARD_NO_RESET,
-       },
-
-       {
-               .vendor         = PCI_VENDOR_ID_TI,
-               .device         = PCI_DEVICE_ID_TI_XX21_XX11_SD,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .driver_data    = SDHCI_QUIRK_FORCE_DMA,
-       },
-
-       {
-               .vendor         = PCI_VENDOR_ID_ENE,
-               .device         = PCI_DEVICE_ID_ENE_CB712_SD,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
-       },
-
-       {       /* Generic SD host controller */
-               PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
-       },
-
-       { /* end: all zeroes */ },
-};
-
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
-static void sdhci_finish_data(struct sdhci_host *);
-
-static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
-static void sdhci_finish_command(struct sdhci_host *);
-
-static void sdhci_dumpregs(struct sdhci_host *host)
-{
-       printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
-
-       printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
-               readl(host->ioaddr + SDHCI_DMA_ADDRESS),
-               readw(host->ioaddr + SDHCI_HOST_VERSION));
-       printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
-               readw(host->ioaddr + SDHCI_BLOCK_SIZE),
-               readw(host->ioaddr + SDHCI_BLOCK_COUNT));
-       printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_ARGUMENT),
-               readw(host->ioaddr + SDHCI_TRANSFER_MODE));
-       printk(KERN_DEBUG DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_PRESENT_STATE),
-               readb(host->ioaddr + SDHCI_HOST_CONTROL));
-       printk(KERN_DEBUG DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
-               readb(host->ioaddr + SDHCI_POWER_CONTROL),
-               readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
-       printk(KERN_DEBUG DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
-               readb(host->ioaddr + SDHCI_WALK_UP_CONTROL),
-               readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
-       printk(KERN_DEBUG DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
-               readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
-               readl(host->ioaddr + SDHCI_INT_STATUS));
-       printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_INT_ENABLE),
-               readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
-       printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
-               readw(host->ioaddr + SDHCI_ACMD12_ERR),
-               readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
-       printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Max curr: 0x%08x\n",
-               readl(host->ioaddr + SDHCI_CAPABILITIES),
-               readl(host->ioaddr + SDHCI_MAX_CURRENT));
-
-       printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
-}
-
-/*****************************************************************************\
- *                                                                           *
- * Low level functions                                                       *
- *                                                                           *
-\*****************************************************************************/
-
-static void sdhci_reset(struct sdhci_host *host, u8 mask)
-{
-       unsigned long timeout;
-
-       if (host->chip->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
-               if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
-                       SDHCI_CARD_PRESENT))
-                       return;
-       }
-
-       writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
-
-       if (mask & SDHCI_RESET_ALL)
-               host->clock = 0;
-
-       /* Wait max 100 ms */
-       timeout = 100;
-
-       /* hw clears the bit when it's done */
-       while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
-               if (timeout == 0) {
-                       printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
-                               mmc_hostname(host->mmc), (int)mask);
-                       sdhci_dumpregs(host);
-                       return;
-               }
-               timeout--;
-               mdelay(1);
-       }
-}
-
-static void sdhci_init(struct sdhci_host *host)
-{
-       u32 intmask;
-
-       sdhci_reset(host, SDHCI_RESET_ALL);
-
-       intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
-               SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
-               SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
-               SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
-               SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
-               SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
-
-       writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
-       writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
-}
-
-static void sdhci_activate_led(struct sdhci_host *host)
-{
-       u8 ctrl;
-
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
-       ctrl |= SDHCI_CTRL_LED;
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
-}
-
-static void sdhci_deactivate_led(struct sdhci_host *host)
-{
-       u8 ctrl;
-
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
-       ctrl &= ~SDHCI_CTRL_LED;
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
-}
-
-/*****************************************************************************\
- *                                                                           *
- * Core functions                                                            *
- *                                                                           *
-\*****************************************************************************/
-
-static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
-{
-       return page_address(host->cur_sg->page) + host->cur_sg->offset;
-}
-
-static inline int sdhci_next_sg(struct sdhci_host* host)
-{
-       /*
-        * Skip to next SG entry.
-        */
-       host->cur_sg++;
-       host->num_sg--;
-
-       /*
-        * Any entries left?
-        */
-       if (host->num_sg > 0) {
-               host->offset = 0;
-               host->remain = host->cur_sg->length;
-       }
-
-       return host->num_sg;
-}
-
-static void sdhci_read_block_pio(struct sdhci_host *host)
-{
-       int blksize, chunk_remain;
-       u32 data;
-       char *buffer;
-       int size;
-
-       DBG("PIO reading\n");
-
-       blksize = host->data->blksz;
-       chunk_remain = 0;
-       data = 0;
-
-       buffer = sdhci_sg_to_buffer(host) + host->offset;
-
-       while (blksize) {
-               if (chunk_remain == 0) {
-                       data = readl(host->ioaddr + SDHCI_BUFFER);
-                       chunk_remain = min(blksize, 4);
-               }
-
-               size = min(host->size, host->remain);
-               size = min(size, chunk_remain);
-
-               chunk_remain -= size;
-               blksize -= size;
-               host->offset += size;
-               host->remain -= size;
-               host->size -= size;
-               while (size) {
-                       *buffer = data & 0xFF;
-                       buffer++;
-                       data >>= 8;
-                       size--;
-               }
-
-               if (host->remain == 0) {
-                       if (sdhci_next_sg(host) == 0) {
-                               BUG_ON(blksize != 0);
-                               return;
-                       }
-                       buffer = sdhci_sg_to_buffer(host);
-               }
-       }
-}
-
-static void sdhci_write_block_pio(struct sdhci_host *host)
-{
-       int blksize, chunk_remain;
-       u32 data;
-       char *buffer;
-       int bytes, size;
-
-       DBG("PIO writing\n");
-
-       blksize = host->data->blksz;
-       chunk_remain = 4;
-       data = 0;
-
-       bytes = 0;
-       buffer = sdhci_sg_to_buffer(host) + host->offset;
-
-       while (blksize) {
-               size = min(host->size, host->remain);
-               size = min(size, chunk_remain);
-
-               chunk_remain -= size;
-               blksize -= size;
-               host->offset += size;
-               host->remain -= size;
-               host->size -= size;
-               while (size) {
-                       data >>= 8;
-                       data |= (u32)*buffer << 24;
-                       buffer++;
-                       size--;
-               }
-
-               if (chunk_remain == 0) {
-                       writel(data, host->ioaddr + SDHCI_BUFFER);
-                       chunk_remain = min(blksize, 4);
-               }
-
-               if (host->remain == 0) {
-                       if (sdhci_next_sg(host) == 0) {
-                               BUG_ON(blksize != 0);
-                               return;
-                       }
-                       buffer = sdhci_sg_to_buffer(host);
-               }
-       }
-}
-
-static void sdhci_transfer_pio(struct sdhci_host *host)
-{
-       u32 mask;
-
-       BUG_ON(!host->data);
-
-       if (host->size == 0)
-               return;
-
-       if (host->data->flags & MMC_DATA_READ)
-               mask = SDHCI_DATA_AVAILABLE;
-       else
-               mask = SDHCI_SPACE_AVAILABLE;
-
-       while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
-               if (host->data->flags & MMC_DATA_READ)
-                       sdhci_read_block_pio(host);
-               else
-                       sdhci_write_block_pio(host);
-
-               if (host->size == 0)
-                       break;
-
-               BUG_ON(host->num_sg == 0);
-       }
-
-       DBG("PIO transfer complete.\n");
-}
-
-static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
-{
-       u8 count;
-       unsigned target_timeout, current_timeout;
-
-       WARN_ON(host->data);
-
-       if (data == NULL)
-               return;
-
-       DBG("blksz %04x blks %04x flags %08x\n",
-               data->blksz, data->blocks, data->flags);
-       DBG("tsac %d ms nsac %d clk\n",
-               data->timeout_ns / 1000000, data->timeout_clks);
-
-       /* Sanity checks */
-       BUG_ON(data->blksz * data->blocks > 524288);
-       BUG_ON(data->blksz > host->mmc->max_blk_size);
-       BUG_ON(data->blocks > 65535);
-
-       /* timeout in us */
-       target_timeout = data->timeout_ns / 1000 +
-               data->timeout_clks / host->clock;
-
-       /*
-        * Figure out needed cycles.
-        * We do this in steps in order to fit inside a 32 bit int.
-        * The first step is the minimum timeout, which will have a
-        * minimum resolution of 6 bits:
-        * (1) 2^13*1000 > 2^22,
-        * (2) host->timeout_clk < 2^16
-        *     =>
-        *     (1) / (2) > 2^6
-        */
-       count = 0;
-       current_timeout = (1 << 13) * 1000 / host->timeout_clk;
-       while (current_timeout < target_timeout) {
-               count++;
-               current_timeout <<= 1;
-               if (count >= 0xF)
-                       break;
-       }
-
-       if (count >= 0xF) {
-               printk(KERN_WARNING "%s: Too large timeout requested!\n",
-                       mmc_hostname(host->mmc));
-               count = 0xE;
-       }
-
-       writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
-
-       if (host->flags & SDHCI_USE_DMA) {
-               int count;
-
-               count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len,
-                       (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
-               BUG_ON(count != 1);
-
-               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;
-
-               host->offset = 0;
-               host->remain = host->cur_sg->length;
-       }
-
-       /* We do not handle DMA boundaries, so set it to max (512 KiB) */
-       writew(SDHCI_MAKE_BLKSZ(7, data->blksz),
-               host->ioaddr + SDHCI_BLOCK_SIZE);
-       writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
-}
-
-static void sdhci_set_transfer_mode(struct sdhci_host *host,
-       struct mmc_data *data)
-{
-       u16 mode;
-
-       WARN_ON(host->data);
-
-       if (data == NULL)
-               return;
-
-       mode = SDHCI_TRNS_BLK_CNT_EN;
-       if (data->blocks > 1)
-               mode |= SDHCI_TRNS_MULTI;
-       if (data->flags & MMC_DATA_READ)
-               mode |= SDHCI_TRNS_READ;
-       if (host->flags & SDHCI_USE_DMA)
-               mode |= SDHCI_TRNS_DMA;
-
-       writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
-}
-
-static void sdhci_finish_data(struct sdhci_host *host)
-{
-       struct mmc_data *data;
-       u16 blocks;
-
-       BUG_ON(!host->data);
-
-       data = host->data;
-       host->data = NULL;
-
-       if (host->flags & SDHCI_USE_DMA) {
-               pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len,
-                       (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
-       }
-
-       /*
-        * Controller doesn't count down when in single block mode.
-        */
-       if ((data->blocks == 1) && (data->error == MMC_ERR_NONE))
-               blocks = 0;
-       else
-               blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
-       data->bytes_xfered = data->blksz * (data->blocks - blocks);
-
-       if ((data->error == MMC_ERR_NONE) && blocks) {
-               printk(KERN_ERR "%s: Controller signalled completion even "
-                       "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);
-
-       if (data->stop) {
-               /*
-                * The controller needs a reset of internal state machines
-                * upon error conditions.
-                */
-               if (data->error != MMC_ERR_NONE) {
-                       sdhci_reset(host, SDHCI_RESET_CMD);
-                       sdhci_reset(host, SDHCI_RESET_DATA);
-               }
-
-               sdhci_send_command(host, data->stop);
-       } else
-               tasklet_schedule(&host->finish_tasklet);
-}
-
-static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
-{
-       int flags;
-       u32 mask;
-       unsigned long timeout;
-
-       WARN_ON(host->cmd);
-
-       DBG("Sending cmd (%x)\n", cmd->opcode);
-
-       /* Wait max 10 ms */
-       timeout = 10;
-
-       mask = SDHCI_CMD_INHIBIT;
-       if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
-               mask |= SDHCI_DATA_INHIBIT;
-
-       /* We shouldn't wait for data inihibit for stop commands, even
-          though they might use busy signaling */
-       if (host->mrq->data && (cmd == host->mrq->data->stop))
-               mask &= ~SDHCI_DATA_INHIBIT;
-
-       while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
-               if (timeout == 0) {
-                       printk(KERN_ERR "%s: Controller never released "
-                               "inhibit bit(s).\n", mmc_hostname(host->mmc));
-                       sdhci_dumpregs(host);
-                       cmd->error = MMC_ERR_FAILED;
-                       tasklet_schedule(&host->finish_tasklet);
-                       return;
-               }
-               timeout--;
-               mdelay(1);
-       }
-
-       mod_timer(&host->timer, jiffies + 10 * HZ);
-
-       host->cmd = cmd;
-
-       sdhci_prepare_data(host, cmd->data);
-
-       writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
-
-       sdhci_set_transfer_mode(host, cmd->data);
-
-       if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
-               printk(KERN_ERR "%s: Unsupported response type!\n",
-                       mmc_hostname(host->mmc));
-               cmd->error = MMC_ERR_INVALID;
-               tasklet_schedule(&host->finish_tasklet);
-               return;
-       }
-
-       if (!(cmd->flags & MMC_RSP_PRESENT))
-               flags = SDHCI_CMD_RESP_NONE;
-       else if (cmd->flags & MMC_RSP_136)
-               flags = SDHCI_CMD_RESP_LONG;
-       else if (cmd->flags & MMC_RSP_BUSY)
-               flags = SDHCI_CMD_RESP_SHORT_BUSY;
-       else
-               flags = SDHCI_CMD_RESP_SHORT;
-
-       if (cmd->flags & MMC_RSP_CRC)
-               flags |= SDHCI_CMD_CRC;
-       if (cmd->flags & MMC_RSP_OPCODE)
-               flags |= SDHCI_CMD_INDEX;
-       if (cmd->data)
-               flags |= SDHCI_CMD_DATA;
-
-       writew(SDHCI_MAKE_CMD(cmd->opcode, flags),
-               host->ioaddr + SDHCI_COMMAND);
-}
-
-static void sdhci_finish_command(struct sdhci_host *host)
-{
-       int i;
-
-       BUG_ON(host->cmd == NULL);
-
-       if (host->cmd->flags & MMC_RSP_PRESENT) {
-               if (host->cmd->flags & MMC_RSP_136) {
-                       /* CRC is stripped so we need to do some shifting. */
-                       for (i = 0;i < 4;i++) {
-                               host->cmd->resp[i] = readl(host->ioaddr +
-                                       SDHCI_RESPONSE + (3-i)*4) << 8;
-                               if (i != 3)
-                                       host->cmd->resp[i] |=
-                                               readb(host->ioaddr +
-                                               SDHCI_RESPONSE + (3-i)*4-1);
-                       }
-               } else {
-                       host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
-               }
-       }
-
-       host->cmd->error = MMC_ERR_NONE;
-
-       DBG("Ending cmd (%x)\n", host->cmd->opcode);
-
-       if (host->cmd->data)
-               host->data = host->cmd->data;
-       else
-               tasklet_schedule(&host->finish_tasklet);
-
-       host->cmd = NULL;
-}
-
-static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
-{
-       int div;
-       u16 clk;
-       unsigned long timeout;
-
-       if (clock == host->clock)
-               return;
-
-       writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
-
-       if (clock == 0)
-               goto out;
-
-       for (div = 1;div < 256;div *= 2) {
-               if ((host->max_clk / div) <= clock)
-                       break;
-       }
-       div >>= 1;
-
-       clk = div << SDHCI_DIVIDER_SHIFT;
-       clk |= SDHCI_CLOCK_INT_EN;
-       writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
-
-       /* Wait max 10 ms */
-       timeout = 10;
-       while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
-               & SDHCI_CLOCK_INT_STABLE)) {
-               if (timeout == 0) {
-                       printk(KERN_ERR "%s: Internal clock never "
-                               "stabilised.\n", mmc_hostname(host->mmc));
-                       sdhci_dumpregs(host);
-                       return;
-               }
-               timeout--;
-               mdelay(1);
-       }
-
-       clk |= SDHCI_CLOCK_CARD_EN;
-       writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
-
-out:
-       host->clock = clock;
-}
-
-static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
-{
-       u8 pwr;
-
-       if (host->power == power)
-               return;
-
-       if (power == (unsigned short)-1) {
-               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
-               goto out;
-       }
-
-       /*
-        * Spec says that we should clear the power reg before setting
-        * a new value. Some controllers don't seem to like this though.
-        */
-       if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
-               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
-
-       pwr = SDHCI_POWER_ON;
-
-       switch (power) {
-       case MMC_VDD_170:
-       case MMC_VDD_180:
-       case MMC_VDD_190:
-               pwr |= SDHCI_POWER_180;
-               break;
-       case MMC_VDD_290:
-       case MMC_VDD_300:
-       case MMC_VDD_310:
-               pwr |= SDHCI_POWER_300;
-               break;
-       case MMC_VDD_320:
-       case MMC_VDD_330:
-       case MMC_VDD_340:
-               pwr |= SDHCI_POWER_330;
-               break;
-       default:
-               BUG();
-       }
-
-       writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
-
-out:
-       host->power = power;
-}
-
-/*****************************************************************************\
- *                                                                           *
- * MMC callbacks                                                             *
- *                                                                           *
-\*****************************************************************************/
-
-static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct sdhci_host *host;
-       unsigned long flags;
-
-       host = mmc_priv(mmc);
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       WARN_ON(host->mrq != NULL);
-
-       sdhci_activate_led(host);
-
-       host->mrq = mrq;
-
-       if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
-               host->mrq->cmd->error = MMC_ERR_TIMEOUT;
-               tasklet_schedule(&host->finish_tasklet);
-       } else
-               sdhci_send_command(host, mrq->cmd);
-
-       mmiowb();
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct sdhci_host *host;
-       unsigned long flags;
-       u8 ctrl;
-
-       host = mmc_priv(mmc);
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       /*
-        * Reset the chip on each power off.
-        * Should clear out any weird states.
-        */
-       if (ios->power_mode == MMC_POWER_OFF) {
-               writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
-               sdhci_init(host);
-       }
-
-       sdhci_set_clock(host, ios->clock);
-
-       if (ios->power_mode == MMC_POWER_OFF)
-               sdhci_set_power(host, -1);
-       else
-               sdhci_set_power(host, ios->vdd);
-
-       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
-
-       if (ios->bus_width == MMC_BUS_WIDTH_4)
-               ctrl |= SDHCI_CTRL_4BITBUS;
-       else
-               ctrl &= ~SDHCI_CTRL_4BITBUS;
-
-       if (ios->timing == MMC_TIMING_SD_HS)
-               ctrl |= SDHCI_CTRL_HISPD;
-       else
-               ctrl &= ~SDHCI_CTRL_HISPD;
-
-       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
-
-       mmiowb();
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static int sdhci_get_ro(struct mmc_host *mmc)
-{
-       struct sdhci_host *host;
-       unsigned long flags;
-       int present;
-
-       host = mmc_priv(mmc);
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
-
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       return !(present & SDHCI_WRITE_PROTECT);
-}
-
-static const struct mmc_host_ops sdhci_ops = {
-       .request        = sdhci_request,
-       .set_ios        = sdhci_set_ios,
-       .get_ro         = sdhci_get_ro,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Tasklets                                                                  *
- *                                                                           *
-\*****************************************************************************/
-
-static void sdhci_tasklet_card(unsigned long param)
-{
-       struct sdhci_host *host;
-       unsigned long flags;
-
-       host = (struct sdhci_host*)param;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
-               if (host->mrq) {
-                       printk(KERN_ERR "%s: Card removed during transfer!\n",
-                               mmc_hostname(host->mmc));
-                       printk(KERN_ERR "%s: Resetting controller.\n",
-                               mmc_hostname(host->mmc));
-
-                       sdhci_reset(host, SDHCI_RESET_CMD);
-                       sdhci_reset(host, SDHCI_RESET_DATA);
-
-                       host->mrq->cmd->error = MMC_ERR_FAILED;
-                       tasklet_schedule(&host->finish_tasklet);
-               }
-       }
-
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
-}
-
-static void sdhci_tasklet_finish(unsigned long param)
-{
-       struct sdhci_host *host;
-       unsigned long flags;
-       struct mmc_request *mrq;
-
-       host = (struct sdhci_host*)param;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       del_timer(&host->timer);
-
-       mrq = host->mrq;
-
-       DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
-       /*
-        * The controller needs a reset of internal state machines
-        * upon error conditions.
-        */
-       if ((mrq->cmd->error != MMC_ERR_NONE) ||
-               (mrq->data && ((mrq->data->error != MMC_ERR_NONE) ||
-               (mrq->data->stop && (mrq->data->stop->error != MMC_ERR_NONE))))) {
-
-               /* Some controllers need this kick or reset won't work here */
-               if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
-                       unsigned int clock;
-
-                       /* This is to force an update */
-                       clock = host->clock;
-                       host->clock = 0;
-                       sdhci_set_clock(host, clock);
-               }
-
-               /* Spec says we should do both at the same time, but Ricoh
-                  controllers do not like that. */
-               sdhci_reset(host, SDHCI_RESET_CMD);
-               sdhci_reset(host, SDHCI_RESET_DATA);
-       }
-
-       host->mrq = NULL;
-       host->cmd = NULL;
-       host->data = NULL;
-
-       sdhci_deactivate_led(host);
-
-       mmiowb();
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       mmc_request_done(host->mmc, mrq);
-}
-
-static void sdhci_timeout_timer(unsigned long data)
-{
-       struct sdhci_host *host;
-       unsigned long flags;
-
-       host = (struct sdhci_host*)data;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       if (host->mrq) {
-               printk(KERN_ERR "%s: Timeout waiting for hardware "
-                       "interrupt.\n", mmc_hostname(host->mmc));
-               sdhci_dumpregs(host);
-
-               if (host->data) {
-                       host->data->error = MMC_ERR_TIMEOUT;
-                       sdhci_finish_data(host);
-               } else {
-                       if (host->cmd)
-                               host->cmd->error = MMC_ERR_TIMEOUT;
-                       else
-                               host->mrq->cmd->error = MMC_ERR_TIMEOUT;
-
-                       tasklet_schedule(&host->finish_tasklet);
-               }
-       }
-
-       mmiowb();
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-/*****************************************************************************\
- *                                                                           *
- * Interrupt handling                                                        *
- *                                                                           *
-\*****************************************************************************/
-
-static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
-{
-       BUG_ON(intmask == 0);
-
-       if (!host->cmd) {
-               printk(KERN_ERR "%s: Got command interrupt even though no "
-                       "command operation was in progress.\n",
-                       mmc_hostname(host->mmc));
-               sdhci_dumpregs(host);
-               return;
-       }
-
-       if (intmask & SDHCI_INT_RESPONSE)
-               sdhci_finish_command(host);
-       else {
-               if (intmask & SDHCI_INT_TIMEOUT)
-                       host->cmd->error = MMC_ERR_TIMEOUT;
-               else if (intmask & SDHCI_INT_CRC)
-                       host->cmd->error = MMC_ERR_BADCRC;
-               else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
-                       host->cmd->error = MMC_ERR_FAILED;
-               else
-                       host->cmd->error = MMC_ERR_INVALID;
-
-               tasklet_schedule(&host->finish_tasklet);
-       }
-}
-
-static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
-{
-       BUG_ON(intmask == 0);
-
-       if (!host->data) {
-               /*
-                * A data end interrupt is sent together with the response
-                * for the stop command.
-                */
-               if (intmask & SDHCI_INT_DATA_END)
-                       return;
-
-               printk(KERN_ERR "%s: Got data interrupt even though no "
-                       "data operation was in progress.\n",
-                       mmc_hostname(host->mmc));
-               sdhci_dumpregs(host);
-
-               return;
-       }
-
-       if (intmask & SDHCI_INT_DATA_TIMEOUT)
-               host->data->error = MMC_ERR_TIMEOUT;
-       else if (intmask & SDHCI_INT_DATA_CRC)
-               host->data->error = MMC_ERR_BADCRC;
-       else if (intmask & SDHCI_INT_DATA_END_BIT)
-               host->data->error = MMC_ERR_FAILED;
-
-       if (host->data->error != MMC_ERR_NONE)
-               sdhci_finish_data(host);
-       else {
-               if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
-                       sdhci_transfer_pio(host);
-
-               if (intmask & SDHCI_INT_DATA_END)
-                       sdhci_finish_data(host);
-       }
-}
-
-static irqreturn_t sdhci_irq(int irq, void *dev_id)
-{
-       irqreturn_t result;
-       struct sdhci_host* host = dev_id;
-       u32 intmask;
-
-       spin_lock(&host->lock);
-
-       intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
-
-       if (!intmask || intmask == 0xffffffff) {
-               result = IRQ_NONE;
-               goto out;
-       }
-
-       DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
-
-       if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-               writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
-                       host->ioaddr + SDHCI_INT_STATUS);
-               tasklet_schedule(&host->card_tasklet);
-       }
-
-       intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-
-       if (intmask & SDHCI_INT_CMD_MASK) {
-               writel(intmask & SDHCI_INT_CMD_MASK,
-                       host->ioaddr + SDHCI_INT_STATUS);
-               sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
-       }
-
-       if (intmask & SDHCI_INT_DATA_MASK) {
-               writel(intmask & SDHCI_INT_DATA_MASK,
-                       host->ioaddr + SDHCI_INT_STATUS);
-               sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
-       }
-
-       intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
-
-       if (intmask & SDHCI_INT_BUS_POWER) {
-               printk(KERN_ERR "%s: Card is consuming too much power!\n",
-                       mmc_hostname(host->mmc));
-               writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
-       }
-
-       intmask &= SDHCI_INT_BUS_POWER;
-
-       if (intmask) {
-               printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
-                       mmc_hostname(host->mmc), intmask);
-               sdhci_dumpregs(host);
-
-               writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
-       }
-
-       result = IRQ_HANDLED;
-
-       mmiowb();
-out:
-       spin_unlock(&host->lock);
-
-       return result;
-}
-
-/*****************************************************************************\
- *                                                                           *
- * Suspend/resume                                                            *
- *                                                                           *
-\*****************************************************************************/
-
-#ifdef CONFIG_PM
-
-static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state)
-{
-       struct sdhci_chip *chip;
-       int i, ret;
-
-       chip = pci_get_drvdata(pdev);
-       if (!chip)
-               return 0;
-
-       DBG("Suspending...\n");
-
-       for (i = 0;i < chip->num_slots;i++) {
-               if (!chip->hosts[i])
-                       continue;
-               ret = mmc_suspend_host(chip->hosts[i]->mmc, state);
-               if (ret) {
-                       for (i--;i >= 0;i--)
-                               mmc_resume_host(chip->hosts[i]->mmc);
-                       return ret;
-               }
-       }
-
-       pci_save_state(pdev);
-       pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-
-       for (i = 0;i < chip->num_slots;i++) {
-               if (!chip->hosts[i])
-                       continue;
-               free_irq(chip->hosts[i]->irq, chip->hosts[i]);
-       }
-
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-       return 0;
-}
-
-static int sdhci_resume (struct pci_dev *pdev)
-{
-       struct sdhci_chip *chip;
-       int i, ret;
-
-       chip = pci_get_drvdata(pdev);
-       if (!chip)
-               return 0;
-
-       DBG("Resuming...\n");
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-
-       for (i = 0;i < chip->num_slots;i++) {
-               if (!chip->hosts[i])
-                       continue;
-               if (chip->hosts[i]->flags & SDHCI_USE_DMA)
-                       pci_set_master(pdev);
-               ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
-                       IRQF_SHARED, chip->hosts[i]->slot_descr,
-                       chip->hosts[i]);
-               if (ret)
-                       return ret;
-               sdhci_init(chip->hosts[i]);
-               mmiowb();
-               ret = mmc_resume_host(chip->hosts[i]->mmc);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-#else /* CONFIG_PM */
-
-#define sdhci_suspend NULL
-#define sdhci_resume NULL
-
-#endif /* CONFIG_PM */
-
-/*****************************************************************************\
- *                                                                           *
- * Device probing/removal                                                    *
- *                                                                           *
-\*****************************************************************************/
-
-static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
-{
-       int ret;
-       unsigned int version;
-       struct sdhci_chip *chip;
-       struct mmc_host *mmc;
-       struct sdhci_host *host;
-
-       u8 first_bar;
-       unsigned int caps;
-
-       chip = pci_get_drvdata(pdev);
-       BUG_ON(!chip);
-
-       ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
-       if (ret)
-               return ret;
-
-       first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
-
-       if (first_bar > 5) {
-               printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n");
-               return -ENODEV;
-       }
-
-       if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) {
-               printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n");
-               return -ENODEV;
-       }
-
-       if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
-               printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. "
-                       "You may experience problems.\n");
-       }
-
-       if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
-               printk(KERN_ERR DRIVER_NAME ": Vendor specific interface. Aborting.\n");
-               return -ENODEV;
-       }
-
-       if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) {
-               printk(KERN_ERR DRIVER_NAME ": Unknown interface. Aborting.\n");
-               return -ENODEV;
-       }
-
-       mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev);
-       if (!mmc)
-               return -ENOMEM;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-
-       host->chip = chip;
-       chip->hosts[slot] = host;
-
-       host->bar = first_bar + slot;
-
-       host->addr = pci_resource_start(pdev, host->bar);
-       host->irq = pdev->irq;
-
-       DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
-
-       snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
-
-       ret = pci_request_region(pdev, host->bar, host->slot_descr);
-       if (ret)
-               goto free;
-
-       host->ioaddr = ioremap_nocache(host->addr,
-               pci_resource_len(pdev, host->bar));
-       if (!host->ioaddr) {
-               ret = -ENOMEM;
-               goto release;
-       }
-
-       sdhci_reset(host, SDHCI_RESET_ALL);
-
-       version = readw(host->ioaddr + SDHCI_HOST_VERSION);
-       version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
-       if (version != 0) {
-               printk(KERN_ERR "%s: Unknown controller version (%d). "
-                       "You may experience problems.\n", host->slot_descr,
-                       version);
-       }
-
-       caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
-
-       if (debug_nodma)
-               DBG("DMA forced off\n");
-       else if (debug_forcedma) {
-               DBG("DMA forced on\n");
-               host->flags |= SDHCI_USE_DMA;
-       } else if (chip->quirks & SDHCI_QUIRK_FORCE_DMA)
-               host->flags |= SDHCI_USE_DMA;
-       else if ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA)
-               DBG("Controller doesn't have DMA interface\n");
-       else if (!(caps & SDHCI_CAN_DO_DMA))
-               DBG("Controller doesn't have DMA capability\n");
-       else
-               host->flags |= SDHCI_USE_DMA;
-
-       if (host->flags & SDHCI_USE_DMA) {
-               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
-                       printk(KERN_WARNING "%s: No suitable DMA available. "
-                               "Falling back to PIO.\n", host->slot_descr);
-                       host->flags &= ~SDHCI_USE_DMA;
-               }
-       }
-
-       if (host->flags & SDHCI_USE_DMA)
-               pci_set_master(pdev);
-       else /* XXX: Hack to get MMC layer to avoid highmem */
-               pdev->dma_mask = 0;
-
-       host->max_clk =
-               (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
-       if (host->max_clk == 0) {
-               printk(KERN_ERR "%s: Hardware doesn't specify base clock "
-                       "frequency.\n", host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-       host->max_clk *= 1000000;
-
-       host->timeout_clk =
-               (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
-       if (host->timeout_clk == 0) {
-               printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
-                       "frequency.\n", host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-       if (caps & SDHCI_TIMEOUT_CLK_UNIT)
-               host->timeout_clk *= 1000;
-
-       /*
-        * Set host parameters.
-        */
-       mmc->ops = &sdhci_ops;
-       mmc->f_min = host->max_clk / 256;
-       mmc->f_max = host->max_clk;
-       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
-
-       if (caps & SDHCI_CAN_DO_HISPD)
-               mmc->caps |= MMC_CAP_SD_HIGHSPEED;
-
-       mmc->ocr_avail = 0;
-       if (caps & SDHCI_CAN_VDD_330)
-               mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
-       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;
-
-       if (mmc->ocr_avail == 0) {
-               printk(KERN_ERR "%s: Hardware doesn't report any "
-                       "support voltages.\n", host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-
-       spin_lock_init(&host->lock);
-
-       /*
-        * Maximum number of segments. Hardware cannot do scatter lists.
-        */
-       if (host->flags & SDHCI_USE_DMA)
-               mmc->max_hw_segs = 1;
-       else
-               mmc->max_hw_segs = 16;
-       mmc->max_phys_segs = 16;
-
-       /*
-        * Maximum number of sectors in one transfer. Limited by DMA boundary
-        * size (512KiB).
-        */
-       mmc->max_req_size = 524288;
-
-       /*
-        * Maximum segment size. Could be one segment with the maximum number
-        * of bytes.
-        */
-       mmc->max_seg_size = mmc->max_req_size;
-
-       /*
-        * Maximum block size. This varies from controller to controller and
-        * is specified in the capabilities register.
-        */
-       mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
-       if (mmc->max_blk_size >= 3) {
-               printk(KERN_ERR "%s: Invalid maximum block size.\n",
-                       host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-       mmc->max_blk_size = 512 << mmc->max_blk_size;
-
-       /*
-        * Maximum block count.
-        */
-       mmc->max_blk_count = 65535;
-
-       /*
-        * Init tasklets.
-        */
-       tasklet_init(&host->card_tasklet,
-               sdhci_tasklet_card, (unsigned long)host);
-       tasklet_init(&host->finish_tasklet,
-               sdhci_tasklet_finish, (unsigned long)host);
-
-       setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
-
-       ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-               host->slot_descr, host);
-       if (ret)
-               goto untasklet;
-
-       sdhci_init(host);
-
-#ifdef CONFIG_MMC_DEBUG
-       sdhci_dumpregs(host);
-#endif
-
-       mmiowb();
-
-       mmc_add_host(mmc);
-
-       printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
-               host->addr, host->irq,
-               (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
-
-       return 0;
-
-untasklet:
-       tasklet_kill(&host->card_tasklet);
-       tasklet_kill(&host->finish_tasklet);
-unmap:
-       iounmap(host->ioaddr);
-release:
-       pci_release_region(pdev, host->bar);
-free:
-       mmc_free_host(mmc);
-
-       return ret;
-}
-
-static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
-{
-       struct sdhci_chip *chip;
-       struct mmc_host *mmc;
-       struct sdhci_host *host;
-
-       chip = pci_get_drvdata(pdev);
-       host = chip->hosts[slot];
-       mmc = host->mmc;
-
-       chip->hosts[slot] = NULL;
-
-       mmc_remove_host(mmc);
-
-       sdhci_reset(host, SDHCI_RESET_ALL);
-
-       free_irq(host->irq, host);
-
-       del_timer_sync(&host->timer);
-
-       tasklet_kill(&host->card_tasklet);
-       tasklet_kill(&host->finish_tasklet);
-
-       iounmap(host->ioaddr);
-
-       pci_release_region(pdev, host->bar);
-
-       mmc_free_host(mmc);
-}
-
-static int __devinit sdhci_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
-{
-       int ret, i;
-       u8 slots, rev;
-       struct sdhci_chip *chip;
-
-       BUG_ON(pdev == NULL);
-       BUG_ON(ent == NULL);
-
-       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
-
-       printk(KERN_INFO DRIVER_NAME
-               ": SDHCI controller found at %s [%04x:%04x] (rev %x)\n",
-               pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
-               (int)rev);
-
-       ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
-       if (ret)
-               return ret;
-
-       slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
-       DBG("found %d slot(s)\n", slots);
-       if (slots == 0)
-               return -ENODEV;
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-
-       chip = kzalloc(sizeof(struct sdhci_chip) +
-               sizeof(struct sdhci_host*) * slots, GFP_KERNEL);
-       if (!chip) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       chip->pdev = pdev;
-       chip->quirks = ent->driver_data;
-
-       if (debug_quirks)
-               chip->quirks = debug_quirks;
-
-       chip->num_slots = slots;
-       pci_set_drvdata(pdev, chip);
-
-       for (i = 0;i < slots;i++) {
-               ret = sdhci_probe_slot(pdev, i);
-               if (ret) {
-                       for (i--;i >= 0;i--)
-                               sdhci_remove_slot(pdev, i);
-                       goto free;
-               }
-       }
-
-       return 0;
-
-free:
-       pci_set_drvdata(pdev, NULL);
-       kfree(chip);
-
-err:
-       pci_disable_device(pdev);
-       return ret;
-}
-
-static void __devexit sdhci_remove(struct pci_dev *pdev)
-{
-       int i;
-       struct sdhci_chip *chip;
-
-       chip = pci_get_drvdata(pdev);
-
-       if (chip) {
-               for (i = 0;i < chip->num_slots;i++)
-                       sdhci_remove_slot(pdev, i);
-
-               pci_set_drvdata(pdev, NULL);
-
-               kfree(chip);
-       }
-
-       pci_disable_device(pdev);
-}
-
-static struct pci_driver sdhci_driver = {
-       .name =         DRIVER_NAME,
-       .id_table =     pci_ids,
-       .probe =        sdhci_probe,
-       .remove =       __devexit_p(sdhci_remove),
-       .suspend =      sdhci_suspend,
-       .resume =       sdhci_resume,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init sdhci_drv_init(void)
-{
-       printk(KERN_INFO DRIVER_NAME
-               ": Secure Digital Host Controller Interface driver\n");
-       printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
-
-       return pci_register_driver(&sdhci_driver);
-}
-
-static void __exit sdhci_drv_exit(void)
-{
-       DBG("Exiting\n");
-
-       pci_unregister_driver(&sdhci_driver);
-}
-
-module_init(sdhci_drv_init);
-module_exit(sdhci_drv_exit);
-
-module_param(debug_nodma, uint, 0444);
-module_param(debug_forcedma, uint, 0444);
-module_param(debug_quirks, uint, 0444);
-
-MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM_DESC(debug_nodma, "Forcefully disable DMA transfers. (default 0)");
-MODULE_PARM_DESC(debug_forcedma, "Forcefully enable DMA transfers. (default 0)");
-MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
deleted file mode 100644 (file)
index e324f0a..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- *  linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
- *
- *  Copyright (C) 2005 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.
- */
-
-/*
- * PCI registers
- */
-
-#define PCI_SDHCI_IFPIO                        0x00
-#define PCI_SDHCI_IFDMA                        0x01
-#define PCI_SDHCI_IFVENDOR             0x02
-
-#define PCI_SLOT_INFO                  0x40    /* 8 bits */
-#define  PCI_SLOT_INFO_SLOTS(x)                ((x >> 4) & 7)
-#define  PCI_SLOT_INFO_FIRST_BAR_MASK  0x07
-
-/*
- * Controller registers
- */
-
-#define SDHCI_DMA_ADDRESS      0x00
-
-#define SDHCI_BLOCK_SIZE       0x04
-#define  SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
-
-#define SDHCI_BLOCK_COUNT      0x06
-
-#define SDHCI_ARGUMENT         0x08
-
-#define SDHCI_TRANSFER_MODE    0x0C
-#define  SDHCI_TRNS_DMA                0x01
-#define  SDHCI_TRNS_BLK_CNT_EN 0x02
-#define  SDHCI_TRNS_ACMD12     0x04
-#define  SDHCI_TRNS_READ       0x10
-#define  SDHCI_TRNS_MULTI      0x20
-
-#define SDHCI_COMMAND          0x0E
-#define  SDHCI_CMD_RESP_MASK   0x03
-#define  SDHCI_CMD_CRC         0x08
-#define  SDHCI_CMD_INDEX       0x10
-#define  SDHCI_CMD_DATA                0x20
-
-#define  SDHCI_CMD_RESP_NONE   0x00
-#define  SDHCI_CMD_RESP_LONG   0x01
-#define  SDHCI_CMD_RESP_SHORT  0x02
-#define  SDHCI_CMD_RESP_SHORT_BUSY 0x03
-
-#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
-
-#define SDHCI_RESPONSE         0x10
-
-#define SDHCI_BUFFER           0x20
-
-#define SDHCI_PRESENT_STATE    0x24
-#define  SDHCI_CMD_INHIBIT     0x00000001
-#define  SDHCI_DATA_INHIBIT    0x00000002
-#define  SDHCI_DOING_WRITE     0x00000100
-#define  SDHCI_DOING_READ      0x00000200
-#define  SDHCI_SPACE_AVAILABLE 0x00000400
-#define  SDHCI_DATA_AVAILABLE  0x00000800
-#define  SDHCI_CARD_PRESENT    0x00010000
-#define  SDHCI_WRITE_PROTECT   0x00080000
-
-#define SDHCI_HOST_CONTROL     0x28
-#define  SDHCI_CTRL_LED                0x01
-#define  SDHCI_CTRL_4BITBUS    0x02
-#define  SDHCI_CTRL_HISPD      0x04
-
-#define SDHCI_POWER_CONTROL    0x29
-#define  SDHCI_POWER_ON                0x01
-#define  SDHCI_POWER_180       0x0A
-#define  SDHCI_POWER_300       0x0C
-#define  SDHCI_POWER_330       0x0E
-
-#define SDHCI_BLOCK_GAP_CONTROL        0x2A
-
-#define SDHCI_WALK_UP_CONTROL  0x2B
-
-#define SDHCI_CLOCK_CONTROL    0x2C
-#define  SDHCI_DIVIDER_SHIFT   8
-#define  SDHCI_CLOCK_CARD_EN   0x0004
-#define  SDHCI_CLOCK_INT_STABLE        0x0002
-#define  SDHCI_CLOCK_INT_EN    0x0001
-
-#define SDHCI_TIMEOUT_CONTROL  0x2E
-
-#define SDHCI_SOFTWARE_RESET   0x2F
-#define  SDHCI_RESET_ALL       0x01
-#define  SDHCI_RESET_CMD       0x02
-#define  SDHCI_RESET_DATA      0x04
-
-#define SDHCI_INT_STATUS       0x30
-#define SDHCI_INT_ENABLE       0x34
-#define SDHCI_SIGNAL_ENABLE    0x38
-#define  SDHCI_INT_RESPONSE    0x00000001
-#define  SDHCI_INT_DATA_END    0x00000002
-#define  SDHCI_INT_DMA_END     0x00000008
-#define  SDHCI_INT_SPACE_AVAIL 0x00000010
-#define  SDHCI_INT_DATA_AVAIL  0x00000020
-#define  SDHCI_INT_CARD_INSERT 0x00000040
-#define  SDHCI_INT_CARD_REMOVE 0x00000080
-#define  SDHCI_INT_CARD_INT    0x00000100
-#define  SDHCI_INT_TIMEOUT     0x00010000
-#define  SDHCI_INT_CRC         0x00020000
-#define  SDHCI_INT_END_BIT     0x00040000
-#define  SDHCI_INT_INDEX       0x00080000
-#define  SDHCI_INT_DATA_TIMEOUT        0x00100000
-#define  SDHCI_INT_DATA_CRC    0x00200000
-#define  SDHCI_INT_DATA_END_BIT        0x00400000
-#define  SDHCI_INT_BUS_POWER   0x00800000
-#define  SDHCI_INT_ACMD12ERR   0x01000000
-
-#define  SDHCI_INT_NORMAL_MASK 0x00007FFF
-#define  SDHCI_INT_ERROR_MASK  0xFFFF8000
-
-#define  SDHCI_INT_CMD_MASK    (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
-               SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
-#define  SDHCI_INT_DATA_MASK   (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
-               SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
-               SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
-               SDHCI_INT_DATA_END_BIT)
-
-#define SDHCI_ACMD12_ERR       0x3C
-
-/* 3E-3F reserved */
-
-#define SDHCI_CAPABILITIES     0x40
-#define  SDHCI_TIMEOUT_CLK_MASK        0x0000003F
-#define  SDHCI_TIMEOUT_CLK_SHIFT 0
-#define  SDHCI_TIMEOUT_CLK_UNIT        0x00000080
-#define  SDHCI_CLOCK_BASE_MASK 0x00003F00
-#define  SDHCI_CLOCK_BASE_SHIFT        8
-#define  SDHCI_MAX_BLOCK_MASK  0x00030000
-#define  SDHCI_MAX_BLOCK_SHIFT  16
-#define  SDHCI_CAN_DO_HISPD    0x00200000
-#define  SDHCI_CAN_DO_DMA      0x00400000
-#define  SDHCI_CAN_VDD_330     0x01000000
-#define  SDHCI_CAN_VDD_300     0x02000000
-#define  SDHCI_CAN_VDD_180     0x04000000
-
-/* 44-47 reserved for more caps */
-
-#define SDHCI_MAX_CURRENT      0x48
-
-/* 4C-4F reserved for more max current */
-
-/* 50-FB reserved */
-
-#define SDHCI_SLOT_INT_STATUS  0xFC
-
-#define SDHCI_HOST_VERSION     0xFE
-#define  SDHCI_VENDOR_VER_MASK 0xFF00
-#define  SDHCI_VENDOR_VER_SHIFT        8
-#define  SDHCI_SPEC_VER_MASK   0x00FF
-#define  SDHCI_SPEC_VER_SHIFT  0
-
-struct sdhci_chip;
-
-struct sdhci_host {
-       struct sdhci_chip       *chip;
-       struct mmc_host         *mmc;           /* MMC structure */
-
-       spinlock_t              lock;           /* Mutex */
-
-       int                     flags;          /* Host attributes */
-#define SDHCI_USE_DMA          (1<<0)
-
-       unsigned int            max_clk;        /* Max possible freq (MHz) */
-       unsigned int            timeout_clk;    /* Timeout freq (KHz) */
-
-       unsigned int            clock;          /* Current clock (MHz) */
-       unsigned short          power;          /* Current voltage */
-
-       struct mmc_request      *mrq;           /* Current request */
-       struct mmc_command      *cmd;           /* Current command */
-       struct mmc_data         *data;          /* Current data request */
-
-       struct scatterlist      *cur_sg;        /* We're working on this */
-       int                     num_sg;         /* Entries left */
-       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 */
-       int                     bar;            /* PCI BAR index */
-       unsigned long           addr;           /* Bus address */
-       void __iomem *          ioaddr;         /* Mapped address */
-
-       struct tasklet_struct   card_tasklet;   /* Tasklet structures */
-       struct tasklet_struct   finish_tasklet;
-
-       struct timer_list       timer;          /* Timer for timeouts */
-};
-
-struct sdhci_chip {
-       struct pci_dev          *pdev;
-
-       unsigned long           quirks;
-
-       int                     num_slots;      /* Slots on controller */
-       struct sdhci_host       *hosts[0];      /* Pointers to hosts */
-};
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);
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
deleted file mode 100644 (file)
index 05ccfc4..0000000
+++ /dev/null
@@ -1,2172 +0,0 @@
-/*
- *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
- *
- *  Copyright (C) 2004-2006 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.
- *
- *
- * Warning!
- *
- * Changes to the FIFO system should be done with extreme care since
- * the hardware is full of bugs related to the FIFO. Known issues are:
- *
- * - FIFO size field in FSR is always zero.
- *
- * - FIFO interrupts tend not to work as they should. Interrupts are
- *   triggered only for full/empty events, not for threshold values.
- *
- * - On APIC systems the FIFO empty interrupt is sometimes lost.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#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>
-#include <asm/scatterlist.h>
-
-#include "wbsd.h"
-
-#define DRIVER_NAME "wbsd"
-
-#define DBG(x...) \
-       pr_debug(DRIVER_NAME ": " x)
-#define DBGF(f, x...) \
-       pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x)
-
-/*
- * Device resources
- */
-
-#ifdef CONFIG_PNP
-
-static const struct pnp_device_id pnp_dev_table[] = {
-       { "WEC0517", 0 },
-       { "WEC0518", 0 },
-       { "", 0 },
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-#endif /* CONFIG_PNP */
-
-static const int config_ports[] = { 0x2E, 0x4E };
-static const int unlock_codes[] = { 0x83, 0x87 };
-
-static const int valid_ids[] = {
-       0x7112,
-       };
-
-#ifdef CONFIG_PNP
-static unsigned int nopnp = 0;
-#else
-static const unsigned int nopnp = 1;
-#endif
-static unsigned int io = 0x248;
-static unsigned int irq = 6;
-static int dma = 2;
-
-/*
- * Basic functions
- */
-
-static inline void wbsd_unlock_config(struct wbsd_host *host)
-{
-       BUG_ON(host->config == 0);
-
-       outb(host->unlock_code, host->config);
-       outb(host->unlock_code, host->config);
-}
-
-static inline void wbsd_lock_config(struct wbsd_host *host)
-{
-       BUG_ON(host->config == 0);
-
-       outb(LOCK_CODE, host->config);
-}
-
-static inline void wbsd_write_config(struct wbsd_host *host, u8 reg, u8 value)
-{
-       BUG_ON(host->config == 0);
-
-       outb(reg, host->config);
-       outb(value, host->config + 1);
-}
-
-static inline u8 wbsd_read_config(struct wbsd_host *host, u8 reg)
-{
-       BUG_ON(host->config == 0);
-
-       outb(reg, host->config);
-       return inb(host->config + 1);
-}
-
-static inline void wbsd_write_index(struct wbsd_host *host, u8 index, u8 value)
-{
-       outb(index, host->base + WBSD_IDXR);
-       outb(value, host->base + WBSD_DATAR);
-}
-
-static inline u8 wbsd_read_index(struct wbsd_host *host, u8 index)
-{
-       outb(index, host->base + WBSD_IDXR);
-       return inb(host->base + WBSD_DATAR);
-}
-
-/*
- * Common routines
- */
-
-static void wbsd_init_device(struct wbsd_host *host)
-{
-       u8 setup, ier;
-
-       /*
-        * Reset chip (SD/MMC part) and fifo.
-        */
-       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
-       setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
-       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
-       /*
-        * Set DAT3 to input
-        */
-       setup &= ~WBSD_DAT3_H;
-       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-       host->flags &= ~WBSD_FIGNORE_DETECT;
-
-       /*
-        * Read back default clock.
-        */
-       host->clk = wbsd_read_index(host, WBSD_IDX_CLK);
-
-       /*
-        * Power down port.
-        */
-       outb(WBSD_POWER_N, host->base + WBSD_CSR);
-
-       /*
-        * Set maximum timeout.
-        */
-       wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
-
-       /*
-        * Test for card presence
-        */
-       if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)
-               host->flags |= WBSD_FCARD_PRESENT;
-       else
-               host->flags &= ~WBSD_FCARD_PRESENT;
-
-       /*
-        * Enable interesting interrupts.
-        */
-       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_TC;
-
-       outb(ier, host->base + WBSD_EIR);
-
-       /*
-        * Clear interrupts.
-        */
-       inb(host->base + WBSD_ISR);
-}
-
-static void wbsd_reset(struct wbsd_host *host)
-{
-       u8 setup;
-
-       printk(KERN_ERR "%s: Resetting chip\n", mmc_hostname(host->mmc));
-
-       /*
-        * Soft reset of chip (SD/MMC part).
-        */
-       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
-       setup |= WBSD_SOFT_RESET;
-       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-}
-
-static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq)
-{
-       unsigned long dmaflags;
-
-       DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
-       if (host->dma >= 0) {
-               /*
-                * Release ISA DMA controller.
-                */
-               dmaflags = claim_dma_lock();
-               disable_dma(host->dma);
-               clear_dma_ff(host->dma);
-               release_dma_lock(dmaflags);
-
-               /*
-                * Disable DMA on host.
-                */
-               wbsd_write_index(host, WBSD_IDX_DMA, 0);
-       }
-
-       host->mrq = NULL;
-
-       /*
-        * MMC layer might call back into the driver so first unlock.
-        */
-       spin_unlock(&host->lock);
-       mmc_request_done(host->mmc, mrq);
-       spin_lock(&host->lock);
-}
-
-/*
- * Scatter/gather functions
- */
-
-static inline void wbsd_init_sg(struct wbsd_host *host, struct mmc_data *data)
-{
-       /*
-        * Get info. about SG list from data structure.
-        */
-       host->cur_sg = data->sg;
-       host->num_sg = data->sg_len;
-
-       host->offset = 0;
-       host->remain = host->cur_sg->length;
-}
-
-static inline int wbsd_next_sg(struct wbsd_host *host)
-{
-       /*
-        * Skip to next SG entry.
-        */
-       host->cur_sg++;
-       host->num_sg--;
-
-       /*
-        * Any entries left?
-        */
-       if (host->num_sg > 0) {
-               host->offset = 0;
-               host->remain = host->cur_sg->length;
-       }
-
-       return host->num_sg;
-}
-
-static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
-{
-       return page_address(host->cur_sg->page) + host->cur_sg->offset;
-}
-
-static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
-{
-       unsigned int len, i, size;
-       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);
-               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;
-       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);
-               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;
-}
-
-/*
- * Command handling
- */
-
-static inline void wbsd_get_short_reply(struct wbsd_host *host,
-                                       struct mmc_command *cmd)
-{
-       /*
-        * Correct response type?
-        */
-       if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) {
-               cmd->error = MMC_ERR_INVALID;
-               return;
-       }
-
-       cmd->resp[0]  = wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
-       cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
-       cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
-       cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
-       cmd->resp[1]  = wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
-}
-
-static inline void wbsd_get_long_reply(struct wbsd_host *host,
-       struct mmc_command *cmd)
-{
-       int i;
-
-       /*
-        * Correct response type?
-        */
-       if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) {
-               cmd->error = MMC_ERR_INVALID;
-               return;
-       }
-
-       for (i = 0; i < 4; i++) {
-               cmd->resp[i] =
-                       wbsd_read_index(host, WBSD_IDX_RESP1 + i * 4) << 24;
-               cmd->resp[i] |=
-                       wbsd_read_index(host, WBSD_IDX_RESP2 + i * 4) << 16;
-               cmd->resp[i] |=
-                       wbsd_read_index(host, WBSD_IDX_RESP3 + i * 4) << 8;
-               cmd->resp[i] |=
-                       wbsd_read_index(host, WBSD_IDX_RESP4 + i * 4) << 0;
-       }
-}
-
-static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
-{
-       int i;
-       u8 status, isr;
-
-       DBGF("Sending cmd (%x)\n", cmd->opcode);
-
-       /*
-        * Clear accumulated ISR. The interrupt routine
-        * will fill this one with events that occur during
-        * transfer.
-        */
-       host->isr = 0;
-
-       /*
-        * Send the command (CRC calculated by host).
-        */
-       outb(cmd->opcode, host->base + WBSD_CMDR);
-       for (i = 3; i >= 0; i--)
-               outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
-
-       cmd->error = MMC_ERR_NONE;
-
-       /*
-        * Wait for the request to complete.
-        */
-       do {
-               status = wbsd_read_index(host, WBSD_IDX_STATUS);
-       } while (status & WBSD_CARDTRAFFIC);
-
-       /*
-        * Do we expect a reply?
-        */
-       if (cmd->flags & MMC_RSP_PRESENT) {
-               /*
-                * Read back status.
-                */
-               isr = host->isr;
-
-               /* Card removed? */
-               if (isr & WBSD_INT_CARD)
-                       cmd->error = MMC_ERR_TIMEOUT;
-               /* Timeout? */
-               else if (isr & WBSD_INT_TIMEOUT)
-                       cmd->error = MMC_ERR_TIMEOUT;
-               /* CRC? */
-               else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC))
-                       cmd->error = MMC_ERR_BADCRC;
-               /* All ok */
-               else {
-                       if (cmd->flags & MMC_RSP_136)
-                               wbsd_get_long_reply(host, cmd);
-                       else
-                               wbsd_get_short_reply(host, cmd);
-               }
-       }
-
-       DBGF("Sent cmd (%x), res %d\n", cmd->opcode, cmd->error);
-}
-
-/*
- * Data functions
- */
-
-static void wbsd_empty_fifo(struct wbsd_host *host)
-{
-       struct mmc_data *data = host->mrq->cmd->data;
-       char *buffer;
-       int i, fsr, fifo;
-
-       /*
-        * Handle excessive data.
-        */
-       if (data->bytes_xfered == host->size)
-               return;
-
-       buffer = wbsd_sg_to_buffer(host) + host->offset;
-
-       /*
-        * Drain the fifo. This has a tendency to loop longer
-        * than the FIFO length (usually one block).
-        */
-       while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) {
-               /*
-                * The size field in the FSR is broken so we have to
-                * do some guessing.
-                */
-               if (fsr & WBSD_FIFO_FULL)
-                       fifo = 16;
-               else if (fsr & WBSD_FIFO_FUTHRE)
-                       fifo = 8;
-               else
-                       fifo = 1;
-
-               for (i = 0; i < fifo; i++) {
-                       *buffer = inb(host->base + WBSD_DFR);
-                       buffer++;
-                       host->offset++;
-                       host->remain--;
-
-                       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;
-
-                                       return;
-                               }
-
-                               buffer = wbsd_sg_to_buffer(host);
-                       }
-               }
-       }
-
-       /*
-        * This is a very dirty hack to solve a
-        * hardware problem. The chip doesn't trigger
-        * FIFO threshold interrupts properly.
-        */
-       if ((host->size - data->bytes_xfered) < 16)
-               tasklet_schedule(&host->fifo_tasklet);
-}
-
-static void wbsd_fill_fifo(struct wbsd_host *host)
-{
-       struct mmc_data *data = host->mrq->cmd->data;
-       char *buffer;
-       int i, fsr, fifo;
-
-       /*
-        * Check that we aren't being called after the
-        * entire buffer has been transfered.
-        */
-       if (data->bytes_xfered == host->size)
-               return;
-
-       buffer = wbsd_sg_to_buffer(host) + host->offset;
-
-       /*
-        * Fill the fifo. This has a tendency to loop longer
-        * than the FIFO length (usually one block).
-        */
-       while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) {
-               /*
-                * The size field in the FSR is broken so we have to
-                * do some guessing.
-                */
-               if (fsr & WBSD_FIFO_EMPTY)
-                       fifo = 0;
-               else if (fsr & WBSD_FIFO_EMTHRE)
-                       fifo = 8;
-               else
-                       fifo = 15;
-
-               for (i = 16; i > fifo; i--) {
-                       outb(*buffer, host->base + WBSD_DFR);
-                       buffer++;
-                       host->offset++;
-                       host->remain--;
-
-                       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;
-
-                                       return;
-                               }
-
-                               buffer = wbsd_sg_to_buffer(host);
-                       }
-               }
-       }
-
-       /*
-        * The controller stops sending interrupts for
-        * 'FIFO empty' under certain conditions. So we
-        * need to be a bit more pro-active.
-        */
-       tasklet_schedule(&host->fifo_tasklet);
-}
-
-static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
-{
-       u16 blksize;
-       u8 setup;
-       unsigned long dmaflags;
-
-       DBGF("blksz %04x blks %04x flags %08x\n",
-               data->blksz, data->blocks, data->flags);
-       DBGF("tsac %d ms nsac %d clk\n",
-               data->timeout_ns / 1000000, data->timeout_clks);
-
-       /*
-        * Calculate size.
-        */
-       host->size = data->blocks * data->blksz;
-
-       /*
-        * Check timeout values for overflow.
-        * (Yes, some cards cause this value to overflow).
-        */
-       if (data->timeout_ns > 127000000)
-               wbsd_write_index(host, WBSD_IDX_TAAC, 127);
-       else {
-               wbsd_write_index(host, WBSD_IDX_TAAC,
-                       data->timeout_ns / 1000000);
-       }
-
-       if (data->timeout_clks > 255)
-               wbsd_write_index(host, WBSD_IDX_NSAC, 255);
-       else
-               wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
-
-       /*
-        * Inform the chip of how large blocks will be
-        * sent. It needs this to determine when to
-        * calculate CRC.
-        *
-        * Space for CRC must be included in the size.
-        * Two bytes are needed for each data line.
-        */
-       if (host->bus_width == MMC_BUS_WIDTH_1) {
-               blksize = data->blksz + 2;
-
-               wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
-               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
-       } else if (host->bus_width == MMC_BUS_WIDTH_4) {
-               blksize = data->blksz + 2 * 4;
-
-               wbsd_write_index(host, WBSD_IDX_PBSMSB,
-                       ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
-               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
-       } else {
-               data->error = MMC_ERR_INVALID;
-               return;
-       }
-
-       /*
-        * Clear the FIFO. This is needed even for DMA
-        * transfers since the chip still uses the FIFO
-        * internally.
-        */
-       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
-       setup |= WBSD_FIFO_RESET;
-       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
-       /*
-        * DMA transfer?
-        */
-       if (host->dma >= 0) {
-               /*
-                * The buffer for DMA is only 64 kB.
-                */
-               BUG_ON(host->size > 0x10000);
-               if (host->size > 0x10000) {
-                       data->error = MMC_ERR_INVALID;
-                       return;
-               }
-
-               /*
-                * Transfer data from the SG list to
-                * the DMA buffer.
-                */
-               if (data->flags & MMC_DATA_WRITE)
-                       wbsd_sg_to_dma(host, data);
-
-               /*
-                * Initialise the ISA DMA controller.
-                */
-               dmaflags = claim_dma_lock();
-               disable_dma(host->dma);
-               clear_dma_ff(host->dma);
-               if (data->flags & MMC_DATA_READ)
-                       set_dma_mode(host->dma, DMA_MODE_READ & ~0x40);
-               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);
-
-               enable_dma(host->dma);
-               release_dma_lock(dmaflags);
-
-               /*
-                * Enable DMA on the host.
-                */
-               wbsd_write_index(host, WBSD_IDX_DMA, WBSD_DMA_ENABLE);
-       } else {
-               /*
-                * This flag is used to keep printk
-                * output to a minimum.
-                */
-               host->firsterr = 1;
-
-               /*
-                * Initialise the SG list.
-                */
-               wbsd_init_sg(host, data);
-
-               /*
-                * Turn off DMA.
-                */
-               wbsd_write_index(host, WBSD_IDX_DMA, 0);
-
-               /*
-                * Set up FIFO threshold levels (and fill
-                * buffer if doing a write).
-                */
-               if (data->flags & MMC_DATA_READ) {
-                       wbsd_write_index(host, WBSD_IDX_FIFOEN,
-                               WBSD_FIFOEN_FULL | 8);
-               } else {
-                       wbsd_write_index(host, WBSD_IDX_FIFOEN,
-                               WBSD_FIFOEN_EMPTY | 8);
-                       wbsd_fill_fifo(host);
-               }
-       }
-
-       data->error = MMC_ERR_NONE;
-}
-
-static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
-{
-       unsigned long dmaflags;
-       int count;
-       u8 status;
-
-       WARN_ON(host->mrq == NULL);
-
-       /*
-        * Send a stop command if needed.
-        */
-       if (data->stop)
-               wbsd_send_command(host, data->stop);
-
-       /*
-        * Wait for the controller to leave data
-        * transfer state.
-        */
-       do {
-               status = wbsd_read_index(host, WBSD_IDX_STATUS);
-       } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
-
-       /*
-        * DMA transfer?
-        */
-       if (host->dma >= 0) {
-               /*
-                * Disable DMA on the host.
-                */
-               wbsd_write_index(host, WBSD_IDX_DMA, 0);
-
-               /*
-                * Turn of ISA DMA controller.
-                */
-               dmaflags = claim_dma_lock();
-               disable_dma(host->dma);
-               clear_dma_ff(host->dma);
-               count = get_dma_residue(host->dma);
-               release_dma_lock(dmaflags);
-
-               /*
-                * Any leftover data?
-                */
-               if (count) {
-                       printk(KERN_ERR "%s: Incomplete DMA transfer. "
-                               "%d bytes left.\n",
-                               mmc_hostname(host->mmc), count);
-
-                       data->error = MMC_ERR_FAILED;
-               } else {
-                       /*
-                        * Transfer data from DMA buffer to
-                        * SG list.
-                        */
-                       if (data->flags & MMC_DATA_READ)
-                               wbsd_dma_to_sg(host, data);
-
-                       data->bytes_xfered = host->size;
-               }
-       }
-
-       DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-
-       wbsd_request_end(host, host->mrq);
-}
-
-/*****************************************************************************\
- *                                                                           *
- * MMC layer callbacks                                                       *
- *                                                                           *
-\*****************************************************************************/
-
-static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct wbsd_host *host = mmc_priv(mmc);
-       struct mmc_command *cmd;
-
-       /*
-        * Disable tasklets to avoid a deadlock.
-        */
-       spin_lock_bh(&host->lock);
-
-       BUG_ON(host->mrq != NULL);
-
-       cmd = mrq->cmd;
-
-       host->mrq = mrq;
-
-       /*
-        * If there is no card in the slot then
-        * timeout immediatly.
-        */
-       if (!(host->flags & WBSD_FCARD_PRESENT)) {
-               cmd->error = MMC_ERR_TIMEOUT;
-               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
-                * just go back to the idle state and won't send any data
-                * interrupts.
-                */
-               switch (cmd->opcode) {
-               case 11:
-               case 17:
-               case 18:
-               case 20:
-               case 24:
-               case 25:
-               case 26:
-               case 27:
-               case 30:
-               case 42:
-               case 56:
-                       break;
-
-               /* ACMDs. We don't keep track of state, so we just treat them
-                * like any other command. */
-               case 51:
-                       break;
-
-               default:
-#ifdef CONFIG_MMC_DEBUG
-                       printk(KERN_WARNING "%s: Data command %d is not "
-                               "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);
-
-                       goto done;
-               };
-
-               /*
-                * Dirty fix for hardware bug.
-                */
-               if (host->dma == -1)
-                       tasklet_schedule(&host->fifo_tasklet);
-
-               spin_unlock_bh(&host->lock);
-
-               return;
-       }
-
-done:
-       wbsd_request_end(host, mrq);
-
-       spin_unlock_bh(&host->lock);
-}
-
-static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct wbsd_host *host = mmc_priv(mmc);
-       u8 clk, setup, pwr;
-
-       spin_lock_bh(&host->lock);
-
-       /*
-        * Reset the chip on each power off.
-        * Should clear out any weird states.
-        */
-       if (ios->power_mode == MMC_POWER_OFF)
-               wbsd_init_device(host);
-
-       if (ios->clock >= 24000000)
-               clk = WBSD_CLK_24M;
-       else if (ios->clock >= 16000000)
-               clk = WBSD_CLK_16M;
-       else if (ios->clock >= 12000000)
-               clk = WBSD_CLK_12M;
-       else
-               clk = WBSD_CLK_375K;
-
-       /*
-        * Only write to the clock register when
-        * there is an actual change.
-        */
-       if (clk != host->clk) {
-               wbsd_write_index(host, WBSD_IDX_CLK, clk);
-               host->clk = clk;
-       }
-
-       /*
-        * Power up card.
-        */
-       if (ios->power_mode != MMC_POWER_OFF) {
-               pwr = inb(host->base + WBSD_CSR);
-               pwr &= ~WBSD_POWER_N;
-               outb(pwr, host->base + WBSD_CSR);
-       }
-
-       /*
-        * MMC cards need to have pin 1 high during init.
-        * It wreaks havoc with the card detection though so
-        * that needs to be disabled.
-        */
-       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
-       if (ios->chip_select == MMC_CS_HIGH) {
-               BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
-               setup |= WBSD_DAT3_H;
-               host->flags |= WBSD_FIGNORE_DETECT;
-       } else {
-               if (setup & WBSD_DAT3_H) {
-                       setup &= ~WBSD_DAT3_H;
-
-                       /*
-                        * We cannot resume card detection immediatly
-                        * because of capacitance and delays in the chip.
-                        */
-                       mod_timer(&host->ignore_timer, jiffies + HZ / 100);
-               }
-       }
-       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
-       /*
-        * Store bus width for later. Will be used when
-        * setting up the data transfer.
-        */
-       host->bus_width = ios->bus_width;
-
-       spin_unlock_bh(&host->lock);
-}
-
-static int wbsd_get_ro(struct mmc_host *mmc)
-{
-       struct wbsd_host *host = mmc_priv(mmc);
-       u8 csr;
-
-       spin_lock_bh(&host->lock);
-
-       csr = inb(host->base + WBSD_CSR);
-       csr |= WBSD_MSLED;
-       outb(csr, host->base + WBSD_CSR);
-
-       mdelay(1);
-
-       csr = inb(host->base + WBSD_CSR);
-       csr &= ~WBSD_MSLED;
-       outb(csr, host->base + WBSD_CSR);
-
-       spin_unlock_bh(&host->lock);
-
-       return csr & WBSD_WRPT;
-}
-
-static const struct mmc_host_ops wbsd_ops = {
-       .request        = wbsd_request,
-       .set_ios        = wbsd_set_ios,
-       .get_ro         = wbsd_get_ro,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Interrupt handling                                                        *
- *                                                                           *
-\*****************************************************************************/
-
-/*
- * Helper function to reset detection ignore
- */
-
-static void wbsd_reset_ignore(unsigned long data)
-{
-       struct wbsd_host *host = (struct wbsd_host *)data;
-
-       BUG_ON(host == NULL);
-
-       DBG("Resetting card detection ignore\n");
-
-       spin_lock_bh(&host->lock);
-
-       host->flags &= ~WBSD_FIGNORE_DETECT;
-
-       /*
-        * Card status might have changed during the
-        * blackout.
-        */
-       tasklet_schedule(&host->card_tasklet);
-
-       spin_unlock_bh(&host->lock);
-}
-
-/*
- * Tasklets
- */
-
-static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
-{
-       WARN_ON(!host->mrq);
-       if (!host->mrq)
-               return NULL;
-
-       WARN_ON(!host->mrq->cmd);
-       if (!host->mrq->cmd)
-               return NULL;
-
-       WARN_ON(!host->mrq->cmd->data);
-       if (!host->mrq->cmd->data)
-               return NULL;
-
-       return host->mrq->cmd->data;
-}
-
-static void wbsd_tasklet_card(unsigned long param)
-{
-       struct wbsd_host *host = (struct wbsd_host *)param;
-       u8 csr;
-       int delay = -1;
-
-       spin_lock(&host->lock);
-
-       if (host->flags & WBSD_FIGNORE_DETECT) {
-               spin_unlock(&host->lock);
-               return;
-       }
-
-       csr = inb(host->base + WBSD_CSR);
-       WARN_ON(csr == 0xff);
-
-       if (csr & WBSD_CARDPRESENT) {
-               if (!(host->flags & WBSD_FCARD_PRESENT)) {
-                       DBG("Card inserted\n");
-                       host->flags |= WBSD_FCARD_PRESENT;
-
-                       delay = 500;
-               }
-       } else if (host->flags & WBSD_FCARD_PRESENT) {
-               DBG("Card removed\n");
-               host->flags &= ~WBSD_FCARD_PRESENT;
-
-               if (host->mrq) {
-                       printk(KERN_ERR "%s: Card removed during transfer!\n",
-                               mmc_hostname(host->mmc));
-                       wbsd_reset(host);
-
-                       host->mrq->cmd->error = MMC_ERR_FAILED;
-                       tasklet_schedule(&host->finish_tasklet);
-               }
-
-               delay = 0;
-       }
-
-       /*
-        * Unlock first since we might get a call back.
-        */
-
-       spin_unlock(&host->lock);
-
-       if (delay != -1)
-               mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
-}
-
-static void wbsd_tasklet_fifo(unsigned long param)
-{
-       struct wbsd_host *host = (struct wbsd_host *)param;
-       struct mmc_data *data;
-
-       spin_lock(&host->lock);
-
-       if (!host->mrq)
-               goto end;
-
-       data = wbsd_get_data(host);
-       if (!data)
-               goto end;
-
-       if (data->flags & MMC_DATA_WRITE)
-               wbsd_fill_fifo(host);
-       else
-               wbsd_empty_fifo(host);
-
-       /*
-        * Done?
-        */
-       if (host->size == data->bytes_xfered) {
-               wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
-               tasklet_schedule(&host->finish_tasklet);
-       }
-
-end:
-       spin_unlock(&host->lock);
-}
-
-static void wbsd_tasklet_crc(unsigned long param)
-{
-       struct wbsd_host *host = (struct wbsd_host *)param;
-       struct mmc_data *data;
-
-       spin_lock(&host->lock);
-
-       if (!host->mrq)
-               goto end;
-
-       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);
-}
-
-static void wbsd_tasklet_timeout(unsigned long param)
-{
-       struct wbsd_host *host = (struct wbsd_host *)param;
-       struct mmc_data *data;
-
-       spin_lock(&host->lock);
-
-       if (!host->mrq)
-               goto end;
-
-       data = wbsd_get_data(host);
-       if (!data)
-               goto end;
-
-       DBGF("Timeout\n");
-
-       data->error = MMC_ERR_TIMEOUT;
-
-       tasklet_schedule(&host->finish_tasklet);
-
-end:
-       spin_unlock(&host->lock);
-}
-
-static void wbsd_tasklet_finish(unsigned long param)
-{
-       struct wbsd_host *host = (struct wbsd_host *)param;
-       struct mmc_data *data;
-
-       spin_lock(&host->lock);
-
-       WARN_ON(!host->mrq);
-       if (!host->mrq)
-               goto end;
-
-       data = wbsd_get_data(host);
-       if (!data)
-               goto end;
-
-       wbsd_finish_data(host, data);
-
-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
- */
-
-static irqreturn_t wbsd_irq(int irq, void *dev_id)
-{
-       struct wbsd_host *host = dev_id;
-       int isr;
-
-       isr = inb(host->base + WBSD_ISR);
-
-       /*
-        * Was it actually our hardware that caused the interrupt?
-        */
-       if (isr == 0xff || isr == 0x00)
-               return IRQ_NONE;
-
-       host->isr |= isr;
-
-       /*
-        * Schedule tasklets as needed.
-        */
-       if (isr & WBSD_INT_CARD)
-               tasklet_schedule(&host->card_tasklet);
-       if (isr & WBSD_INT_FIFO_THRE)
-               tasklet_schedule(&host->fifo_tasklet);
-       if (isr & WBSD_INT_CRC)
-               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);
-
-       return IRQ_HANDLED;
-}
-
-/*****************************************************************************\
- *                                                                           *
- * Device initialisation and shutdown                                        *
- *                                                                           *
-\*****************************************************************************/
-
-/*
- * Allocate/free MMC structure.
- */
-
-static int __devinit wbsd_alloc_mmc(struct device *dev)
-{
-       struct mmc_host *mmc;
-       struct wbsd_host *host;
-
-       /*
-        * Allocate MMC structure.
-        */
-       mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
-       if (!mmc)
-               return -ENOMEM;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-
-       host->dma = -1;
-
-       /*
-        * Set host parameters.
-        */
-       mmc->ops = &wbsd_ops;
-       mmc->f_min = 375000;
-       mmc->f_max = 24000000;
-       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
-
-       spin_lock_init(&host->lock);
-
-       /*
-        * Set up timers
-        */
-       init_timer(&host->ignore_timer);
-       host->ignore_timer.data = (unsigned long)host;
-       host->ignore_timer.function = wbsd_reset_ignore;
-
-       /*
-        * Maximum number of segments. Worst case is one sector per segment
-        * so this will be 64kB/512.
-        */
-       mmc->max_hw_segs = 128;
-       mmc->max_phys_segs = 128;
-
-       /*
-        * Maximum request size. Also limited by 64KiB buffer.
-        */
-       mmc->max_req_size = 65536;
-
-       /*
-        * Maximum segment size. Could be one segment with the maximum number
-        * of bytes.
-        */
-       mmc->max_seg_size = mmc->max_req_size;
-
-       /*
-        * Maximum block size. We have 12 bits (= 4095) but have to subtract
-        * space for CRC. So the maximum is 4095 - 4*2 = 4087.
-        */
-       mmc->max_blk_size = 4087;
-
-       /*
-        * Maximum block count. There is no real limit so the maximum
-        * request size will be the only restriction.
-        */
-       mmc->max_blk_count = mmc->max_req_size;
-
-       dev_set_drvdata(dev, mmc);
-
-       return 0;
-}
-
-static void __devexit wbsd_free_mmc(struct device *dev)
-{
-       struct mmc_host *mmc;
-       struct wbsd_host *host;
-
-       mmc = dev_get_drvdata(dev);
-       if (!mmc)
-               return;
-
-       host = mmc_priv(mmc);
-       BUG_ON(host == NULL);
-
-       del_timer_sync(&host->ignore_timer);
-
-       mmc_free_host(mmc);
-
-       dev_set_drvdata(dev, NULL);
-}
-
-/*
- * Scan for known chip id:s
- */
-
-static int __devinit wbsd_scan(struct wbsd_host *host)
-{
-       int i, j, k;
-       int id;
-
-       /*
-        * Iterate through all ports, all codes to
-        * find hardware that is in our known list.
-        */
-       for (i = 0; i < ARRAY_SIZE(config_ports); i++) {
-               if (!request_region(config_ports[i], 2, DRIVER_NAME))
-                       continue;
-
-               for (j = 0; j < ARRAY_SIZE(unlock_codes); j++) {
-                       id = 0xFFFF;
-
-                       host->config = config_ports[i];
-                       host->unlock_code = unlock_codes[j];
-
-                       wbsd_unlock_config(host);
-
-                       outb(WBSD_CONF_ID_HI, config_ports[i]);
-                       id = inb(config_ports[i] + 1) << 8;
-
-                       outb(WBSD_CONF_ID_LO, config_ports[i]);
-                       id |= inb(config_ports[i] + 1);
-
-                       wbsd_lock_config(host);
-
-                       for (k = 0; k < ARRAY_SIZE(valid_ids); k++) {
-                               if (id == valid_ids[k]) {
-                                       host->chip_id = id;
-
-                                       return 0;
-                               }
-                       }
-
-                       if (id != 0xFFFF) {
-                               DBG("Unknown hardware (id %x) found at %x\n",
-                                       id, config_ports[i]);
-                       }
-               }
-
-               release_region(config_ports[i], 2);
-       }
-
-       host->config = 0;
-       host->unlock_code = 0;
-
-       return -ENODEV;
-}
-
-/*
- * Allocate/free io port ranges
- */
-
-static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
-{
-       if (base & 0x7)
-               return -EINVAL;
-
-       if (!request_region(base, 8, DRIVER_NAME))
-               return -EIO;
-
-       host->base = base;
-
-       return 0;
-}
-
-static void __devexit wbsd_release_regions(struct wbsd_host *host)
-{
-       if (host->base)
-               release_region(host->base, 8);
-
-       host->base = 0;
-
-       if (host->config)
-               release_region(host->config, 2);
-
-       host->config = 0;
-}
-
-/*
- * Allocate/free DMA port and buffer
- */
-
-static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
-{
-       if (dma < 0)
-               return;
-
-       if (request_dma(dma, DRIVER_NAME))
-               goto err;
-
-       /*
-        * We need to allocate a special buffer in
-        * order for ISA to be able to DMA to it.
-        */
-       host->dma_buffer = kmalloc(WBSD_DMA_SIZE,
-               GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN);
-       if (!host->dma_buffer)
-               goto free;
-
-       /*
-        * Translate the address to a physical address.
-        */
-       host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
-               WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-
-       /*
-        * ISA DMA must be aligned on a 64k basis.
-        */
-       if ((host->dma_addr & 0xffff) != 0)
-               goto kfree;
-       /*
-        * ISA cannot access memory above 16 MB.
-        */
-       else if (host->dma_addr >= 0x1000000)
-               goto kfree;
-
-       host->dma = dma;
-
-       return;
-
-kfree:
-       /*
-        * If we've gotten here then there is some kind of alignment bug
-        */
-       BUG_ON(1);
-
-       dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
-               WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-       host->dma_addr = (dma_addr_t)NULL;
-
-       kfree(host->dma_buffer);
-       host->dma_buffer = NULL;
-
-free:
-       free_dma(dma);
-
-err:
-       printk(KERN_WARNING DRIVER_NAME ": Unable to allocate DMA %d. "
-               "Falling back on FIFO.\n", dma);
-}
-
-static void __devexit wbsd_release_dma(struct wbsd_host *host)
-{
-       if (host->dma_addr) {
-               dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
-                       WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-       }
-       kfree(host->dma_buffer);
-       if (host->dma >= 0)
-               free_dma(host->dma);
-
-       host->dma = -1;
-       host->dma_buffer = NULL;
-       host->dma_addr = (dma_addr_t)NULL;
-}
-
-/*
- * Allocate/free IRQ.
- */
-
-static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
-{
-       int ret;
-
-       /*
-        * Allocate interrupt.
-        */
-
-       ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host);
-       if (ret)
-               return ret;
-
-       host->irq = irq;
-
-       /*
-        * Set up tasklets.
-        */
-       tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
-                       (unsigned long)host);
-       tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo,
-                       (unsigned long)host);
-       tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc,
-                       (unsigned long)host);
-       tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout,
-                       (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;
-}
-
-static void __devexit wbsd_release_irq(struct wbsd_host *host)
-{
-       if (!host->irq)
-               return;
-
-       free_irq(host->irq, host);
-
-       host->irq = 0;
-
-       tasklet_kill(&host->card_tasklet);
-       tasklet_kill(&host->fifo_tasklet);
-       tasklet_kill(&host->crc_tasklet);
-       tasklet_kill(&host->timeout_tasklet);
-       tasklet_kill(&host->finish_tasklet);
-       tasklet_kill(&host->block_tasklet);
-}
-
-/*
- * Allocate all resources for the host.
- */
-
-static int __devinit wbsd_request_resources(struct wbsd_host *host,
-       int base, int irq, int dma)
-{
-       int ret;
-
-       /*
-        * Allocate I/O ports.
-        */
-       ret = wbsd_request_region(host, base);
-       if (ret)
-               return ret;
-
-       /*
-        * Allocate interrupt.
-        */
-       ret = wbsd_request_irq(host, irq);
-       if (ret)
-               return ret;
-
-       /*
-        * Allocate DMA.
-        */
-       wbsd_request_dma(host, dma);
-
-       return 0;
-}
-
-/*
- * Release all resources for the host.
- */
-
-static void __devexit wbsd_release_resources(struct wbsd_host *host)
-{
-       wbsd_release_dma(host);
-       wbsd_release_irq(host);
-       wbsd_release_regions(host);
-}
-
-/*
- * Configure the resources the chip should use.
- */
-
-static void wbsd_chip_config(struct wbsd_host *host)
-{
-       wbsd_unlock_config(host);
-
-       /*
-        * Reset the chip.
-        */
-       wbsd_write_config(host, WBSD_CONF_SWRST, 1);
-       wbsd_write_config(host, WBSD_CONF_SWRST, 0);
-
-       /*
-        * Select SD/MMC function.
-        */
-       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-
-       /*
-        * Set up card detection.
-        */
-       wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
-
-       /*
-        * Configure chip
-        */
-       wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
-       wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-
-       wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
-
-       if (host->dma >= 0)
-               wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
-
-       /*
-        * Enable and power up chip.
-        */
-       wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
-       wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
-
-       wbsd_lock_config(host);
-}
-
-/*
- * Check that configured resources are correct.
- */
-
-static int wbsd_chip_validate(struct wbsd_host *host)
-{
-       int base, irq, dma;
-
-       wbsd_unlock_config(host);
-
-       /*
-        * Select SD/MMC function.
-        */
-       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-
-       /*
-        * Read configuration.
-        */
-       base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
-       base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
-
-       irq = wbsd_read_config(host, WBSD_CONF_IRQ);
-
-       dma = wbsd_read_config(host, WBSD_CONF_DRQ);
-
-       wbsd_lock_config(host);
-
-       /*
-        * Validate against given configuration.
-        */
-       if (base != host->base)
-               return 0;
-       if (irq != host->irq)
-               return 0;
-       if ((dma != host->dma) && (host->dma != -1))
-               return 0;
-
-       return 1;
-}
-
-/*
- * Powers down the SD function
- */
-
-static void wbsd_chip_poweroff(struct wbsd_host *host)
-{
-       wbsd_unlock_config(host);
-
-       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-       wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
-
-       wbsd_lock_config(host);
-}
-
-/*****************************************************************************\
- *                                                                           *
- * Devices setup and shutdown                                                *
- *                                                                           *
-\*****************************************************************************/
-
-static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
-       int pnp)
-{
-       struct wbsd_host *host = NULL;
-       struct mmc_host *mmc = NULL;
-       int ret;
-
-       ret = wbsd_alloc_mmc(dev);
-       if (ret)
-               return ret;
-
-       mmc = dev_get_drvdata(dev);
-       host = mmc_priv(mmc);
-
-       /*
-        * Scan for hardware.
-        */
-       ret = wbsd_scan(host);
-       if (ret) {
-               if (pnp && (ret == -ENODEV)) {
-                       printk(KERN_WARNING DRIVER_NAME
-                               ": Unable to confirm device presence. You may "
-                               "experience lock-ups.\n");
-               } else {
-                       wbsd_free_mmc(dev);
-                       return ret;
-               }
-       }
-
-       /*
-        * Request resources.
-        */
-       ret = wbsd_request_resources(host, base, irq, dma);
-       if (ret) {
-               wbsd_release_resources(host);
-               wbsd_free_mmc(dev);
-               return ret;
-       }
-
-       /*
-        * See if chip needs to be configured.
-        */
-       if (pnp) {
-               if ((host->config != 0) && !wbsd_chip_validate(host)) {
-                       printk(KERN_WARNING DRIVER_NAME
-                               ": PnP active but chip not configured! "
-                               "You probably have a buggy BIOS. "
-                               "Configuring chip manually.\n");
-                       wbsd_chip_config(host);
-               }
-       } else
-               wbsd_chip_config(host);
-
-       /*
-        * Power Management stuff. No idea how this works.
-        * Not tested.
-        */
-#ifdef CONFIG_PM
-       if (host->config) {
-               wbsd_unlock_config(host);
-               wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
-               wbsd_lock_config(host);
-       }
-#endif
-       /*
-        * Allow device to initialise itself properly.
-        */
-       mdelay(5);
-
-       /*
-        * Reset the chip into a known state.
-        */
-       wbsd_init_device(host);
-
-       mmc_add_host(mmc);
-
-       printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
-       if (host->chip_id != 0)
-               printk(" id %x", (int)host->chip_id);
-       printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
-       if (host->dma >= 0)
-               printk(" dma %d", (int)host->dma);
-       else
-               printk(" FIFO");
-       if (pnp)
-               printk(" PnP");
-       printk("\n");
-
-       return 0;
-}
-
-static void __devexit wbsd_shutdown(struct device *dev, int pnp)
-{
-       struct mmc_host *mmc = dev_get_drvdata(dev);
-       struct wbsd_host *host;
-
-       if (!mmc)
-               return;
-
-       host = mmc_priv(mmc);
-
-       mmc_remove_host(mmc);
-
-       /*
-        * Power down the SD/MMC function.
-        */
-       if (!pnp)
-               wbsd_chip_poweroff(host);
-
-       wbsd_release_resources(host);
-
-       wbsd_free_mmc(dev);
-}
-
-/*
- * Non-PnP
- */
-
-static int __devinit wbsd_probe(struct platform_device *dev)
-{
-       /* Use the module parameters for resources */
-       return wbsd_init(&dev->dev, io, irq, dma, 0);
-}
-
-static int __devexit wbsd_remove(struct platform_device *dev)
-{
-       wbsd_shutdown(&dev->dev, 0);
-
-       return 0;
-}
-
-/*
- * PnP
- */
-
-#ifdef CONFIG_PNP
-
-static int __devinit
-wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
-{
-       int io, irq, dma;
-
-       /*
-        * Get resources from PnP layer.
-        */
-       io = pnp_port_start(pnpdev, 0);
-       irq = pnp_irq(pnpdev, 0);
-       if (pnp_dma_valid(pnpdev, 0))
-               dma = pnp_dma(pnpdev, 0);
-       else
-               dma = -1;
-
-       DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
-
-       return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
-}
-
-static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
-{
-       wbsd_shutdown(&dev->dev, 1);
-}
-
-#endif /* CONFIG_PNP */
-
-/*
- * Power management
- */
-
-#ifdef CONFIG_PM
-
-static int wbsd_suspend(struct wbsd_host *host, pm_message_t state)
-{
-       BUG_ON(host == NULL);
-
-       return mmc_suspend_host(host->mmc, state);
-}
-
-static int wbsd_resume(struct wbsd_host *host)
-{
-       BUG_ON(host == NULL);
-
-       wbsd_init_device(host);
-
-       return mmc_resume_host(host->mmc);
-}
-
-static int wbsd_platform_suspend(struct platform_device *dev,
-                                pm_message_t state)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-       struct wbsd_host *host;
-       int ret;
-
-       if (mmc == NULL)
-               return 0;
-
-       DBGF("Suspending...\n");
-
-       host = mmc_priv(mmc);
-
-       ret = wbsd_suspend(host, state);
-       if (ret)
-               return ret;
-
-       wbsd_chip_poweroff(host);
-
-       return 0;
-}
-
-static int wbsd_platform_resume(struct platform_device *dev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-       struct wbsd_host *host;
-
-       if (mmc == NULL)
-               return 0;
-
-       DBGF("Resuming...\n");
-
-       host = mmc_priv(mmc);
-
-       wbsd_chip_config(host);
-
-       /*
-        * Allow device to initialise itself properly.
-        */
-       mdelay(5);
-
-       return wbsd_resume(host);
-}
-
-#ifdef CONFIG_PNP
-
-static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
-{
-       struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
-       struct wbsd_host *host;
-
-       if (mmc == NULL)
-               return 0;
-
-       DBGF("Suspending...\n");
-
-       host = mmc_priv(mmc);
-
-       return wbsd_suspend(host, state);
-}
-
-static int wbsd_pnp_resume(struct pnp_dev *pnp_dev)
-{
-       struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
-       struct wbsd_host *host;
-
-       if (mmc == NULL)
-               return 0;
-
-       DBGF("Resuming...\n");
-
-       host = mmc_priv(mmc);
-
-       /*
-        * See if chip needs to be configured.
-        */
-       if (host->config != 0) {
-               if (!wbsd_chip_validate(host)) {
-                       printk(KERN_WARNING DRIVER_NAME
-                               ": PnP active but chip not configured! "
-                               "You probably have a buggy BIOS. "
-                               "Configuring chip manually.\n");
-                       wbsd_chip_config(host);
-               }
-       }
-
-       /*
-        * Allow device to initialise itself properly.
-        */
-       mdelay(5);
-
-       return wbsd_resume(host);
-}
-
-#endif /* CONFIG_PNP */
-
-#else /* CONFIG_PM */
-
-#define wbsd_platform_suspend NULL
-#define wbsd_platform_resume NULL
-
-#define wbsd_pnp_suspend NULL
-#define wbsd_pnp_resume NULL
-
-#endif /* CONFIG_PM */
-
-static struct platform_device *wbsd_device;
-
-static struct platform_driver wbsd_driver = {
-       .probe          = wbsd_probe,
-       .remove         = __devexit_p(wbsd_remove),
-
-       .suspend        = wbsd_platform_suspend,
-       .resume         = wbsd_platform_resume,
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-};
-
-#ifdef CONFIG_PNP
-
-static struct pnp_driver wbsd_pnp_driver = {
-       .name           = DRIVER_NAME,
-       .id_table       = pnp_dev_table,
-       .probe          = wbsd_pnp_probe,
-       .remove         = __devexit_p(wbsd_pnp_remove),
-
-       .suspend        = wbsd_pnp_suspend,
-       .resume         = wbsd_pnp_resume,
-};
-
-#endif /* CONFIG_PNP */
-
-/*
- * Module loading/unloading
- */
-
-static int __init wbsd_drv_init(void)
-{
-       int result;
-
-       printk(KERN_INFO DRIVER_NAME
-               ": Winbond W83L51xD SD/MMC card interface driver\n");
-       printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
-
-#ifdef CONFIG_PNP
-
-       if (!nopnp) {
-               result = pnp_register_driver(&wbsd_pnp_driver);
-               if (result < 0)
-                       return result;
-       }
-#endif /* CONFIG_PNP */
-
-       if (nopnp) {
-               result = platform_driver_register(&wbsd_driver);
-               if (result < 0)
-                       return result;
-
-               wbsd_device = platform_device_alloc(DRIVER_NAME, -1);
-               if (!wbsd_device) {
-                       platform_driver_unregister(&wbsd_driver);
-                       return -ENOMEM;
-               }
-
-               result = platform_device_add(wbsd_device);
-               if (result) {
-                       platform_device_put(wbsd_device);
-                       platform_driver_unregister(&wbsd_driver);
-                       return result;
-               }
-       }
-
-       return 0;
-}
-
-static void __exit wbsd_drv_exit(void)
-{
-#ifdef CONFIG_PNP
-
-       if (!nopnp)
-               pnp_unregister_driver(&wbsd_pnp_driver);
-
-#endif /* CONFIG_PNP */
-
-       if (nopnp) {
-               platform_device_unregister(wbsd_device);
-
-               platform_driver_unregister(&wbsd_driver);
-       }
-
-       DBG("unloaded\n");
-}
-
-module_init(wbsd_drv_init);
-module_exit(wbsd_drv_exit);
-#ifdef CONFIG_PNP
-module_param(nopnp, uint, 0444);
-#endif
-module_param(io, uint, 0444);
-module_param(irq, uint, 0444);
-module_param(dma, int, 0444);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
-MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
-
-#ifdef CONFIG_PNP
-MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)");
-#endif
-MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)");
-MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)");
-MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)");
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
deleted file mode 100644 (file)
index d06718b..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *  linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
- *
- *  Copyright (C) 2004-2005 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.
- */
-
-#define LOCK_CODE              0xAA
-
-#define WBSD_CONF_SWRST                0x02
-#define WBSD_CONF_DEVICE       0x07
-#define WBSD_CONF_ID_HI                0x20
-#define WBSD_CONF_ID_LO                0x21
-#define WBSD_CONF_POWER                0x22
-#define WBSD_CONF_PME          0x23
-#define WBSD_CONF_PMES         0x24
-
-#define WBSD_CONF_ENABLE       0x30
-#define WBSD_CONF_PORT_HI      0x60
-#define WBSD_CONF_PORT_LO      0x61
-#define WBSD_CONF_IRQ          0x70
-#define WBSD_CONF_DRQ          0x74
-
-#define WBSD_CONF_PINS         0xF0
-
-#define DEVICE_SD              0x03
-
-#define WBSD_PINS_DAT3_HI      0x20
-#define WBSD_PINS_DAT3_OUT     0x10
-#define WBSD_PINS_GP11_HI      0x04
-#define WBSD_PINS_DETECT_GP11  0x02
-#define WBSD_PINS_DETECT_DAT3  0x01
-
-#define WBSD_CMDR              0x00
-#define WBSD_DFR               0x01
-#define WBSD_EIR               0x02
-#define WBSD_ISR               0x03
-#define WBSD_FSR               0x04
-#define WBSD_IDXR              0x05
-#define WBSD_DATAR             0x06
-#define WBSD_CSR               0x07
-
-#define WBSD_EINT_CARD         0x40
-#define WBSD_EINT_FIFO_THRE    0x20
-#define WBSD_EINT_CCRC         0x10
-#define WBSD_EINT_TIMEOUT      0x08
-#define WBSD_EINT_PROGEND      0x04
-#define WBSD_EINT_CRC          0x02
-#define WBSD_EINT_TC           0x01
-
-#define WBSD_INT_PENDING       0x80
-#define WBSD_INT_CARD          0x40
-#define WBSD_INT_FIFO_THRE     0x20
-#define WBSD_INT_CRC           0x10
-#define WBSD_INT_TIMEOUT       0x08
-#define WBSD_INT_PROGEND       0x04
-#define WBSD_INT_BUSYEND       0x02
-#define WBSD_INT_TC            0x01
-
-#define WBSD_FIFO_EMPTY                0x80
-#define WBSD_FIFO_FULL         0x40
-#define WBSD_FIFO_EMTHRE       0x20
-#define WBSD_FIFO_FUTHRE       0x10
-#define WBSD_FIFO_SZMASK       0x0F
-
-#define WBSD_MSLED             0x20
-#define WBSD_POWER_N           0x10
-#define WBSD_WRPT              0x04
-#define WBSD_CARDPRESENT       0x01
-
-#define WBSD_IDX_CLK           0x01
-#define WBSD_IDX_PBSMSB                0x02
-#define WBSD_IDX_TAAC          0x03
-#define WBSD_IDX_NSAC          0x04
-#define WBSD_IDX_PBSLSB                0x05
-#define WBSD_IDX_SETUP         0x06
-#define WBSD_IDX_DMA           0x07
-#define WBSD_IDX_FIFOEN                0x08
-#define WBSD_IDX_STATUS                0x10
-#define WBSD_IDX_RSPLEN                0x1E
-#define WBSD_IDX_RESP0         0x1F
-#define WBSD_IDX_RESP1         0x20
-#define WBSD_IDX_RESP2         0x21
-#define WBSD_IDX_RESP3         0x22
-#define WBSD_IDX_RESP4         0x23
-#define WBSD_IDX_RESP5         0x24
-#define WBSD_IDX_RESP6         0x25
-#define WBSD_IDX_RESP7         0x26
-#define WBSD_IDX_RESP8         0x27
-#define WBSD_IDX_RESP9         0x28
-#define WBSD_IDX_RESP10                0x29
-#define WBSD_IDX_RESP11                0x2A
-#define WBSD_IDX_RESP12                0x2B
-#define WBSD_IDX_RESP13                0x2C
-#define WBSD_IDX_RESP14                0x2D
-#define WBSD_IDX_RESP15                0x2E
-#define WBSD_IDX_RESP16                0x2F
-#define WBSD_IDX_CRCSTATUS     0x30
-#define WBSD_IDX_ISR           0x3F
-
-#define WBSD_CLK_375K          0x00
-#define WBSD_CLK_12M           0x01
-#define WBSD_CLK_16M           0x02
-#define WBSD_CLK_24M           0x03
-
-#define WBSD_DATA_WIDTH                0x01
-
-#define WBSD_DAT3_H            0x08
-#define WBSD_FIFO_RESET                0x04
-#define WBSD_SOFT_RESET                0x02
-#define WBSD_INC_INDEX         0x01
-
-#define WBSD_DMA_SINGLE                0x02
-#define WBSD_DMA_ENABLE                0x01
-
-#define WBSD_FIFOEN_EMPTY      0x20
-#define WBSD_FIFOEN_FULL       0x10
-#define WBSD_FIFO_THREMASK     0x0F
-
-#define WBSD_BLOCK_READ                0x80
-#define WBSD_BLOCK_WRITE       0x40
-#define WBSD_BUSY              0x20
-#define WBSD_CARDTRAFFIC       0x04
-#define WBSD_SENDCMD           0x02
-#define WBSD_RECVRES           0x01
-
-#define WBSD_RSP_SHORT         0x00
-#define WBSD_RSP_LONG          0x01
-
-#define WBSD_CRC_MASK          0x1F
-#define WBSD_CRC_OK            0x05 /* S010E (00101) */
-#define WBSD_CRC_FAIL          0x0B /* S101E (01011) */
-
-#define WBSD_DMA_SIZE          65536
-
-struct wbsd_host
-{
-       struct mmc_host*        mmc;            /* MMC structure */
-
-       spinlock_t              lock;           /* Mutex */
-
-       int                     flags;          /* Driver states */
-
-#define WBSD_FCARD_PRESENT     (1<<0)          /* Card is present */
-#define WBSD_FIGNORE_DETECT    (1<<1)          /* Ignore card detection */
-
-       struct mmc_request*     mrq;            /* Current request */
-
-       u8                      isr;            /* Accumulated ISR */
-
-       struct scatterlist*     cur_sg;         /* Current SG entry */
-       unsigned int            num_sg;         /* Number of entries left */
-
-       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 */
-
-       int                     firsterr;       /* See fifo functions */
-
-       u8                      clk;            /* Current clock speed */
-       unsigned char           bus_width;      /* Current bus width */
-
-       int                     config;         /* Config port */
-       u8                      unlock_code;    /* Code to unlock config */
-
-       int                     chip_id;        /* ID of controller */
-
-       int                     base;           /* I/O port base */
-       int                     irq;            /* Interrupt */
-       int                     dma;            /* DMA channel */
-
-       struct tasklet_struct   card_tasklet;   /* Tasklet structures */
-       struct tasklet_struct   fifo_tasklet;
-       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 */
-};
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 ad9a136..9e6933a 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;
@@ -699,6 +712,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)
 {
@@ -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;
 }
@@ -1248,11 +1446,64 @@ 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);
        }
 }
 
@@ -1992,6 +2261,23 @@ bnx2_msi(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
+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)
 {
@@ -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 fb196fd..55ff0fb 100644 (file)
@@ -134,7 +134,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
                        DCSR(si->rxdma) &= ~DCSR_RUN;
                        /* disable FICP */
                        ICCR0 = 0;
-                       pxa_set_cken(CKEN13_FICP, 0);
+                       pxa_set_cken(CKEN_FICP, 0);
 
                        /* set board transceiver to SIR mode */
                        si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
@@ -144,7 +144,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
                        pxa_gpio_mode(GPIO47_STTXD_MD);
 
                        /* enable the STUART clock */
-                       pxa_set_cken(CKEN5_STUART, 1);
+                       pxa_set_cken(CKEN_STUART, 1);
                }
 
                /* disable STUART first */
@@ -169,7 +169,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
                /* disable STUART */
                STIER = 0;
                STISR = 0;
-               pxa_set_cken(CKEN5_STUART, 0);
+               pxa_set_cken(CKEN_STUART, 0);
 
                /* disable FICP first */
                ICCR0 = 0;
@@ -182,7 +182,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
                pxa_gpio_mode(GPIO47_ICPTXD_MD);
 
                /* enable the FICP clock */
-               pxa_set_cken(CKEN13_FICP, 1);
+               pxa_set_cken(CKEN_FICP, 1);
 
                si->speed = speed;
                pxa_irda_fir_dma_rx_start(si);
@@ -593,7 +593,7 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
        /* disable STUART SIR mode */
        STISR = 0;
        /* disable the STUART clock */
-       pxa_set_cken(CKEN5_STUART, 0);
+       pxa_set_cken(CKEN_STUART, 0);
 
        /* disable DMA */
        DCSR(si->txdma) &= ~DCSR_RUN;
@@ -601,7 +601,7 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
        /* disable FICP */
        ICCR0 = 0;
        /* disable the FICP clock */
-       pxa_set_cken(CKEN13_FICP, 0);
+       pxa_set_cken(CKEN_FICP, 0);
 
        DRCMR17 = 0;
        DRCMR18 = 0;
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 <linux/sched.h>
 #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;
@@ -891,6 +890,34 @@ pci_disable_device(struct pci_dev *dev)
        pcibios_disable_device(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
@@ -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.
                 */
@@ -2246,16 +2271,6 @@ static int __init BusLogic_init(void)
                   and Electronic Mail Address.
                 */
                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 72fb5ec..e62d23f 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 f69bd09..1a9a24b 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/serial.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
+#include <linux/clk.h>
 
 #include <asm/io.h>
 
@@ -70,6 +71,7 @@
  */
 struct uart_amba_port {
        struct uart_port        port;
+       struct clk              *clk;
        struct amba_device      *dev;
        struct amba_pl010_data  *data;
        unsigned int            old_status;
@@ -77,73 +79,77 @@ struct uart_amba_port {
 
 static void pl010_stop_tx(struct uart_port *port)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int cr;
 
-       cr = readb(port->membase + UART010_CR);
+       cr = readb(uap->port.membase + UART010_CR);
        cr &= ~UART010_CR_TIE;
-       writel(cr, port->membase + UART010_CR);
+       writel(cr, uap->port.membase + UART010_CR);
 }
 
 static void pl010_start_tx(struct uart_port *port)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int cr;
 
-       cr = readb(port->membase + UART010_CR);
+       cr = readb(uap->port.membase + UART010_CR);
        cr |= UART010_CR_TIE;
-       writel(cr, port->membase + UART010_CR);
+       writel(cr, uap->port.membase + UART010_CR);
 }
 
 static void pl010_stop_rx(struct uart_port *port)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int cr;
 
-       cr = readb(port->membase + UART010_CR);
+       cr = readb(uap->port.membase + UART010_CR);
        cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
-       writel(cr, port->membase + UART010_CR);
+       writel(cr, uap->port.membase + UART010_CR);
 }
 
 static void pl010_enable_ms(struct uart_port *port)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int cr;
 
-       cr = readb(port->membase + UART010_CR);
+       cr = readb(uap->port.membase + UART010_CR);
        cr |= UART010_CR_MSIE;
-       writel(cr, port->membase + UART010_CR);
+       writel(cr, uap->port.membase + UART010_CR);
 }
 
-static void pl010_rx_chars(struct uart_port *port)
+static void pl010_rx_chars(struct uart_amba_port *uap)
 {
-       struct tty_struct *tty = port->info->tty;
+       struct tty_struct *tty = uap->port.info->tty;
        unsigned int status, ch, flag, rsr, max_count = 256;
 
-       status = readb(port->membase + UART01x_FR);
+       status = readb(uap->port.membase + UART01x_FR);
        while (UART_RX_DATA(status) && max_count--) {
-               ch = readb(port->membase + UART01x_DR);
+               ch = readb(uap->port.membase + UART01x_DR);
                flag = TTY_NORMAL;
 
-               port->icount.rx++;
+               uap->port.icount.rx++;
 
                /*
                 * Note that the error handling code is
                 * out of the main execution path
                 */
-               rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
+               rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
                if (unlikely(rsr & UART01x_RSR_ANY)) {
-                       writel(0, port->membase + UART01x_ECR);
+                       writel(0, uap->port.membase + UART01x_ECR);
 
                        if (rsr & UART01x_RSR_BE) {
                                rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
-                               port->icount.brk++;
-                               if (uart_handle_break(port))
+                               uap->port.icount.brk++;
+                               if (uart_handle_break(&uap->port))
                                        goto ignore_char;
                        } else if (rsr & UART01x_RSR_PE)
-                               port->icount.parity++;
+                               uap->port.icount.parity++;
                        else if (rsr & UART01x_RSR_FE)
-                               port->icount.frame++;
+                               uap->port.icount.frame++;
                        if (rsr & UART01x_RSR_OE)
-                               port->icount.overrun++;
+                               uap->port.icount.overrun++;
 
-                       rsr &= port->read_status_mask;
+                       rsr &= uap->port.read_status_mask;
 
                        if (rsr & UART01x_RSR_BE)
                                flag = TTY_BREAK;
@@ -153,53 +159,52 @@ static void pl010_rx_chars(struct uart_port *port)
                                flag = TTY_FRAME;
                }
 
-               if (uart_handle_sysrq_char(port, ch))
+               if (uart_handle_sysrq_char(&uap->port, ch))
                        goto ignore_char;
 
-               uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
+               uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
 
        ignore_char:
-               status = readb(port->membase + UART01x_FR);
+               status = readb(uap->port.membase + UART01x_FR);
        }
        tty_flip_buffer_push(tty);
        return;
 }
 
-static void pl010_tx_chars(struct uart_port *port)
+static void pl010_tx_chars(struct uart_amba_port *uap)
 {
-       struct circ_buf *xmit = &port->info->xmit;
+       struct circ_buf *xmit = &uap->port.info->xmit;
        int count;
 
-       if (port->x_char) {
-               writel(port->x_char, port->membase + UART01x_DR);
-               port->icount.tx++;
-               port->x_char = 0;
+       if (uap->port.x_char) {
+               writel(uap->port.x_char, uap->port.membase + UART01x_DR);
+               uap->port.icount.tx++;
+               uap->port.x_char = 0;
                return;
        }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               pl010_stop_tx(port);
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
+               pl010_stop_tx(&uap->port);
                return;
        }
 
-       count = port->fifosize >> 1;
+       count = uap->port.fifosize >> 1;
        do {
-               writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
+               writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
+               uap->port.icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
        } while (--count > 0);
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+               uart_write_wakeup(&uap->port);
 
        if (uart_circ_empty(xmit))
-               pl010_stop_tx(port);
+               pl010_stop_tx(&uap->port);
 }
 
-static void pl010_modem_status(struct uart_port *port)
+static void pl010_modem_status(struct uart_amba_port *uap)
 {
-       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int status, delta;
 
        writel(0, uap->port.membase + UART010_ICR);
@@ -226,47 +231,50 @@ static void pl010_modem_status(struct uart_port *port)
 
 static irqreturn_t pl010_int(int irq, void *dev_id)
 {
-       struct uart_port *port = dev_id;
+       struct uart_amba_port *uap = dev_id;
        unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
        int handled = 0;
 
-       spin_lock(&port->lock);
+       spin_lock(&uap->port.lock);
 
-       status = readb(port->membase + UART010_IIR);
+       status = readb(uap->port.membase + UART010_IIR);
        if (status) {
                do {
                        if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
-                               pl010_rx_chars(port);
+                               pl010_rx_chars(uap);
                        if (status & UART010_IIR_MIS)
-                               pl010_modem_status(port);
+                               pl010_modem_status(uap);
                        if (status & UART010_IIR_TIS)
-                               pl010_tx_chars(port);
+                               pl010_tx_chars(uap);
 
                        if (pass_counter-- == 0)
                                break;
 
-                       status = readb(port->membase + UART010_IIR);
+                       status = readb(uap->port.membase + UART010_IIR);
                } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
                                   UART010_IIR_TIS));
                handled = 1;
        }
 
-       spin_unlock(&port->lock);
+       spin_unlock(&uap->port.lock);
 
        return IRQ_RETVAL(handled);
 }
 
 static unsigned int pl010_tx_empty(struct uart_port *port)
 {
-       return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
+       unsigned int status = readb(uap->port.membase + UART01x_FR);
+       return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
 }
 
 static unsigned int pl010_get_mctrl(struct uart_port *port)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int result = 0;
        unsigned int status;
 
-       status = readb(port->membase + UART01x_FR);
+       status = readb(uap->port.membase + UART01x_FR);
        if (status & UART01x_FR_DCD)
                result |= TIOCM_CAR;
        if (status & UART01x_FR_DSR)
@@ -287,17 +295,18 @@ static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
 static void pl010_break_ctl(struct uart_port *port, int break_state)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned long flags;
        unsigned int lcr_h;
 
-       spin_lock_irqsave(&port->lock, flags);
-       lcr_h = readb(port->membase + UART010_LCRH);
+       spin_lock_irqsave(&uap->port.lock, flags);
+       lcr_h = readb(uap->port.membase + UART010_LCRH);
        if (break_state == -1)
                lcr_h |= UART01x_LCRH_BRK;
        else
                lcr_h &= ~UART01x_LCRH_BRK;
-       writel(lcr_h, port->membase + UART010_LCRH);
-       spin_unlock_irqrestore(&port->lock, flags);
+       writel(lcr_h, uap->port.membase + UART010_LCRH);
+       spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
 static int pl010_startup(struct uart_port *port)
@@ -305,49 +314,71 @@ static int pl010_startup(struct uart_port *port)
        struct uart_amba_port *uap = (struct uart_amba_port *)port;
        int retval;
 
+       /*
+        * Try to enable the clock producer.
+        */
+       retval = clk_enable(uap->clk);
+       if (retval)
+               goto out;
+
+       uap->port.uartclk = clk_get_rate(uap->clk);
+
        /*
         * Allocate the IRQ
         */
-       retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", port);
+       retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
        if (retval)
-               return retval;
+               goto clk_dis;
 
        /*
         * initialise the old status of the modem signals
         */
-       uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
+       uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
 
        /*
         * Finally, enable interrupts
         */
        writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
-              port->membase + UART010_CR);
+              uap->port.membase + UART010_CR);
 
        return 0;
+
+ clk_dis:
+       clk_disable(uap->clk);
+ out:
+       return retval;
 }
 
 static void pl010_shutdown(struct uart_port *port)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
+
        /*
         * Free the interrupt
         */
-       free_irq(port->irq, port);
+       free_irq(uap->port.irq, uap);
 
        /*
         * disable all interrupts, disable the port
         */
-       writel(0, port->membase + UART010_CR);
+       writel(0, uap->port.membase + UART010_CR);
 
        /* disable break condition and fifos */
-       writel(readb(port->membase + UART010_LCRH) &
+       writel(readb(uap->port.membase + UART010_LCRH) &
                ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
-              port->membase + UART010_LCRH);
+              uap->port.membase + UART010_LCRH);
+
+       /*
+        * Shut down the clock producer
+        */
+       clk_disable(uap->clk);
 }
 
 static void
 pl010_set_termios(struct uart_port *port, struct ktermios *termios,
                     struct ktermios *old)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int lcr_h, old_cr;
        unsigned long flags;
        unsigned int baud, quot;
@@ -355,7 +386,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
        /*
         * Ask the core to calculate the divisor for us.
         */
-       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+       baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); 
        quot = uart_get_divisor(port, baud);
 
        switch (termios->c_cflag & CSIZE) {
@@ -379,66 +410,66 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
                if (!(termios->c_cflag & PARODD))
                        lcr_h |= UART01x_LCRH_EPS;
        }
-       if (port->fifosize > 1)
+       if (uap->port.fifosize > 1)
                lcr_h |= UART01x_LCRH_FEN;
 
-       spin_lock_irqsave(&port->lock, flags);
+       spin_lock_irqsave(&uap->port.lock, flags);
 
        /*
         * Update the per-port timeout.
         */
        uart_update_timeout(port, termios->c_cflag, baud);
 
-       port->read_status_mask = UART01x_RSR_OE;
+       uap->port.read_status_mask = UART01x_RSR_OE;
        if (termios->c_iflag & INPCK)
-               port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
+               uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
        if (termios->c_iflag & (BRKINT | PARMRK))
-               port->read_status_mask |= UART01x_RSR_BE;
+               uap->port.read_status_mask |= UART01x_RSR_BE;
 
        /*
         * Characters to ignore
         */
-       port->ignore_status_mask = 0;
+       uap->port.ignore_status_mask = 0;
        if (termios->c_iflag & IGNPAR)
-               port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
+               uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
        if (termios->c_iflag & IGNBRK) {
-               port->ignore_status_mask |= UART01x_RSR_BE;
+               uap->port.ignore_status_mask |= UART01x_RSR_BE;
                /*
                 * If we're ignoring parity and break indicators,
                 * ignore overruns too (for real raw support).
                 */
                if (termios->c_iflag & IGNPAR)
-                       port->ignore_status_mask |= UART01x_RSR_OE;
+                       uap->port.ignore_status_mask |= UART01x_RSR_OE;
        }
 
        /*
         * Ignore all characters if CREAD is not set.
         */
        if ((termios->c_cflag & CREAD) == 0)
-               port->ignore_status_mask |= UART_DUMMY_RSR_RX;
+               uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
 
        /* first, disable everything */
-       old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE;
+       old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
 
        if (UART_ENABLE_MS(port, termios->c_cflag))
                old_cr |= UART010_CR_MSIE;
 
-       writel(0, port->membase + UART010_CR);
+       writel(0, uap->port.membase + UART010_CR);
 
        /* Set baud rate */
        quot -= 1;
-       writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM);
-       writel(quot & 0xff, port->membase + UART010_LCRL);
+       writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
+       writel(quot & 0xff, uap->port.membase + UART010_LCRL);
 
        /*
         * ----------v----------v----------v----------v-----
         * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
         * ----------^----------^----------^----------^-----
         */
-       writel(lcr_h, port->membase + UART010_LCRH);
-       writel(old_cr, port->membase + UART010_CR);
+       writel(lcr_h, uap->port.membase + UART010_LCRH);
+       writel(old_cr, uap->port.membase + UART010_CR);
 
-       spin_unlock_irqrestore(&port->lock, flags);
+       spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
 static const char *pl010_type(struct uart_port *port)
@@ -514,47 +545,52 @@ static struct uart_amba_port *amba_ports[UART_NR];
 
 static void pl010_console_putchar(struct uart_port *port, int ch)
 {
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int status;
 
        do {
-               status = readb(port->membase + UART01x_FR);
+               status = readb(uap->port.membase + UART01x_FR);
                barrier();
        } while (!UART_TX_READY(status));
-       writel(ch, port->membase + UART01x_DR);
+       writel(ch, uap->port.membase + UART01x_DR);
 }
 
 static void
 pl010_console_write(struct console *co, const char *s, unsigned int count)
 {
-       struct uart_port *port = &amba_ports[co->index]->port;
+       struct uart_amba_port *uap = amba_ports[co->index];
        unsigned int status, old_cr;
 
+       clk_enable(uap->clk);
+
        /*
         *      First save the CR then disable the interrupts
         */
-       old_cr = readb(port->membase + UART010_CR);
-       writel(UART01x_CR_UARTEN, port->membase + UART010_CR);
+       old_cr = readb(uap->port.membase + UART010_CR);
+       writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
 
-       uart_console_write(port, s, count, pl010_console_putchar);
+       uart_console_write(&uap->port, s, count, pl010_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
         *      and restore the TCR
         */
        do {
-               status = readb(port->membase + UART01x_FR);
+               status = readb(uap->port.membase + UART01x_FR);
                barrier();
        } while (status & UART01x_FR_BUSY);
-       writel(old_cr, port->membase + UART010_CR);
+       writel(old_cr, uap->port.membase + UART010_CR);
+
+       clk_disable(uap->clk);
 }
 
 static void __init
-pl010_console_get_options(struct uart_port *port, int *baud,
+pl010_console_get_options(struct uart_amba_port *uap, int *baud,
                             int *parity, int *bits)
 {
-       if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) {
+       if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
                unsigned int lcr_h, quot;
-               lcr_h = readb(port->membase + UART010_LCRH);
+               lcr_h = readb(uap->port.membase + UART010_LCRH);
 
                *parity = 'n';
                if (lcr_h & UART01x_LCRH_PEN) {
@@ -569,14 +605,15 @@ pl010_console_get_options(struct uart_port *port, int *baud,
                else
                        *bits = 8;
 
-               quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8;
-               *baud = port->uartclk / (16 * (quot + 1));
+               quot = readb(uap->port.membase + UART010_LCRL) |
+                      readb(uap->port.membase + UART010_LCRM) << 8;
+               *baud = uap->port.uartclk / (16 * (quot + 1));
        }
 }
 
 static int __init pl010_console_setup(struct console *co, char *options)
 {
-       struct uart_port *port;
+       struct uart_amba_port *uap;
        int baud = 38400;
        int bits = 8;
        int parity = 'n';
@@ -589,16 +626,18 @@ static int __init pl010_console_setup(struct console *co, char *options)
         */
        if (co->index >= UART_NR)
                co->index = 0;
-       if (!amba_ports[co->index])
+       uap = amba_ports[co->index];
+       if (!uap)
                return -ENODEV;
-       port = &amba_ports[co->index]->port;
+
+       uap->port.uartclk = clk_get_rate(uap->clk);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
        else
-               pl010_console_get_options(port, &baud, &parity, &bits);
+               pl010_console_get_options(uap, &baud, &parity, &bits);
 
-       return uart_set_options(port, co, baud, parity, bits, flow);
+       return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 }
 
 static struct uart_driver amba_reg;
@@ -629,7 +668,7 @@ static struct uart_driver amba_reg = {
 
 static int pl010_probe(struct amba_device *dev, void *id)
 {
-       struct uart_amba_port *port;
+       struct uart_amba_port *uap;
        void __iomem *base;
        int i, ret;
 
@@ -642,8 +681,8 @@ static int pl010_probe(struct amba_device *dev, void *id)
                goto out;
        }
 
-       port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
-       if (!port) {
+       uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
+       if (!uap) {
                ret = -ENOMEM;
                goto out;
        }
@@ -654,51 +693,57 @@ static int pl010_probe(struct amba_device *dev, void *id)
                goto free;
        }
 
-       port->port.dev = &dev->dev;
-       port->port.mapbase = dev->res.start;
-       port->port.membase = base;
-       port->port.iotype = UPIO_MEM;
-       port->port.irq = dev->irq[0];
-       port->port.uartclk = 14745600;
-       port->port.fifosize = 16;
-       port->port.ops = &amba_pl010_pops;
-       port->port.flags = UPF_BOOT_AUTOCONF;
-       port->port.line = i;
-       port->dev = dev;
-       port->data = dev->dev.platform_data;
-
-       amba_ports[i] = port;
-
-       amba_set_drvdata(dev, port);
-       ret = uart_add_one_port(&amba_reg, &port->port);
+       uap->clk = clk_get(&dev->dev, "UARTCLK");
+       if (IS_ERR(uap->clk)) {
+               ret = PTR_ERR(uap->clk);
+               goto unmap;
+       }
+
+       uap->port.dev = &dev->dev;
+       uap->port.mapbase = dev->res.start;
+       uap->port.membase = base;
+       uap->port.iotype = UPIO_MEM;
+       uap->port.irq = dev->irq[0];
+       uap->port.fifosize = 16;
+       uap->port.ops = &amba_pl010_pops;
+       uap->port.flags = UPF_BOOT_AUTOCONF;
+       uap->port.line = i;
+       uap->dev = dev;
+       uap->data = dev->dev.platform_data;
+
+       amba_ports[i] = uap;
+
+       amba_set_drvdata(dev, uap);
+       ret = uart_add_one_port(&amba_reg, &uap->port);
        if (ret) {
                amba_set_drvdata(dev, NULL);
                amba_ports[i] = NULL;
+               clk_put(uap->clk);
+ unmap:
                iounmap(base);
  free:
-               kfree(port);
+               kfree(uap);
        }
-
  out:
        return ret;
 }
 
 static int pl010_remove(struct amba_device *dev)
 {
-       struct uart_amba_port *port = amba_get_drvdata(dev);
+       struct uart_amba_port *uap = amba_get_drvdata(dev);
        int i;
 
        amba_set_drvdata(dev, NULL);
 
-       uart_remove_one_port(&amba_reg, &port->port);
+       uart_remove_one_port(&amba_reg, &uap->port);
 
        for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
-               if (amba_ports[i] == port)
+               if (amba_ports[i] == uap)
                        amba_ports[i] = NULL;
 
-       iounmap(port->port.membase);
-       kfree(port);
-
+       iounmap(uap->port.membase);
+       clk_put(uap->clk);
+       kfree(uap);
        return 0;
 }
 
index 935f48f..3320bcd 100644 (file)
@@ -484,11 +484,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios * termios,
        unsigned long flags;
        unsigned int mode, imr, quot, baud;
 
+       /* Get current mode register */
+       mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
+
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
        quot = uart_get_divisor(port, baud);
 
-       /* Get current mode register */
-       mode = UART_GET_MR(port) & ~(ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
+       if (quot > 65535) {             /* BRGR is 16-bit, so switch to slower clock */
+               quot /= 8;
+               mode |= ATMEL_US_USCLKS_MCK_DIV8;
+       }
 
        /* byte size */
        switch (termios->c_cflag & CSIZE) {
index 11b4436..e014177 100644 (file)
@@ -46,6 +46,9 @@
 #define                        ATMEL_US_USMODE_ISO7816_T1      6
 #define                        ATMEL_US_USMODE_IRDA            8
 #define                ATMEL_US_USCLKS         (3   <<  4)             /* Clock Selection */
+#define                        ATMEL_US_USCLKS_MCK             (0 <<  4)
+#define                        ATMEL_US_USCLKS_MCK_DIV8        (1 <<  4)
+#define                        ATMEL_US_USCLKS_SCK             (3 <<  4)
 #define                ATMEL_US_CHRL           (3   <<  6)             /* Character Length */
 #define                        ATMEL_US_CHRL_5                 (0 <<  6)
 #define                        ATMEL_US_CHRL_6                 (1 <<  6)
index 04cc88c..e42faa4 100644 (file)
 #include <asm/hardware.h>
 #include <asm/arch/imx-uart.h>
 
+/* Register definitions */
+#define URXD0 0x0  /* Receiver Register */
+#define URTX0 0x40 /* Transmitter Register */
+#define UCR1  0x80 /* Control Register 1 */
+#define UCR2  0x84 /* Control Register 2 */
+#define UCR3  0x88 /* Control Register 3 */
+#define UCR4  0x8c /* Control Register 4 */
+#define UFCR  0x90 /* FIFO Control Register */
+#define USR1  0x94 /* Status Register 1 */
+#define USR2  0x98 /* Status Register 2 */
+#define UESC  0x9c /* Escape Character Register */
+#define UTIM  0xa0 /* Escape Timer Register */
+#define UBIR  0xa4 /* BRM Incremental Register */
+#define UBMR  0xa8 /* BRM Modulator Register */
+#define UBRC  0xac /* Baud Rate Count Register */
+#define BIPR1 0xb0 /* Incremental Preset Register 1 */
+#define BIPR2 0xb4 /* Incremental Preset Register 2 */
+#define BIPR3 0xb8 /* Incremental Preset Register 3 */
+#define BIPR4 0xbc /* Incremental Preset Register 4 */
+#define BMPR1 0xc0 /* BRM Modulator Register 1 */
+#define BMPR2 0xc4 /* BRM Modulator Register 2 */
+#define BMPR3 0xc8 /* BRM Modulator Register 3 */
+#define BMPR4 0xcc /* BRM Modulator Register 4 */
+#define UTS   0xd0 /* UART Test Register */
+
+/* UART Control Register Bit Fields.*/
+#define  URXD_CHARRDY    (1<<15)
+#define  URXD_ERR        (1<<14)
+#define  URXD_OVRRUN     (1<<13)
+#define  URXD_FRMERR     (1<<12)
+#define  URXD_BRK        (1<<11)
+#define  URXD_PRERR      (1<<10)
+#define  UCR1_ADEN       (1<<15) /* Auto dectect interrupt */
+#define  UCR1_ADBR       (1<<14) /* Auto detect baud rate */
+#define  UCR1_TRDYEN     (1<<13) /* Transmitter ready interrupt enable */
+#define  UCR1_IDEN       (1<<12) /* Idle condition interrupt */
+#define  UCR1_RRDYEN     (1<<9)         /* Recv ready interrupt enable */
+#define  UCR1_RDMAEN     (1<<8)         /* Recv ready DMA enable */
+#define  UCR1_IREN       (1<<7)         /* Infrared interface enable */
+#define  UCR1_TXMPTYEN   (1<<6)         /* Transimitter empty interrupt enable */
+#define  UCR1_RTSDEN     (1<<5)         /* RTS delta interrupt enable */
+#define  UCR1_SNDBRK     (1<<4)         /* Send break */
+#define  UCR1_TDMAEN     (1<<3)         /* Transmitter ready DMA enable */
+#define  UCR1_UARTCLKEN  (1<<2)         /* UART clock enabled */
+#define  UCR1_DOZE       (1<<1)         /* Doze */
+#define  UCR1_UARTEN     (1<<0)         /* UART enabled */
+#define  UCR2_ESCI              (1<<15) /* Escape seq interrupt enable */
+#define  UCR2_IRTS      (1<<14) /* Ignore RTS pin */
+#define  UCR2_CTSC      (1<<13) /* CTS pin control */
+#define  UCR2_CTS        (1<<12) /* Clear to send */
+#define  UCR2_ESCEN      (1<<11) /* Escape enable */
+#define  UCR2_PREN       (1<<8)  /* Parity enable */
+#define  UCR2_PROE       (1<<7)  /* Parity odd/even */
+#define  UCR2_STPB       (1<<6)         /* Stop */
+#define  UCR2_WS         (1<<5)         /* Word size */
+#define  UCR2_RTSEN      (1<<4)         /* Request to send interrupt enable */
+#define  UCR2_TXEN       (1<<2)         /* Transmitter enabled */
+#define  UCR2_RXEN       (1<<1)         /* Receiver enabled */
+#define  UCR2_SRST      (1<<0)  /* SW reset */
+#define  UCR3_DTREN     (1<<13) /* DTR interrupt enable */
+#define  UCR3_PARERREN   (1<<12) /* Parity enable */
+#define  UCR3_FRAERREN   (1<<11) /* Frame error interrupt enable */
+#define  UCR3_DSR        (1<<10) /* Data set ready */
+#define  UCR3_DCD        (1<<9)  /* Data carrier detect */
+#define  UCR3_RI         (1<<8)  /* Ring indicator */
+#define  UCR3_TIMEOUTEN  (1<<7)  /* Timeout interrupt enable */
+#define  UCR3_RXDSEN    (1<<6)  /* Receive status interrupt enable */
+#define  UCR3_AIRINTEN   (1<<5)  /* Async IR wake interrupt enable */
+#define  UCR3_AWAKEN    (1<<4)  /* Async wake interrupt enable */
+#define  UCR3_REF25     (1<<3)  /* Ref freq 25 MHz */
+#define  UCR3_REF30     (1<<2)  /* Ref Freq 30 MHz */
+#define  UCR3_INVT      (1<<1)  /* Inverted Infrared transmission */
+#define  UCR3_BPEN      (1<<0)  /* Preset registers enable */
+#define  UCR4_CTSTL_32   (32<<10) /* CTS trigger level (32 chars) */
+#define  UCR4_INVR      (1<<9)  /* Inverted infrared reception */
+#define  UCR4_ENIRI     (1<<8)  /* Serial infrared interrupt enable */
+#define  UCR4_WKEN      (1<<7)  /* Wake interrupt enable */
+#define  UCR4_REF16     (1<<6)  /* Ref freq 16 MHz */
+#define  UCR4_IRSC      (1<<5)  /* IR special case */
+#define  UCR4_TCEN      (1<<3)  /* Transmit complete interrupt enable */
+#define  UCR4_BKEN      (1<<2)  /* Break condition interrupt enable */
+#define  UCR4_OREN      (1<<1)  /* Receiver overrun interrupt enable */
+#define  UCR4_DREN      (1<<0)  /* Recv data ready interrupt enable */
+#define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
+#define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
+#define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
+#define  USR1_PARITYERR  (1<<15) /* Parity error interrupt flag */
+#define  USR1_RTSS      (1<<14) /* RTS pin status */
+#define  USR1_TRDY      (1<<13) /* Transmitter ready interrupt/dma flag */
+#define  USR1_RTSD      (1<<12) /* RTS delta */
+#define  USR1_ESCF      (1<<11) /* Escape seq interrupt flag */
+#define  USR1_FRAMERR    (1<<10) /* Frame error interrupt flag */
+#define  USR1_RRDY       (1<<9)         /* Receiver ready interrupt/dma flag */
+#define  USR1_TIMEOUT    (1<<7)         /* Receive timeout interrupt status */
+#define  USR1_RXDS      (1<<6)  /* Receiver idle interrupt flag */
+#define  USR1_AIRINT    (1<<5)  /* Async IR wake interrupt flag */
+#define  USR1_AWAKE     (1<<4)  /* Aysnc wake interrupt flag */
+#define  USR2_ADET      (1<<15) /* Auto baud rate detect complete */
+#define  USR2_TXFE      (1<<14) /* Transmit buffer FIFO empty */
+#define  USR2_DTRF      (1<<13) /* DTR edge interrupt flag */
+#define  USR2_IDLE      (1<<12) /* Idle condition */
+#define  USR2_IRINT     (1<<8)  /* Serial infrared interrupt flag */
+#define  USR2_WAKE      (1<<7)  /* Wake */
+#define  USR2_RTSF      (1<<4)  /* RTS edge interrupt flag */
+#define  USR2_TXDC      (1<<3)  /* Transmitter complete */
+#define  USR2_BRCD      (1<<2)  /* Break condition */
+#define  USR2_ORE        (1<<1)         /* Overrun error */
+#define  USR2_RDR        (1<<0)         /* Recv data ready */
+#define  UTS_FRCPERR    (1<<13) /* Force parity error */
+#define  UTS_LOOP        (1<<12) /* Loop tx and rx */
+#define  UTS_TXEMPTY    (1<<6)  /* TxFIFO empty */
+#define  UTS_RXEMPTY    (1<<5)  /* RxFIFO empty */
+#define  UTS_TXFULL     (1<<4)  /* TxFIFO full */
+#define  UTS_RXFULL     (1<<3)  /* RxFIFO full */
+#define  UTS_SOFTRST    (1<<0)  /* Software reset */
+
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_IMX_MAJOR       204
 #define MINOR_START            41
@@ -128,7 +244,10 @@ static void imx_timeout(unsigned long data)
 static void imx_stop_tx(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
+       unsigned long temp;
+
+       temp = readl(sport->port.membase + UCR1);
+       writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
 }
 
 /*
@@ -137,7 +256,10 @@ static void imx_stop_tx(struct uart_port *port)
 static void imx_stop_rx(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       UCR2((u32)sport->port.membase) &= ~UCR2_RXEN;
+       unsigned long temp;
+
+       temp = readl(sport->port.membase + UCR2);
+       writel(temp &~ UCR2_RXEN, sport->port.membase + UCR2);
 }
 
 /*
@@ -154,10 +276,10 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 {
        struct circ_buf *xmit = &sport->port.info->xmit;
 
-       while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) {
+       while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
                /* send xmit->buf[xmit->tail]
                 * out the port here */
-               URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
+               writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
                xmit->tail = (xmit->tail + 1) &
                         (UART_XMIT_SIZE - 1);
                sport->port.icount.tx++;
@@ -175,21 +297,24 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 static void imx_start_tx(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
 
-       UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
+       temp = readl(sport->port.membase + UCR1);
+       writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
 
-       imx_transmit_buffer(sport);
+       if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
+               imx_transmit_buffer(sport);
 }
 
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
 {
        struct imx_port *sport = (struct imx_port *)dev_id;
-       unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS;
+       unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
        unsigned long flags;
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
-       USR1((u32)sport->port.membase) = USR1_RTSD;
+       writel(USR1_RTSD, sport->port.membase + USR1);
        uart_handle_cts_change(&sport->port, !!val);
        wake_up_interruptible(&sport->port.info->delta_msr_wait);
 
@@ -207,7 +332,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id)
        if (sport->port.x_char)
        {
                /* Send next char */
-               URTX0((u32)sport->port.membase) = sport->port.x_char;
+               writel(sport->port.x_char, sport->port.membase + URTX0);
                goto out;
        }
 
@@ -231,17 +356,18 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
        struct imx_port *sport = dev_id;
        unsigned int rx,flg,ignored = 0;
        struct tty_struct *tty = sport->port.info->tty;
-       unsigned long flags;
+       unsigned long flags, temp;
 
-       rx = URXD0((u32)sport->port.membase);
+       rx = readl(sport->port.membase + URXD0);
        spin_lock_irqsave(&sport->port.lock,flags);
 
        do {
                flg = TTY_NORMAL;
                sport->port.icount.rx++;
 
-               if( USR2((u32)sport->port.membase) & USR2_BRCD ) {
-                       USR2((u32)sport->port.membase) |= USR2_BRCD;
+               temp = readl(sport->port.membase + USR2);
+               if( temp & USR2_BRCD ) {
+                       writel(temp | USR2_BRCD, sport->port.membase + USR2);
                        if(uart_handle_break(&sport->port))
                                goto ignore_char;
                }
@@ -257,7 +383,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
                tty_insert_flip_char(tty, rx, flg);
 
        ignore_char:
-               rx = URXD0((u32)sport->port.membase);
+               rx = readl(sport->port.membase + URXD0);
        } while(rx & URXD_CHARRDY);
 
 out:
@@ -301,7 +427,7 @@ static unsigned int imx_tx_empty(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
 
-       return USR2((u32)sport->port.membase) & USR2_TXDC ?  TIOCSER_TEMT : 0;
+       return (readl(sport->port.membase + USR2) & USR2_TXDC) ?  TIOCSER_TEMT : 0;
 }
 
 /*
@@ -312,10 +438,10 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
         struct imx_port *sport = (struct imx_port *)port;
         unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
 
-        if (USR1((u32)sport->port.membase) & USR1_RTSS)
+        if (readl(sport->port.membase + USR1) & USR1_RTSS)
                 tmp |= TIOCM_CTS;
 
-        if (UCR2((u32)sport->port.membase) & UCR2_CTS)
+        if (readl(sport->port.membase + UCR2) & UCR2_CTS)
                 tmp |= TIOCM_RTS;
 
         return tmp;
@@ -324,11 +450,14 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
 static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
         struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
+
+       temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
 
         if (mctrl & TIOCM_RTS)
-                UCR2((u32)sport->port.membase) |= UCR2_CTS;
-        else
-                UCR2((u32)sport->port.membase) &= ~UCR2_CTS;
+               temp |= UCR2_CTS;
+
+       writel(temp, sport->port.membase + UCR2);
 }
 
 /*
@@ -337,14 +466,16 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void imx_break_ctl(struct uart_port *port, int break_state)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       unsigned long flags;
+       unsigned long flags, temp;
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
+       temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK;
+
        if ( break_state != 0 )
-               UCR1((u32)sport->port.membase) |= UCR1_SNDBRK;
-       else
-               UCR1((u32)sport->port.membase) &= ~UCR1_SNDBRK;
+               temp |= UCR1_SNDBRK;
+
+       writel(temp, sport->port.membase + UCR1);
 
        spin_unlock_irqrestore(&sport->port.lock, flags);
 }
@@ -360,7 +491,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
        /* set receiver / transmitter trigger level.
         * RFDIV is set such way to satisfy requested uartclk value
         */
-       val = TXTL<<10 | RXTL;
+       val = TXTL << 10 | RXTL;
        ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk;
 
        if(!ufcr_rfdiv)
@@ -373,7 +504,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 
        val |= UFCR_RFDIV & (ufcr_rfdiv << 7);
 
-       UFCR((u32)sport->port.membase) = val;
+       writel(val, sport->port.membase + UFCR);
 
        return 0;
 }
@@ -382,14 +513,15 @@ static int imx_startup(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
        int retval;
-       unsigned long flags;
+       unsigned long flags, temp;
 
        imx_setup_ufcr(sport, 0);
 
        /* disable the DREN bit (Data Ready interrupt enable) before
         * requesting IRQs
         */
-       UCR4((u32)sport->port.membase) &= ~UCR4_DREN;
+       temp = readl(sport->port.membase + UCR4);
+       writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
        /*
         * Allocate the IRQ
@@ -411,12 +543,16 @@ static int imx_startup(struct uart_port *port)
        /*
         * Finally, clear and enable interrupts
         */
+       writel(USR1_RTSD, sport->port.membase + USR1);
+
+       temp = readl(sport->port.membase + UCR1);
+       temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       writel(temp, sport->port.membase + UCR1);
 
-       USR1((u32)sport->port.membase) = USR1_RTSD;
-       UCR1((u32)sport->port.membase) |=
-                        (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       temp = readl(sport->port.membase + UCR2);
+       temp |= (UCR2_RXEN | UCR2_TXEN);
+       writel(temp, sport->port.membase + UCR2);
 
-       UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN);
        /*
         * Enable modem status interrupts
         */
@@ -437,6 +573,7 @@ error_out1:
 static void imx_shutdown(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
 
        /*
         * Stop our timer.
@@ -454,8 +591,9 @@ static void imx_shutdown(struct uart_port *port)
         * Disable all interrupts, port and break condition.
         */
 
-       UCR1((u32)sport->port.membase) &=
-                        ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       temp = readl(sport->port.membase + UCR1);
+       temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       writel(temp, sport->port.membase + UCR1);
 }
 
 static void
@@ -548,18 +686,18 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        /*
         * disable interrupts and drain transmitter
         */
-       old_ucr1 = UCR1((u32)sport->port.membase);
-       UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
+       old_ucr1 = readl(sport->port.membase + UCR1);
+       writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
+                       sport->port.membase + UCR1);
 
-       while ( !(USR2((u32)sport->port.membase) & USR2_TXDC))
+       while ( !(readl(sport->port.membase + USR2) & USR2_TXDC))
                barrier();
 
        /* then, disable everything */
-       old_txrxen = UCR2((u32)sport->port.membase) & ( UCR2_TXEN | UCR2_RXEN );
-       UCR2((u32)sport->port.membase) &= ~( UCR2_TXEN | UCR2_RXEN);
-
-       /* set the parity, stop bits and data size */
-       UCR2((u32)sport->port.membase) = ucr2;
+       old_txrxen = readl(sport->port.membase + UCR2);
+       writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN),
+                       sport->port.membase + UCR2);
+       old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
 
        /* set the baud rate. We assume uartclk = 16 MHz
         *
@@ -567,11 +705,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
         * --------- = --------
         *  uartclk    UBMR - 1
         */
-       UBIR((u32)sport->port.membase) = (baud / 100) - 1;
-       UBMR((u32)sport->port.membase) = 10000 - 1;
+       writel((baud / 100) - 1, sport->port.membase + UBIR);
+       writel(10000 - 1, sport->port.membase + UBMR);
+
+       writel(old_ucr1, sport->port.membase + UCR1);
 
-       UCR1((u32)sport->port.membase) = old_ucr1;
-       UCR2((u32)sport->port.membase) |= old_txrxen;
+       /* set the parity, stop bits and data size */
+       writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
 
        if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
                imx_enable_ms(&sport->port);
@@ -730,9 +870,11 @@ static void __init imx_init_ports(void)
 static void imx_console_putchar(struct uart_port *port, int ch)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
+
+       while (readl(sport->port.membase + UTS) & UTS_TXFULL)
                barrier();
-       URTX0((u32)sport->port.membase) = ch;
+
+       writel(ch, sport->port.membase + URTX0);
 }
 
 /*
@@ -747,13 +889,14 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        /*
         *      First, save UCR1/2 and then disable interrupts
         */
-       old_ucr1 = UCR1((u32)sport->port.membase);
-       old_ucr2 = UCR2((u32)sport->port.membase);
+       old_ucr1 = readl(sport->port.membase + UCR1);
+       old_ucr2 = readl(sport->port.membase + UCR2);
 
-       UCR1((u32)sport->port.membase) =
-                          (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN)
-                          & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
-       UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
+       writel((old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) &
+               ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
+               sport->port.membase + UCR1);
+
+       writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
 
        uart_console_write(&sport->port, s, count, imx_console_putchar);
 
@@ -761,10 +904,10 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
         *      Finally, wait for transmitter to become empty
         *      and restore UCR1/2
         */
-       while (!(USR2((u32)sport->port.membase) & USR2_TXDC));
+       while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
 
-       UCR1((u32)sport->port.membase) = old_ucr1;
-       UCR2((u32)sport->port.membase) = old_ucr2;
+       writel(old_ucr1, sport->port.membase + UCR1);
+       writel(old_ucr2, sport->port.membase + UCR2);
 }
 
 /*
@@ -776,13 +919,13 @@ imx_console_get_options(struct imx_port *sport, int *baud,
                           int *parity, int *bits)
 {
 
-       if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) {
+       if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) {
                /* ok, the port was enabled */
                unsigned int ucr2, ubir,ubmr, uartclk;
                unsigned int baud_raw;
                unsigned int ucfr_rfdiv;
 
-               ucr2 = UCR2((u32)sport->port.membase);
+               ucr2 = readl(sport->port.membase + UCR2);
 
                *parity = 'n';
                if (ucr2 & UCR2_PREN) {
@@ -797,11 +940,10 @@ imx_console_get_options(struct imx_port *sport, int *baud,
                else
                        *bits = 7;
 
-               ubir = UBIR((u32)sport->port.membase) & 0xffff;
-               ubmr = UBMR((u32)sport->port.membase) & 0xffff;
-
+               ubir = readl(sport->port.membase + UBIR) & 0xffff;
+               ubmr = readl(sport->port.membase + UBMR) & 0xffff;
 
-               ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7;
+               ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7;
                if (ucfr_rfdiv == 6)
                        ucfr_rfdiv = 7;
                else
index d403aaa..e9c6cb3 100644 (file)
@@ -717,7 +717,7 @@ struct uart_ops serial_pxa_pops = {
 static struct uart_pxa_port serial_pxa_ports[] = {
      { /* FFUART */
        .name   = "FFUART",
-       .cken   = CKEN6_FFUART,
+       .cken   = CKEN_FFUART,
        .port   = {
                .type           = PORT_PXA,
                .iotype         = UPIO_MEM,
@@ -731,7 +731,7 @@ static struct uart_pxa_port serial_pxa_ports[] = {
        },
   }, { /* BTUART */
        .name   = "BTUART",
-       .cken   = CKEN7_BTUART,
+       .cken   = CKEN_BTUART,
        .port   = {
                .type           = PORT_PXA,
                .iotype         = UPIO_MEM,
@@ -745,7 +745,7 @@ static struct uart_pxa_port serial_pxa_ports[] = {
        },
   }, { /* STUART */
        .name   = "STUART",
-       .cken   = CKEN5_STUART,
+       .cken   = CKEN_STUART,
        .port   = {
                .type           = PORT_PXA,
                .iotype         = UPIO_MEM,
@@ -759,7 +759,7 @@ static struct uart_pxa_port serial_pxa_ports[] = {
        },
   }, {  /* HWUART */
        .name   = "HWUART",
-       .cken   = CKEN4_HWUART,
+       .cken   = CKEN_HWUART,
        .port = {
                .type           = PORT_PXA,
                .iotype         = UPIO_MEM,
index 2c043a1..84392e8 100644 (file)
@@ -1483,7 +1483,7 @@ static void udc_disable(struct pxa2xx_udc *dev)
 
 #ifdef CONFIG_ARCH_PXA
         /* Disable clock for USB device */
-       pxa_set_cken(CKEN11_USB, 0);
+       pxa_set_cken(CKEN_USB, 0);
 #endif
 
        ep0_idle (dev);
@@ -1529,7 +1529,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
 
 #ifdef CONFIG_ARCH_PXA
         /* Enable clock for USB device */
-       pxa_set_cken(CKEN11_USB, 1);
+       pxa_set_cken(CKEN_USB, 1);
        udelay(5);
 #endif
 
index f1563dc..23d2fe5 100644 (file)
@@ -80,7 +80,7 @@ static int pxa27x_start_hc(struct device *dev)
 
        inf = dev->platform_data;
 
-       pxa_set_cken(CKEN10_USBHOST, 1);
+       pxa_set_cken(CKEN_USBHOST, 1);
 
        UHCHR |= UHCHR_FHR;
        udelay(11);
@@ -123,7 +123,7 @@ static void pxa27x_stop_hc(struct device *dev)
        UHCCOMS |= 1;
        udelay(10);
 
-       pxa_set_cken(CKEN10_USBHOST, 0);
+       pxa_set_cken(CKEN_USBHOST, 0);
 }
 
 
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 05890dc..2d89d0e 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 91a2078..3e67c34 100644 (file)
@@ -371,7 +371,8 @@ static const char *vgacon_startup(void)
        }
 
        /* VGA16 modes are not handled by VGACON */
-       if ((ORIG_VIDEO_MODE == 0x0D) ||        /* 320x200/4 */
+       if ((ORIG_VIDEO_MODE == 0x00) ||        /* SCREEN_INFO not initialized */
+           (ORIG_VIDEO_MODE == 0x0D) ||        /* 320x200/4 */
            (ORIG_VIDEO_MODE == 0x0E) ||        /* 640x200/4 */
            (ORIG_VIDEO_MODE == 0x10) ||        /* 640x350/4 */
            (ORIG_VIDEO_MODE == 0x12) ||        /* 640x480/4 */
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 b4947c8..0b195f3 100644 (file)
@@ -803,7 +803,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
        pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
 
        /* enable LCD controller clock */
-       pxa_set_cken(CKEN16_LCD, 1);
+       pxa_set_cken(CKEN_LCD, 1);
 
        /* Sequence from 11.7.10 */
        LCCR3 = fbi->reg_lccr3;
@@ -840,7 +840,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
        remove_wait_queue(&fbi->ctrlr_wait, &wait);
 
        /* disable LCD controller clock */
-       pxa_set_cken(CKEN16_LCD, 0);
+       pxa_set_cken(CKEN_LCD, 0);
 }
 
 /*
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
  */
@@ -114,31 +129,6 @@ void __exit afs_fs_exit(void)
        _leave("");
 }
 
-/*
- * 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
@@ -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 5d1f487..a9b6bc5 100644 (file)
@@ -1,4 +1,16 @@
-Verison 1.48
+Version 1.49
+------------
+IPv6 support.  Enable ipv6 addresses to be passed on mount (put the ipv6
+address after the "ip=" mount option, at least until mount.cifs is fixed to
+handle DNS host to ipv6 name translation).  Accept override of uid or gid
+on mount even when Unix Extensions are negotiated (it used to be ignored
+when Unix Extensions were ignored).  This allows users to override the
+default uid and gid for files when they are certain that the uids or
+gids on the server do not match those of the client.  Make "sec=none"
+mount override username (so that null user connection is attempted)
+to match what documentation said.
+
+Version 1.48
 ------------
 Fix mtime bouncing around from local idea of last write times to remote time.
 Fix hang (in i_size_read) when simultaneous size update of same remote file
@@ -9,7 +21,13 @@ from read-only back to read-write, reflect this change in default file mode
 (we had been leaving a file's mode read-only until the inode were reloaded).
 Allow setting of attribute back to ATTR_NORMAL (removing readonly dos attribute
 when archive dos attribute not set and we are changing mode back to writeable
-on server which does not support the Unix Extensions).
+on server which does not support the Unix Extensions).  Remove read only dos
+attribute on chmod when adding any write permission (ie on any of
+user/group/other (not all of user/group/other ie  0222) when
+mounted to windows.  Add support for POSIX MkDir (slight performance
+enhancement and eliminates the network race between the mkdir and set 
+path info of the mode).
+
 
 Version 1.47
 ------------
index 080c5eb..4d01697 100644 (file)
@@ -257,13 +257,19 @@ A partial list of the supported mount options follows:
                mount.  
   domain       Set the SMB/CIFS workgroup name prepended to the
                username during CIFS session establishment
-  uid          If CIFS Unix extensions are not supported by the server
-               this overrides the default uid for inodes. For mounts to
-               servers which do support the CIFS Unix extensions, such
-               as a properly configured Samba server, the server provides
-               the uid, gid and mode.  For servers which do not support
-               the Unix extensions, the default uid (and gid) returned on
-               lookup of existing files is the uid (gid) of the person
+  uid          Set the default uid for inodes. For mounts to servers
+               which do support the CIFS Unix extensions, such as a
+               properly configured Samba server, the server provides
+               the uid, gid and mode so this parameter should  not be
+               specified unless the server and clients uid and gid
+               numbering differ.  If the server and client are in the
+               same domain (e.g. running winbind or nss_ldap) and
+               the server supports the Unix Extensions then the uid
+               and gid can be retrieved from the server (and uid
+               and gid would not have to be specifed on the mount. 
+               For servers which do not support the CIFS Unix
+               extensions, the default uid (and gid) returned on lookup
+               of existing files will be the uid (gid) of the person
                who executed the mount (root, except when mount.cifs
                is configured setuid for user mounts) unless the "uid=" 
                (gid) mount option is specified.  For the uid (gid) of newly
@@ -281,8 +287,7 @@ A partial list of the supported mount options follows:
                the client.  Note that the mount.cifs helper must be
                at version 1.10 or higher to support specifying the uid
                (or gid) in non-numberic form.
-  gid          If CIFS Unix extensions are not supported by the server
-               this overrides the default gid for inodes.
+  gid          Set the default gid for inodes (similar to above).
   file_mode     If CIFS Unix extensions are not supported by the server
                this overrides the default mode for file inodes.
   dir_mode      If CIFS Unix extensions are not supported by the server 
@@ -467,7 +472,7 @@ including:
        -V      print mount.cifs version
        -?      display simple usage information
 
-With recent 2.6 kernel versions of modutils, the version of the cifs kernel
+With most 2.6 kernel versions of modutils, the version of the cifs kernel
 module can be displayed via modinfo.
 
 Misc /proc/fs/cifs Flags and Debug Info
@@ -516,8 +521,22 @@ SecurityFlags              Flags which control security negotiation and
                        must use plaintext passwords                    0x20020
                        (reserved for future packet encryption)         0x00040
 
-cifsFYI                        If set to one, additional debug information is
-                       logged to the system error log. (default 0)
+cifsFYI                        If set to non-zero value, additional debug information
+                       will be logged to the system error log.  This field
+                       contains three flags controlling different classes of
+                       debugging entries.  The maximum value it can be set
+                       to is 7 which enables all debugging points (default 0).
+                       Some debugging statements are not compiled into the
+                       cifs kernel unless CONFIG_CIFS_DEBUG2 is enabled in the
+                       kernel configuration. cifsFYI may be set to one or
+                       nore of the following flags (7 sets them all):
+
+                       log cifs informational messages                 0x01
+                       log return codes from cifs entry points         0x02
+                       log slow responses (ie which take longer than 1 second)
+                         CONFIG_CIFS_STATS2 must be enabled in .config 0x04
+                               
+                               
 traceSMB               If set to one, debug information is logged to the
                        system error log with the start of smb requests
                        and responses (default 0)
index d7b9c27..78b620e 100644 (file)
@@ -1,4 +1,4 @@
-Version 1.39 November 30, 2005
+Version 1.49 April 26, 2007
 
 A Partial List of Missing Features
 ==================================
@@ -18,7 +18,7 @@ better)
 
 d) Kerberos/SPNEGO session setup support - (started)
 
-e) NTLMv2 authentication (mostly implemented - double check
+e) More testing of NTLMv2 authentication (mostly implemented - double check
 that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
 fs/cifs/connect.c)
 
@@ -27,55 +27,44 @@ used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
 and raw NTLMSSP already. This is important when enabling
 extended security and mounting to Windows 2003 Servers
 
-f) Directory entry caching relies on a 1 second timer, rather than 
+g) Directory entry caching relies on a 1 second timer, rather than 
 using FindNotify or equivalent.  - (started)
 
-g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
-style byte range lock differences.  Save byte range locks so
-reconnect can replay them.  
-
-h) Support unlock all (unlock 0,MAX_OFFSET)
-by unlocking all known byte range locks that we locked on the file.
-
-i) quota support (needs minor kernel change since quota calls
+h) quota support (needs minor kernel change since quota calls
 to make it to network filesystems or deviceless filesystems)
 
-j) investigate sync behavior (including syncpage) and check  
+i) investigate sync behavior (including syncpage) and check  
 for proper behavior of intr/nointr
 
-k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
 extra copy in/out of the socket buffers in some cases.
 
-l) finish support for IPv6.  This is mostly complete but
-needs a simple conversion of ipv6 to sin6_addr from the
-address in string representation.
-
-m) Better optimize open (and pathbased setfilesize) to reduce the
+k) Better optimize open (and pathbased setfilesize) to reduce the
 oplock breaks coming from windows srv.  Piggyback identical file
 opens on top of each other by incrementing reference count rather
 than resending (helps reduce server resource utilization and avoid
 spurious oplock breaks).
 
-o) Improve performance of readpages by sending more than one read
+l) Improve performance of readpages by sending more than one read
 at a time when 8 pages or more are requested. In conjuntion
 add support for async_cifs_readpages.
 
-p) Add support for storing symlink info to Windows servers 
+m) Add support for storing symlink info to Windows servers 
 in the Extended Attribute format their SFU clients would recognize.
 
-q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
+n) Finish fcntl D_NOTIFY support so kde and gnome file list windows
 will autorefresh (partially complete by Asser). Needs minor kernel
 vfs change to support removing D_NOTIFY on a file.   
 
-r) Add GUI tool to configure /proc/fs/cifs settings and for display of
+o) Add GUI tool to configure /proc/fs/cifs settings and for display of
 the CIFS statistics (started)
 
-s) implement support for security and trusted categories of xattrs
+p) implement support for security and trusted categories of xattrs
 (requires minor protocol extension) to enable better support for SELINUX
 
-t) Implement O_DIRECT flag on open (already supported on mount)
+q) Implement O_DIRECT flag on open (already supported on mount)
 
-u) Create UID mapping facility so server UIDs can be mapped on a per
+r) Create UID mapping facility so server UIDs can be mapped on a per
 mount or a per server basis to client UIDs or nobody if no mapping
 exists.  This is helpful when Unix extensions are negotiated to
 allow better permission checking when UIDs differ on the server
@@ -83,19 +72,26 @@ and client.  Add new protocol request to the CIFS protocol
 standard for asking the server for the corresponding name of a
 particular uid.
 
-v) Add support for CIFS Unix and also the newer POSIX extensions to the
+s) Add support for CIFS Unix and also the newer POSIX extensions to the
 server side for Samba 4.
 
-w) Finish up the dos time conversion routines needed to return old server
-time to the client (default time, of now or time 0 is used now for these 
-very old servers)
-
-x) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) 
+t) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) 
 need to add ability to set time to server (utimes command)
 
-y) Finish testing of Windows 9x/Windows ME server support (started).
+u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
+
+v) mount check for unmatched uids
+
+w) Add mount option for Linux extension disable per mount, and partial
+disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?)
 
-KNOWN BUGS (updated February 26, 2007)
+x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of 
+processes can proceed better in parallel (on the server)
+
+y) Fix Samba 3 to handle reads/writes over 127K (and remove the cifs mount
+restriction of wsize max being 127K) 
+
+KNOWN BUGS (updated April 24, 2007)
 ====================================
 See http://bugzilla.samba.org - search on product "CifsVFS" for
 current bug list.
@@ -127,10 +123,3 @@ negotiated size) and send larger write sizes to modern servers.
 4) More exhaustively test against less common servers.  More testing
 against Windows 9x, Windows ME servers.
 
-DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
-
-mount check for unmatched uids - and uid override
-
-Add mount option for Linux extension disable per mount, and partial disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?) 
-
-Free threads at umount --force that are stuck on the sesSem
index fd1e52e..4cc2012 100644 (file)
 #define CIFS_MOUNT_SET_UID      2 /* set current->euid in create etc. */
 #define CIFS_MOUNT_SERVER_INUM  4 /* inode numbers from uniqueid from server */
 #define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
-#define CIFS_MOUNT_NO_XATTR  0x10 /* if set - disable xattr support */
-#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
-#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
-#define CIFS_MOUNT_UNX_EMUL    0x80 /* Network compat with SFUnix emulation */
-#define CIFS_MOUNT_NO_BRL      0x100 /* No sending byte range locks to srv */
-#define CIFS_MOUNT_CIFS_ACL    0x200 /* send ACL requests to non-POSIX srv */
+#define CIFS_MOUNT_NO_XATTR     0x10  /* if set - disable xattr support       */
+#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames   */
+#define CIFS_MOUNT_POSIX_PATHS  0x40  /* Negotiate posix pathnames if possible*/
+#define CIFS_MOUNT_UNX_EMUL     0x80  /* Network compat with SFUnix emulation */
+#define CIFS_MOUNT_NO_BRL       0x100 /* No sending byte range locks to srv   */
+#define CIFS_MOUNT_CIFS_ACL     0x200 /* send ACL requests to non-POSIX srv   */
+#define CIFS_MOUNT_OVERR_UID    0x400 /* override uid returned from server    */
+#define CIFS_MOUNT_OVERR_GID    0x800 /* override gid returned from server    */
 
 struct cifs_sb_info {
        struct cifsTconInfo *tcon;      /* primary mount */
index d2a8b29..793c4b9 100644 (file)
@@ -74,8 +74,8 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
                charlen = codepage->char2uni(from, len, &wchar_to[i]);
                if (charlen < 1) {
                        cERROR(1,
-                              ("cifs_strtoUCS: char2uni returned %d",
-                               charlen));
+                              ("strtoUCS: char2uni of %d returned %d",
+                               (int)*from, charlen));
                        /* A question mark */
                        to[i] = cpu_to_le16(0x003f);
                        charlen = 1;
index faba4d6..5036dae 100644 (file)
@@ -100,7 +100,7 @@ cifs_read_super(struct super_block *sb, void *data,
        sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
        sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
        cifs_sb = CIFS_SB(sb);
-       if(cifs_sb == NULL)
+       if (cifs_sb == NULL)
                return -ENOMEM;
 
        rc = cifs_mount(sb, cifs_sb, data, devname);
@@ -115,10 +115,10 @@ cifs_read_super(struct super_block *sb, void *data,
        sb->s_magic = CIFS_MAGIC_NUMBER;
        sb->s_op = &cifs_super_ops;
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-       if(experimEnabled != 0)
+       if (experimEnabled != 0)
                sb->s_export_op = &cifs_export_ops;
 #endif /* EXPERIMENTAL */      
-/*     if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+/*     if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
            sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
 #ifdef CONFIG_CIFS_QUOTA
        sb->s_qcop = &cifs_quotactl_ops;
@@ -147,8 +147,8 @@ out_no_root:
                iput(inode);
 
 out_mount_failed:
-       if(cifs_sb) {
-               if(cifs_sb->local_nls)
+       if (cifs_sb) {
+               if (cifs_sb->local_nls)
                        unload_nls(cifs_sb->local_nls); 
                kfree(cifs_sb);
        }
@@ -163,7 +163,7 @@ cifs_put_super(struct super_block *sb)
 
        cFYI(1, ("In cifs_put_super"));
        cifs_sb = CIFS_SB(sb);
-       if(cifs_sb == NULL) {
+       if (cifs_sb == NULL) {
                cFYI(1,("Empty cifs superblock info passed to unmount"));
                return;
        }
@@ -208,14 +208,14 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
     /* Only need to call the old QFSInfo if failed
     on newer one */
-    if(rc)
-       if(pTcon->ses->capabilities & CAP_NT_SMBS)
+    if (rc)
+       if (pTcon->ses->capabilities & CAP_NT_SMBS)
                rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
 
        /* Some old Windows servers also do not support level 103, retry with
           older level one if old server failed the previous call or we
           bypassed it because we detected that this was an older LANMAN sess */
-       if(rc)
+       if (rc)
                rc = SMBOldQFSInfo(xid, pTcon, buf);
        /*     
           int f_type;
@@ -301,11 +301,19 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
                                if (cifs_sb->tcon->ses->userName)
                                        seq_printf(s, ",username=%s",
                                           cifs_sb->tcon->ses->userName);
-                               if(cifs_sb->tcon->ses->domainName)
+                               if (cifs_sb->tcon->ses->domainName)
                                        seq_printf(s, ",domain=%s",
                                           cifs_sb->tcon->ses->domainName);
                        }
                }
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+                       seq_printf(s, ",posixpaths");
+               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
+                  !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
+                       seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
+                  !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
+                       seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
                seq_printf(s, ",rsize=%d",cifs_sb->rsize);
                seq_printf(s, ",wsize=%d",cifs_sb->wsize);
        }
@@ -321,14 +329,14 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifsTconInfo *pTcon;
        
-       if(cifs_sb)
+       if (cifs_sb)
                pTcon = cifs_sb->tcon;
        else
                return -EIO;
 
 
        xid = GetXid();
-       if(pTcon) {
+       if (pTcon) {
                cFYI(1,("set type: 0x%x id: %d",quota_type,qid));               
        } else {
                return -EIO;
@@ -346,13 +354,13 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifsTconInfo *pTcon;
 
-       if(cifs_sb)
+       if (cifs_sb)
                pTcon = cifs_sb->tcon;
        else
                return -EIO;
 
        xid = GetXid();
-       if(pTcon) {
+       if (pTcon) {
                 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
        } else {
                rc = -EIO;
@@ -369,13 +377,13 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifsTconInfo *pTcon;
 
-       if(cifs_sb)
+       if (cifs_sb)
                pTcon = cifs_sb->tcon;
        else
                return -EIO;
 
        xid = GetXid();
-       if(pTcon) {
+       if (pTcon) {
                 cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
        } else {
                rc = -EIO;
@@ -392,13 +400,13 @@ int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifsTconInfo *pTcon;
 
-       if(cifs_sb) {
+       if (cifs_sb) {
                pTcon = cifs_sb->tcon;
        } else {
                return -EIO;
        }
        xid = GetXid();
-       if(pTcon) {
+       if (pTcon) {
                cFYI(1,("pqstats %p",qstats));          
        } else {
                rc = -EIO;
@@ -424,11 +432,11 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
        if (!(flags & MNT_FORCE))
                return;
        cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
-       if(cifs_sb == NULL)
+       if (cifs_sb == NULL)
                return;
 
        tcon = cifs_sb->tcon;
-       if(tcon == NULL)
+       if (tcon == NULL)
                return;
        down(&tcon->tconSem);
        if (atomic_read(&tcon->useCount) == 1)
@@ -437,7 +445,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 
        /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
        /* cancel_notify_requests(tcon); */
-       if(tcon->ses && tcon->ses->server)
+       if (tcon->ses && tcon->ses->server)
        {
                cFYI(1,("wake up tasks now - umount begin not complete"));
                wake_up_all(&tcon->ses->server->request_q);
@@ -529,8 +537,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
                /* some applications poll for the file length in this strange
                   way so we must seek to end on non-oplocked files by
                   setting the revalidate time to zero */
-               if(file->f_path.dentry->d_inode)                
-                       CIFS_I(file->f_path.dentry->d_inode)->time = 0;
+               CIFS_I(file->f_path.dentry->d_inode)->time = 0;
 
                retval = cifs_revalidate(file->f_path.dentry);
                if (retval < 0)
@@ -724,7 +731,7 @@ cifs_destroy_inodecache(void)
 static int
 cifs_init_request_bufs(void)
 {
-       if(CIFSMaxBufSize < 8192) {
+       if (CIFSMaxBufSize < 8192) {
        /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
        Unicode path name has to fit in any SMB/CIFS path based frames */
                CIFSMaxBufSize = 8192;
@@ -741,7 +748,7 @@ cifs_init_request_bufs(void)
        if (cifs_req_cachep == NULL)
                return -ENOMEM;
 
-       if(cifs_min_rcv < 1)
+       if (cifs_min_rcv < 1)
                cifs_min_rcv = 1;
        else if (cifs_min_rcv > 64) {
                cifs_min_rcv = 64;
@@ -751,7 +758,7 @@ cifs_init_request_bufs(void)
        cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
                                                  cifs_req_cachep);
 
-       if(cifs_req_poolp == NULL) {
+       if (cifs_req_poolp == NULL) {
                kmem_cache_destroy(cifs_req_cachep);
                return -ENOMEM;
        }
@@ -772,7 +779,7 @@ cifs_init_request_bufs(void)
                return -ENOMEM;              
        }
 
-       if(cifs_min_small < 2)
+       if (cifs_min_small < 2)
                cifs_min_small = 2;
        else if (cifs_min_small > 256) {
                cifs_min_small = 256;
@@ -782,7 +789,7 @@ cifs_init_request_bufs(void)
        cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
                                                     cifs_sm_req_cachep);
 
-       if(cifs_sm_req_poolp == NULL) {
+       if (cifs_sm_req_poolp == NULL) {
                mempool_destroy(cifs_req_poolp);
                kmem_cache_destroy(cifs_req_cachep);
                kmem_cache_destroy(cifs_sm_req_cachep);
@@ -812,7 +819,7 @@ cifs_init_mids(void)
 
        /* 3 is a reasonable minimum number of simultaneous operations */
        cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
-       if(cifs_mid_poolp == NULL) {
+       if (cifs_mid_poolp == NULL) {
                kmem_cache_destroy(cifs_mid_cachep);
                return -ENOMEM;
        }
@@ -850,14 +857,14 @@ static int cifs_oplock_thread(void * dummyarg)
                        continue;
                
                spin_lock(&GlobalMid_Lock);
-               if(list_empty(&GlobalOplock_Q)) {
+               if (list_empty(&GlobalOplock_Q)) {
                        spin_unlock(&GlobalMid_Lock);
                        set_current_state(TASK_INTERRUPTIBLE);
                        schedule_timeout(39*HZ);
                } else {
                        oplock_item = list_entry(GlobalOplock_Q.next, 
                                struct oplock_q_entry, qhead);
-                       if(oplock_item) {
+                       if (oplock_item) {
                                cFYI(1,("found oplock item to write out")); 
                                pTcon = oplock_item->tcon;
                                inode = oplock_item->pinode;
@@ -871,7 +878,7 @@ static int cifs_oplock_thread(void * dummyarg)
                                /* mutex_lock(&inode->i_mutex);*/
                                if (S_ISREG(inode->i_mode)) {
                                        rc = filemap_fdatawrite(inode->i_mapping);
-                                       if(CIFS_I(inode)->clientCanCacheRead == 0) {
+                                       if (CIFS_I(inode)->clientCanCacheRead == 0) {
                                                filemap_fdatawait(inode->i_mapping);
                                                invalidate_remote_inode(inode);
                                        }
@@ -888,7 +895,7 @@ static int cifs_oplock_thread(void * dummyarg)
                                not bother sending an oplock release if session 
                                to server still is disconnected since oplock 
                                already released by the server in that case */
-                               if(pTcon->tidStatus != CifsNeedReconnect) {
+                               if (pTcon->tidStatus != CifsNeedReconnect) {
                                    rc = CIFSSMBLock(0, pTcon, netfid,
                                            0 /* len */ , 0 /* offset */, 0, 
                                            0, LOCKING_ANDX_OPLOCK_RELEASE,
@@ -922,7 +929,7 @@ static int cifs_dnotify_thread(void * dummyarg)
                list_for_each(tmp, &GlobalSMBSessionList) {
                        ses = list_entry(tmp, struct cifsSesInfo, 
                                cifsSessionList);
-                       if(ses && ses->server && 
+                       if (ses && ses->server && 
                             atomic_read(&ses->server->inFlight))
                                wake_up_all(&ses->server->response_q);
                }
@@ -971,10 +978,10 @@ init_cifs(void)
        rwlock_init(&GlobalSMBSeslock);
        spin_lock_init(&GlobalMid_Lock);
 
-       if(cifs_max_pending < 2) {
+       if (cifs_max_pending < 2) {
                cifs_max_pending = 2;
                cFYI(1,("cifs_max_pending set to min of 2"));
-       } else if(cifs_max_pending > 256) {
+       } else if (cifs_max_pending > 256) {
                cifs_max_pending = 256;
                cFYI(1,("cifs_max_pending set to max of 256"));
        }
index 2c2c384..c235d32 100644 (file)
@@ -100,5 +100,5 @@ extern ssize_t      cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
                       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.48"
+#define CIFS_VERSION   "1.49"
 #endif                         /* _CIFSFS_H */
index e4de8eb..23655de 100644 (file)
@@ -311,7 +311,7 @@ struct cifsFileInfo {
        /* lock scope id (0 if none) */
        struct file * pfile; /* needed for writepage */
        struct inode * pInode; /* needed for oplock break */
-       struct semaphore lock_sem;
+       struct mutex lock_mutex;
        struct list_head llist; /* list of byte range locks we have. */
        unsigned closePend:1;   /* file is marked to close */
        unsigned invalidHandle:1;  /* file closed via session abend */
index 4d8948e..d619ca7 100644 (file)
@@ -1388,7 +1388,7 @@ struct smb_t2_rsp {
 #define SMB_SET_POSIX_LOCK              0x208
 #define SMB_POSIX_OPEN                  0x209
 #define SMB_POSIX_UNLINK                0x20a
-#define SMB_SET_FILE_UNIX_INFO2
+#define SMB_SET_FILE_UNIX_INFO2         0x20b
 #define SMB_SET_FILE_BASIC_INFO2        0x3ec
 #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
 #define SMB_FILE_ALL_INFO2              0x3fa
@@ -2109,22 +2109,40 @@ struct cifs_posix_acl { /* access conrol list  (ACL) */
 
 /* end of POSIX ACL definitions */
 
+/* POSIX Open Flags */
+#define SMB_O_RDONLY    0x1
+#define SMB_O_WRONLY   0x2
+#define SMB_O_RDWR     0x4
+#define SMB_O_CREAT    0x10
+#define SMB_O_EXCL     0x20
+#define SMB_O_TRUNC    0x40
+#define SMB_O_APPEND   0x80
+#define SMB_O_SYNC     0x100
+#define SMB_O_DIRECTORY 0x200
+#define SMB_O_NOFOLLOW         0x400
+#define SMB_O_DIRECT   0x800
+
 typedef struct {
-       __u32 OpenFlags; /* same as NT CreateX */
-       __u32 PosixOpenFlags;
-       __u32 Mode;
-       __u16 Level; /* reply level requested (see QPathInfo levels) */
-       __u16 Pad;  /* reserved - MBZ */
+       __le32 OpenFlags; /* same as NT CreateX */
+       __le32 PosixOpenFlags;
+       __le64 Permissions;
+       __le16 Level; /* reply level requested (see QPathInfo levels) */
 } __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
 
 typedef struct {
-       /* reply varies based on requested level */
+       __le16 OplockFlags;
+       __u16 Fid;
+       __le32 CreateAction;
+       __le16 ReturnedLevel;
+       __le16 Pad;
+       /* struct following varies based on requested level */
 } __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
 
 
 struct file_internal_info {
        __u64  UniqueId; /* inode number */
 } __attribute__((packed));      /* level 0x3ee */
+
 struct file_mode_info {
        __le32  Mode;
 } __attribute__((packed));      /* level 0x3f8 */
index 32eb1ac..5d163e2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsproto.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002,2006
+ *   Copyright (c) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -244,6 +244,11 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
                        const int access_flags, const int omode,
                        __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
                        const struct nls_table *nls_codepage, int remap);
+extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, 
+                       u32 posix_flags, __u64 mode, __u16 * netfid,
+                       FILE_UNIX_BASIC_INFO *pRetData,
+                       __u32 *pOplock, const char *name,
+                       const struct nls_table *nls_codepage, int remap);                       
 extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
                        const int smb_file_id);
 
index 48fc0c2..14de58f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifssmb.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2006
+ *   Copyright (C) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Contains the routines for constructing the SMB PDUs themselves
@@ -24,8 +24,8 @@
  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
  /* These are mostly routines that operate on a pathname, or on a tree id     */
  /* (mounted volume), but there are eight handle based routines which must be */
- /* treated slightly different for reconnection purposes since we never want  */
- /* to reuse a stale file handle and the caller knows the file handle */
+ /* treated slightly differently for reconnection purposes since we never     */
+ /* want to reuse a stale file handle and only the caller knows the file info */
 
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -913,6 +913,130 @@ MkDirRetry:
        return rc;
 }
 
+int
+CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
+               __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
+               __u32 *pOplock, const char *name, 
+               const struct nls_table *nls_codepage, int remap)
+{
+       TRANSACTION2_SPI_REQ *pSMB = NULL;
+       TRANSACTION2_SPI_RSP *pSMBr = NULL;
+       int name_len;
+       int rc = 0;
+       int bytes_returned = 0;
+       char *data_offset;
+       __u16 params, param_offset, offset, byte_count, count;
+       OPEN_PSX_REQ * pdata;
+       OPEN_PSX_RSP * psx_rsp;
+
+       cFYI(1, ("In POSIX Create"));
+PsxCreat:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, name,
+                                    PATH_MAX, nls_codepage, remap);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+       } else {        /* BB improve the check for buffer overruns BB */
+               name_len = strnlen(name, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, name, name_len);
+       }
+
+       params = 6 + name_len;
+       count = sizeof(OPEN_PSX_REQ);
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+       offset = param_offset + params;
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+       pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
+       pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
+       pdata->Permissions = cpu_to_le64(mode);
+       pdata->PosixOpenFlags = cpu_to_le32(posix_flags); 
+       pdata->OpenFlags =  cpu_to_le32(*pOplock);
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+       byte_count = 3 /* pad */  + params + count;
+
+       pSMB->DataCount = cpu_to_le16(count);
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->TotalDataCount = pSMB->DataCount;
+       pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count; 
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Posix create returned %d", rc));
+               goto psx_create_err;
+       }
+
+       cFYI(1,("copying inode info"));
+       rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+       if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
+               rc = -EIO;      /* bad smb */
+               goto psx_create_err;
+       }
+
+       /* copy return information to pRetData */
+       psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol 
+                       + le16_to_cpu(pSMBr->t2.DataOffset));
+               
+       *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
+       if(netfid)
+               *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
+       /* Let caller know file was created so we can set the mode. */
+       /* Do we care about the CreateAction in any other cases? */
+       if(cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
+               *pOplock |= CIFS_CREATE_ACTION;
+       /* check to make sure response data is there */
+       if(psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
+               pRetData->Type = -1; /* unknown */
+#ifdef CONFIG_CIFS_DEBUG2
+               cFYI(1,("unknown type"));
+#endif
+       } else {
+               if(pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) 
+                                       + sizeof(FILE_UNIX_BASIC_INFO)) {
+                       cERROR(1,("Open response data too small"));
+                       pRetData->Type = -1;
+                       goto psx_create_err;
+               }
+               memcpy((char *) pRetData, 
+                       (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
+                       sizeof (FILE_UNIX_BASIC_INFO));
+       }
+                       
+
+psx_create_err:
+       cifs_buf_release(pSMB);
+
+       cifs_stats_inc(&tcon->num_mkdirs);
+
+       if (rc == -EAGAIN)
+               goto PsxCreat;
+
+       return rc;      
+}
+
 static __u16 convert_disposition(int disposition)
 {
        __u16 ofun = 0;
index 20ba7dc..216fb62 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mempool.h>
 #include <linux/delay.h>
 #include <linux/completion.h>
+#include <linux/kthread.h>
 #include <linux/pagevec.h>
 #include <linux/freezer.h>
 #include <asm/uaccess.h>
@@ -74,6 +75,8 @@ struct smb_vol {
        unsigned retry:1;
        unsigned intr:1;
        unsigned setuids:1;
+       unsigned override_uid:1;
+       unsigned override_gid:1;
        unsigned noperm:1;
        unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
        unsigned cifs_acl:1;
@@ -120,7 +123,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
        struct mid_q_entry * mid_entry;
        
        spin_lock(&GlobalMid_Lock);
-       if(server->tcpStatus == CifsExiting) {
+       if( kthread_should_stop() ) {
                /* the demux thread will exit normally 
                next time through the loop */
                spin_unlock(&GlobalMid_Lock);
@@ -182,7 +185,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
        spin_unlock(&GlobalMid_Lock);
        up(&server->tcpSem); 
 
-       while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
+       while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood))
        {
                try_to_freeze();
                if(server->protocolType == IPV6) {
@@ -199,7 +202,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                } else {
                        atomic_inc(&tcpSesReconnectCount);
                        spin_lock(&GlobalMid_Lock);
-                       if(server->tcpStatus != CifsExiting)
+                       if( !kthread_should_stop() )
                                server->tcpStatus = CifsGood;
                        server->sequence_number = 0;
                        spin_unlock(&GlobalMid_Lock);                   
@@ -345,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        int isMultiRsp;
        int reconnect;
 
-       daemonize("cifsd");
        allow_signal(SIGKILL);
        current->flags |= PF_MEMALLOC;
        server->tsk = current;  /* save process info to wake at shutdown */
@@ -361,7 +363,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                        GFP_KERNEL);
        }
 
-       while (server->tcpStatus != CifsExiting) {
+       while (!kthread_should_stop()) {
                if (try_to_freeze())
                        continue;
                if (bigbuf == NULL) {
@@ -400,7 +402,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                    kernel_recvmsg(csocket, &smb_msg,
                                 &iov, 1, 4, 0 /* BB see socket.h flags */);
 
-               if (server->tcpStatus == CifsExiting) {
+               if ( kthread_should_stop() ) {
                        break;
                } else if (server->tcpStatus == CifsNeedReconnect) {
                        cFYI(1, ("Reconnect after server stopped responding"));
@@ -524,7 +526,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                     total_read += length) {
                        length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
                                                pdu_length - total_read, 0);
-                       if((server->tcpStatus == CifsExiting) ||
+                       if( kthread_should_stop() ||
                            (length == -EINTR)) {
                                /* then will exit */
                                reconnect = 2;
@@ -757,7 +759,6 @@ multi_t2_fnd:
                        GFP_KERNEL);
        }
        
-       complete_and_exit(&cifsd_complete, 0);
        return 0;
 }
 
@@ -973,7 +974,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                        }
                        if ((temp_len = strnlen(value, 300)) < 300) {
                                vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
-                               if(vol->UNC == NULL)
+                               if (vol->UNC == NULL)
                                        return 1;
                                strcpy(vol->UNC,value);
                                if (strncmp(vol->UNC, "//", 2) == 0) {
@@ -1010,12 +1011,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                 return 1;       /* needs_arg; */
                         }
                         if ((temp_len = strnlen(value, 1024)) < 1024) {
-                               if(value[0] != '/')
+                               if (value[0] != '/')
                                        temp_len++;  /* missing leading slash */
                                 vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
-                                if(vol->prepath == NULL)
+                                if (vol->prepath == NULL)
                                         return 1;
-                               if(value[0] != '/') {
+                               if (value[0] != '/') {
                                        vol->prepath[0] = '/';
                                        strcpy(vol->prepath+1,value);
                                } else
@@ -1031,7 +1032,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                return 1;       /* needs_arg; */
                        }
                        if (strnlen(value, 65) < 65) {
-                               if(strnicmp(value,"default",7))
+                               if (strnicmp(value,"default",7))
                                        vol->iocharset = value;
                                /* if iocharset not set load_nls_default used by caller */
                                cFYI(1, ("iocharset set to %s",value));
@@ -1043,11 +1044,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                        if (value && *value) {
                                vol->linux_uid =
                                        simple_strtoul(value, &value, 0);
+                               vol->override_uid = 1;
                        }
                } else if (strnicmp(data, "gid", 3) == 0) {
                        if (value && *value) {
                                vol->linux_gid =
                                        simple_strtoul(value, &value, 0);
+                               vol->override_gid = 1;
                        }
                } else if (strnicmp(data, "file_mode", 4) == 0) {
                        if (value && *value) {
@@ -1102,7 +1105,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                }
                                /* The string has 16th byte zero still from
                                set at top of the function  */
-                               if((i==15) && (value[i] != 0))
+                               if ((i==15) && (value[i] != 0))
                                        printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
                        }
                } else if (strnicmp(data, "servern", 7) == 0) {
@@ -1126,7 +1129,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                }
                                /* The string has 16th byte zero still from
                                   set at top of the function  */
-                               if((i==15) && (value[i] != 0))
+                               if ((i==15) && (value[i] != 0))
                                        printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
                        }
                } else if (strnicmp(data, "credentials", 4) == 0) {
@@ -1233,13 +1236,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                        printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
        }
        if (vol->UNC == NULL) {
-               if(devname == NULL) {
+               if (devname == NULL) {
                        printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
                        return 1;
                }
                if ((temp_len = strnlen(devname, 300)) < 300) {
                        vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
-                       if(vol->UNC == NULL)
+                       if (vol->UNC == NULL)
                                return 1;
                        strcpy(vol->UNC,devname);
                        if (strncmp(vol->UNC, "//", 2) == 0) {
@@ -1663,7 +1666,13 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
                                CIFS_SB(sb)->mnt_cifs_flags |= 
                                        CIFS_MOUNT_POSIX_PATHS;
                }
-                       
+       
+               /* We might be setting the path sep back to a different
+               form if we are reconnecting and the server switched its
+               posix path capability for this share */ 
+               if(sb && (CIFS_SB(sb)->prepathlen > 0))
+                       CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
+       
                cFYI(1,("Negotiate caps 0x%x",(int)cap));
 #ifdef CONFIG_CIFS_DEBUG2
                if(cap & CIFS_UNIX_FCNTL_CAP)
@@ -1712,12 +1721,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                return -EINVAL;
        }
 
-       if (volume_info.username) {
+       if (volume_info.nullauth) {
+               cFYI(1,("null user"));
+               volume_info.username = NULL;
+       } else if (volume_info.username) {
                /* BB fixme parse for domain name here */
                cFYI(1, ("Username: %s ", volume_info.username));
-
-       } else if (volume_info.nullauth) {
-               cFYI(1,("null user"));
        } else {
                cifserror("No username specified");
         /* In userspace mount helper we can get user name from alternate
@@ -1791,11 +1800,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
                        NULL /* no ipv6 addr */,
                        volume_info.username, &srvTcp);
-       else if(address_type == AF_INET6)
+       else if(address_type == AF_INET6) {
+               cFYI(1,("looking for ipv6 address"));
                existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
                        &sin_server6.sin6_addr,
                        volume_info.username, &srvTcp);
-       else {
+       else {
                kfree(volume_info.UNC);
                kfree(volume_info.password);
                kfree(volume_info.prepath);
@@ -1807,17 +1817,23 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        if (srvTcp) {
                cFYI(1, ("Existing tcp session with server found"));                
        } else {        /* create socket */
-               if(volume_info.port)
+               if (volume_info.port)
                        sin_server.sin_port = htons(volume_info.port);
                else
                        sin_server.sin_port = 0;
-               rc = ipv4_connect(&sin_server,&csocket,
+               if (address_type == AF_INET6) {
+                       cFYI(1,("attempting ipv6 connect"));
+                       /* BB should we allow ipv6 on port 139? */
+                       /* other OS never observed in Wild doing 139 with v6 */
+                       rc = ipv6_connect(&sin_server6,&csocket);
+               } else 
+                       rc = ipv4_connect(&sin_server,&csocket,
                                  volume_info.source_rfc1001_name,
                                  volume_info.target_rfc1001_name);
                if (rc < 0) {
                        cERROR(1,
-                              ("Error connecting to IPv4 socket. Aborting operation"));
-                       if(csocket != NULL)
+                              ("Error connecting to IPv4 socket. Aborting operation"));                               
+                       if (csocket != NULL)
                                sock_release(csocket);
                        kfree(volume_info.UNC);
                        kfree(volume_info.password);
@@ -1850,10 +1866,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        so no need to spinlock this init of tcpStatus */
                        srvTcp->tcpStatus = CifsNew;
                        init_MUTEX(&srvTcp->tcpSem);
-                       rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
-                                     CLONE_FS | CLONE_FILES | CLONE_VM);
-                       if(rc < 0) {
-                               rc = -ENOMEM;
+                       srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
+                       if ( IS_ERR(srvTcp->tsk) ) {
+                               rc = PTR_ERR(srvTcp->tsk);
+                               cERROR(1,("error %d create cifsd thread", rc));
+                               srvTcp->tsk = NULL;
                                sock_release(csocket);
                                kfree(volume_info.UNC);
                                kfree(volume_info.password);
@@ -1896,7 +1913,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                int len = strlen(volume_info.domainname);
                                pSesInfo->domainName = 
                                        kmalloc(len + 1, GFP_KERNEL);
-                               if(pSesInfo->domainName)
+                               if (pSesInfo->domainName)
                                        strcpy(pSesInfo->domainName,
                                                volume_info.domainname);
                        }
@@ -1906,7 +1923,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        /* BB FIXME need to pass vol->secFlgs BB */
                        rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
                        up(&pSesInfo->sesSem);
-                       if(!rc)
+                       if (!rc)
                                atomic_inc(&srvTcp->socketUseCount);
                } else
                        kfree(volume_info.password);
@@ -1914,7 +1931,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
     
        /* search for existing tcon to this server share */
        if (!rc) {
-               if(volume_info.rsize > CIFSMaxBufSize) {
+               if (volume_info.rsize > CIFSMaxBufSize) {
                        cERROR(1,("rsize %d too large, using MaxBufSize",
                                volume_info.rsize));
                        cifs_sb->rsize = CIFSMaxBufSize;
@@ -1923,11 +1940,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                else /* default */
                        cifs_sb->rsize = CIFSMaxBufSize;
 
-               if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
+               if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
                        cERROR(1,("wsize %d too large using 4096 instead",
                                  volume_info.wsize));
                        cifs_sb->wsize = 4096;
-               } else if(volume_info.wsize)
+               } else if (volume_info.wsize)
                        cifs_sb->wsize = volume_info.wsize;
                else
                        cifs_sb->wsize = 
@@ -1940,14 +1957,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                           conjunction with 52K kvec constraint on arch with 4K
                           page size  */
 
-               if(cifs_sb->rsize < 2048) {
+               if (cifs_sb->rsize < 2048) {
                        cifs_sb->rsize = 2048; 
                        /* Windows ME may prefer this */
                        cFYI(1,("readsize set to minimum 2048"));
                }
                /* calculate prepath */
                cifs_sb->prepath = volume_info.prepath;
-               if(cifs_sb->prepath) {
+               if (cifs_sb->prepath) {
                        cifs_sb->prepathlen = strlen(cifs_sb->prepath);
                        cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
                        volume_info.prepath = NULL;
@@ -1960,24 +1977,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                cFYI(1,("file mode: 0x%x  dir mode: 0x%x",
                        cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
 
-               if(volume_info.noperm)
+               if (volume_info.noperm)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
-               if(volume_info.setuids)
+               if (volume_info.setuids)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
-               if(volume_info.server_ino)
+               if (volume_info.server_ino)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
-               if(volume_info.remap)
+               if (volume_info.remap)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
-               if(volume_info.no_xattr)
+               if (volume_info.no_xattr)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
-               if(volume_info.sfu_emul)
+               if (volume_info.sfu_emul)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
-               if(volume_info.nobrl)
+               if (volume_info.nobrl)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
-               if(volume_info.cifs_acl)
+               if (volume_info.cifs_acl)
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
-
-               if(volume_info.direct_io) {
+               if (volume_info.override_uid)
+                       cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
+               if (volume_info.override_gid)
+                       cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
+               if (volume_info.direct_io) {
                        cFYI(1,("mounting share using direct i/o"));
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
                }
@@ -2030,7 +2050,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        }
                }
        }
-       if(pSesInfo) {
+       if (pSesInfo) {
                if (pSesInfo->capabilities & CAP_LARGE_FILES) {
                        sb->s_maxbytes = (u64) 1 << 63;
                } else
@@ -2044,13 +2064,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        if (rc) {
                /* if session setup failed, use count is zero but
                we still need to free cifsd thread */
-               if(atomic_read(&srvTcp->socketUseCount) == 0) {
+               if (atomic_read(&srvTcp->socketUseCount) == 0) {
                        spin_lock(&GlobalMid_Lock);
                        srvTcp->tcpStatus = CifsExiting;
                        spin_unlock(&GlobalMid_Lock);
-                       if(srvTcp->tsk) {
+                       if (srvTcp->tsk) {
                                send_sig(SIGKILL,srvTcp->tsk,1);
-                               wait_for_completion(&cifsd_complete);
+                               kthread_stop(srvTcp->tsk);
                        }
                }
                 /* If find_unc succeeded then rc == 0 so we can not end */
@@ -2063,10 +2083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                        int temp_rc;
                                        temp_rc = CIFSSMBLogoff(xid, pSesInfo);
                                        /* if the socketUseCount is now zero */
-                                       if((temp_rc == -ESHUTDOWN) &&
-                                          (pSesInfo->server->tsk)) {
+                                       if ((temp_rc == -ESHUTDOWN) &&
+                                          (pSesInfo->server) && (pSesInfo->server->tsk)) {
                                                send_sig(SIGKILL,pSesInfo->server->tsk,1);
-                                               wait_for_completion(&cifsd_complete);
+                                               kthread_stop(pSesInfo->server->tsk);
                                        }
                                } else
                                        cFYI(1, ("No session or bad tcon"));
@@ -2127,7 +2147,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        __u16 count;
 
        cFYI(1, ("In sesssetup"));
-       if(ses == NULL)
+       if (ses == NULL)
                return -EINVAL;
        user = ses->userName;
        domain = ses->domainName;
@@ -2182,7 +2202,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                        *bcc_ptr = 0;
                        bcc_ptr++;
                }
-               if(user == NULL)
+               if (user == NULL)
                        bytes_returned = 0; /* skip null user */
                else
                        bytes_returned =
@@ -2216,7 +2236,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;
        } else {
-               if(user != NULL) {                
+               if (user != NULL) {                
                    strncpy(bcc_ptr, user, 200);
                    bcc_ptr += strnlen(user, 200);
                }
@@ -3316,7 +3336,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
                                cFYI(1,("Waking up socket by sending it signal"));
                                if(cifsd_task) {
                                        send_sig(SIGKILL,cifsd_task,1);
-                                       wait_for_completion(&cifsd_complete);
+                                       kthread_stop(cifsd_task);
                                }
                                rc = 0;
                        } /* else - we have an smb session
index 3fad638..e521051 100644 (file)
@@ -274,7 +274,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        pCifsFile->invalidHandle = FALSE;
                        pCifsFile->closePend     = FALSE;
                        init_MUTEX(&pCifsFile->fh_sem);
-                       init_MUTEX(&pCifsFile->lock_sem);
+                       mutex_init(&pCifsFile->lock_mutex);
                        INIT_LIST_HEAD(&pCifsFile->llist);
                        atomic_set(&pCifsFile->wrtPending,0);
 
index 2d3275b..b570530 100644 (file)
@@ -48,7 +48,7 @@ static inline struct cifsFileInfo *cifs_init_private(
        private_data->netfid = netfid;
        private_data->pid = current->tgid;      
        init_MUTEX(&private_data->fh_sem);
-       init_MUTEX(&private_data->lock_sem);
+       mutex_init(&private_data->lock_mutex);
        INIT_LIST_HEAD(&private_data->llist);
        private_data->pfile = file; /* needed for writepage */
        private_data->pInode = inode;
@@ -338,8 +338,7 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile)
        return rc;
 }
 
-static int cifs_reopen_file(struct inode *inode, struct file *file, 
-       int can_flush)
+static int cifs_reopen_file(struct file *file, int can_flush)
 {
        int rc = -EACCES;
        int xid, oplock;
@@ -347,13 +346,12 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
        struct cifsTconInfo *pTcon;
        struct cifsFileInfo *pCifsFile;
        struct cifsInodeInfo *pCifsInode;
+       struct inode * inode;
        char *full_path = NULL;
        int desiredAccess;
        int disposition = FILE_OPEN;
        __u16 netfid;
 
-       if (inode == NULL)
-               return -EBADF;
        if (file->private_data) {
                pCifsFile = (struct cifsFileInfo *)file->private_data;
        } else
@@ -368,25 +366,37 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
        }
 
        if (file->f_path.dentry == NULL) {
-               up(&pCifsFile->fh_sem);
-               cFYI(1, ("failed file reopen, no valid name if dentry freed"));
-               FreeXid(xid);
-               return -EBADF;
+               cERROR(1, ("no valid name if dentry freed"));
+               dump_stack();
+               rc = -EBADF;
+               goto reopen_error_exit;
        }
+
+       inode = file->f_path.dentry->d_inode;
+       if(inode == NULL) {
+               cERROR(1, ("inode not valid"));
+               dump_stack();
+               rc = -EBADF;
+               goto reopen_error_exit;
+       }
+               
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
+
 /* can not grab rename sem here because various ops, including
    those that already have the rename sem can end up causing writepage
    to get called and if the server was down that means we end up here,
    and we can never tell if the caller already has the rename_sem */
        full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
+reopen_error_exit:
                up(&pCifsFile->fh_sem);
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
-       cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+       cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
                 inode, file->f_flags,full_path));
        desiredAccess = cifs_convert_flags(file->f_flags);
 
@@ -401,13 +411,6 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
           and server version of file size can be stale. If we knew for sure
           that inode was not dirty locally we could do this */
 
-/*     buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
-       if (buf == 0) {
-               up(&pCifsFile->fh_sem);
-               kfree(full_path);
-               FreeXid(xid);
-               return -ENOMEM;
-       } */
        rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
                         CREATE_NOT_DIR, &netfid, &oplock, NULL,
                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
@@ -508,12 +511,12 @@ int cifs_close(struct inode *inode, struct file *file)
 
                /* Delete any outstanding lock records.
                   We'll lose them when the file is closed anyway. */
-               down(&pSMBFile->lock_sem);
+               mutex_lock(&pSMBFile->lock_mutex);
                list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
                        list_del(&li->llist);
                        kfree(li);
                }
-               up(&pSMBFile->lock_sem);
+               mutex_unlock(&pSMBFile->lock_mutex);
 
                write_lock(&GlobalSMBSeslock);
                list_del(&pSMBFile->flist);
@@ -598,9 +601,9 @@ static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
        li->offset = offset;
        li->length = len;
        li->type = lockType;
-       down(&fid->lock_sem);
+       mutex_lock(&fid->lock_mutex);
        list_add(&li->llist, &fid->llist);
-       up(&fid->lock_sem);
+       mutex_unlock(&fid->lock_mutex);
        return 0;
 }
 
@@ -757,7 +760,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                        struct cifsLockInfo *li, *tmp;
 
                        rc = 0;
-                       down(&fid->lock_sem);
+                       mutex_lock(&fid->lock_mutex);
                        list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
                                if (pfLock->fl_start <= li->offset &&
                                                length >= li->length) {
@@ -771,7 +774,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                                        kfree(li);
                                }
                        }
-                       up(&fid->lock_sem);
+                       mutex_unlock(&fid->lock_mutex);
                }
        }
 
@@ -792,12 +795,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
        int xid, long_op;
        struct cifsFileInfo *open_file;
 
-       if (file->f_path.dentry == NULL)
-               return -EBADF;
-
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-       if (cifs_sb == NULL)
-               return -EBADF;
 
        pTcon = cifs_sb->tcon;
 
@@ -807,14 +805,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
 
        if (file->private_data == NULL)
                return -EBADF;
-       else
-               open_file = (struct cifsFileInfo *) file->private_data;
+       open_file = (struct cifsFileInfo *) file->private_data;
        
        xid = GetXid();
-       if (file->f_path.dentry->d_inode == NULL) {
-               FreeXid(xid);
-               return -EBADF;
-       }
 
        if (*poffset > file->f_path.dentry->d_inode->i_size)
                long_op = 2; /* writes past end of file can take a long time */
@@ -841,17 +834,11 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                                        return -EBADF;
                        }
                        if (open_file->invalidHandle) {
-                               if ((file->f_path.dentry == NULL) ||
-                                   (file->f_path.dentry->d_inode == NULL)) {
-                                       FreeXid(xid);
-                                       return total_written;
-                               }
                                /* we could deadlock if we called
                                   filemap_fdatawait from here so tell
                                   reopen_file not to flush data to server
                                   now */
-                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
-                                       file, FALSE);
+                               rc = cifs_reopen_file(file, FALSE);
                                if (rc != 0)
                                        break;
                        }
@@ -908,12 +895,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
        int xid, long_op;
        struct cifsFileInfo *open_file;
 
-       if (file->f_path.dentry == NULL)
-               return -EBADF;
-
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-       if (cifs_sb == NULL)
-               return -EBADF;
 
        pTcon = cifs_sb->tcon;
 
@@ -922,14 +904,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
 
        if (file->private_data == NULL)
                return -EBADF;
-       else
-               open_file = (struct cifsFileInfo *)file->private_data;
+       open_file = (struct cifsFileInfo *)file->private_data;
        
        xid = GetXid();
-       if (file->f_path.dentry->d_inode == NULL) {
-               FreeXid(xid);
-               return -EBADF;
-       }
 
        if (*poffset > file->f_path.dentry->d_inode->i_size)
                long_op = 2; /* writes past end of file can take a long time */
@@ -957,17 +934,11 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
                                        return -EBADF;
                        }
                        if (open_file->invalidHandle) {
-                               if ((file->f_path.dentry == NULL) ||
-                                  (file->f_path.dentry->d_inode == NULL)) {
-                                       FreeXid(xid);
-                                       return total_written;
-                               }
                                /* we could deadlock if we called
                                   filemap_fdatawait from here so tell
                                   reopen_file not to flush data to 
                                   server now */
-                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
-                                       file, FALSE);
+                               rc = cifs_reopen_file(file, FALSE);
                                if (rc != 0)
                                        break;
                        }
@@ -1056,8 +1027,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
                        read_unlock(&GlobalSMBSeslock);
                        if((open_file->invalidHandle) && 
                           (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
-                               rc = cifs_reopen_file(&cifs_inode->vfs_inode, 
-                                                     open_file->pfile, FALSE);
+                               rc = cifs_reopen_file(open_file->pfile, FALSE);
                                /* if it fails, try another handle - might be */
                                /* dangerous to hold up writepages with retry */
                                if(rc) {
@@ -1404,32 +1374,6 @@ static int cifs_commit_write(struct file *file, struct page *page,
        spin_lock(&inode->i_lock);
        if (position > inode->i_size) {
                i_size_write(inode, position);
-               /* if (file->private_data == NULL) {
-                       rc = -EBADF;
-               } else {
-                       open_file = (struct cifsFileInfo *)file->private_data;
-                       cifs_sb = CIFS_SB(inode->i_sb);
-                       rc = -EAGAIN;
-                       while (rc == -EAGAIN) {
-                               if ((open_file->invalidHandle) && 
-                                   (!open_file->closePend)) {
-                                       rc = cifs_reopen_file(
-                                               file->f_path.dentry->d_inode, file);
-                                       if (rc != 0)
-                                               break;
-                               }
-                               if (!open_file->closePend) {
-                                       rc = CIFSSMBSetFileSize(xid,
-                                               cifs_sb->tcon, position,
-                                               open_file->netfid,
-                                               open_file->pid, FALSE);
-                               } else {
-                                       rc = -EBADF;
-                                       break;
-                               }
-                       }
-                       cFYI(1, (" SetEOF (commit write) rc = %d", rc));
-               } */
        }
        spin_unlock(&inode->i_lock);
        if (!PageUptodate(page)) {
@@ -1573,8 +1517,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
                        int buf_type = CIFS_NO_BUFFER;
                        if ((open_file->invalidHandle) && 
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
-                                       file, TRUE);
+                               rc = cifs_reopen_file(file, TRUE);
                                if (rc != 0)
                                        break;
                        }
@@ -1660,8 +1603,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
                while (rc == -EAGAIN) {
                        if ((open_file->invalidHandle) && 
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
-                                       file, TRUE);
+                               rc = cifs_reopen_file(file, TRUE);
                                if (rc != 0)
                                        break;
                        }
@@ -1817,8 +1759,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                while (rc == -EAGAIN) {
                        if ((open_file->invalidHandle) && 
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
-                                       file, TRUE);
+                               rc = cifs_reopen_file(file, TRUE);
                                if (rc != 0)
                                        break;
                        }
index f414526..3e87dad 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/inode.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Copyright (C) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -90,7 +90,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                                (*pinode)->i_ino =
                                        (unsigned long)findData.UniqueId;
                        } /* note ino incremented to unique num in new_inode */
-                       if(sb->s_flags & MS_NOATIME)
+                       if (sb->s_flags & MS_NOATIME)
                                (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
                                
                        insert_inode_hash(*pinode);
@@ -139,8 +139,17 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                        inode->i_mode |= S_IFREG;
                        cFYI(1,("unknown type %d",type));
                }
-               inode->i_uid = le64_to_cpu(findData.Uid);
-               inode->i_gid = le64_to_cpu(findData.Gid);
+               
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
+                       inode->i_uid = cifs_sb->mnt_uid;
+               else
+                       inode->i_uid = le64_to_cpu(findData.Uid);
+
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
+                       inode->i_gid = cifs_sb->mnt_gid;
+               else
+                       inode->i_gid = le64_to_cpu(findData.Gid);
+                       
                inode->i_nlink = le64_to_cpu(findData.Nlinks);
 
                spin_lock(&inode->i_lock);
@@ -178,13 +187,13 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                                                &cifs_file_direct_nobrl_ops;
                                else
                                        inode->i_fop = &cifs_file_direct_ops;
-                       } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                       } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                inode->i_fop = &cifs_file_nobrl_ops;
                        else /* not direct, send byte range locks */ 
                                inode->i_fop = &cifs_file_ops;
 
                        /* check if server can support readpages */
-                       if(pTcon->ses->server->maxBuf < 
+                       if (pTcon->ses->server->maxBuf < 
                            PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
                                inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
                        else
@@ -220,7 +229,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
 
        pbuf = buf;
 
-       if(size == 0) {
+       if (size == 0) {
                inode->i_mode |= S_IFIFO;
                return 0;
        } else if (size < 8) {
@@ -239,11 +248,11 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
                                 netfid,
                                 24 /* length */, 0 /* offset */,
                                 &bytes_read, &pbuf, &buf_type);
-               if((rc == 0) && (bytes_read >= 8)) {
-                       if(memcmp("IntxBLK", pbuf, 8) == 0) {
+               if ((rc == 0) && (bytes_read >= 8)) {
+                       if (memcmp("IntxBLK", pbuf, 8) == 0) {
                                cFYI(1,("Block device"));
                                inode->i_mode |= S_IFBLK;
-                               if(bytes_read == 24) {
+                               if (bytes_read == 24) {
                                        /* we have enough to decode dev num */
                                        __u64 mjr; /* major */
                                        __u64 mnr; /* minor */
@@ -251,10 +260,10 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
                                        mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
                                        inode->i_rdev = MKDEV(mjr, mnr);
                                }
-                       } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
+                       } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
                                cFYI(1,("Char device"));
                                inode->i_mode |= S_IFCHR;
-                               if(bytes_read == 24) {
+                               if (bytes_read == 24) {
                                        /* we have enough to decode dev num */
                                        __u64 mjr; /* major */
                                        __u64 mnr; /* minor */
@@ -262,7 +271,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
                                        mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
                                        inode->i_rdev = MKDEV(mjr, mnr);
                                 }
-                       } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
+                       } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
                                cFYI(1,("Symlink"));
                                inode->i_mode |= S_IFLNK;
                        } else {
@@ -293,7 +302,7 @@ static int get_sfu_uid_mode(struct inode * inode,
        rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
                        ea_value, 4 /* size of buf */, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if(rc < 0)
+       if (rc < 0)
                return (int)rc;
        else if (rc > 3) {
                mode = le32_to_cpu(*((__le32 *)ea_value));
@@ -348,7 +357,7 @@ int cifs_get_inode_info(struct inode **pinode,
                /* BB optimize code so we do not make the above call
                when server claims no NT SMB support and the above call
                failed at least once - set flag in tcon or mount */
-               if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
+               if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
                        rc = SMBQueryInformation(xid, pTcon, search_path,
                                        pfindData, cifs_sb->local_nls, 
                                        cifs_sb->mnt_cifs_flags &
@@ -425,7 +434,7 @@ int cifs_get_inode_info(struct inode **pinode,
                                } else /* do we need cast or hash to ino? */
                                        (*pinode)->i_ino = inode_num;
                        } /* else ino incremented to unique num in new_inode*/
-                       if(sb->s_flags & MS_NOATIME)
+                       if (sb->s_flags & MS_NOATIME)
                                (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
                        insert_inode_hash(*pinode);
                }
@@ -442,7 +451,7 @@ int cifs_get_inode_info(struct inode **pinode,
                (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
 
                /* Linux can not store file creation time so ignore it */
-               if(pfindData->LastAccessTime)
+               if (pfindData->LastAccessTime)
                        inode->i_atime = cifs_NTtimeToUnix
                                (le64_to_cpu(pfindData->LastAccessTime));
                else /* do not need to use current_fs_time - time not stored */
@@ -452,7 +461,7 @@ int cifs_get_inode_info(struct inode **pinode,
                inode->i_ctime =
                    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
                cFYI(0, ("Attributes came in as 0x%x", attr));
-               if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
+               if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
                        inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
                        inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
                }
@@ -521,8 +530,10 @@ int cifs_get_inode_info(struct inode **pinode,
 
                /* BB fill in uid and gid here? with help from winbind? 
                   or retrieve from NTFS stream extended attribute */
-               if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
                        /* fill in uid, gid, mode from server ACL */
+                       /* BB FIXME this should also take into account the
+                        * default uid specified on mount if present */
                        get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
                } else if (atomic_read(&cifsInfo->inUse) == 0) {
                        inode->i_uid = cifs_sb->mnt_uid;
@@ -541,12 +552,12 @@ int cifs_get_inode_info(struct inode **pinode,
                                                &cifs_file_direct_nobrl_ops;
                                else
                                        inode->i_fop = &cifs_file_direct_ops;
-                       } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                       } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                inode->i_fop = &cifs_file_nobrl_ops;
                        else /* not direct, send byte range locks */
                                inode->i_fop = &cifs_file_ops;
 
-                       if(pTcon->ses->server->maxBuf < 
+                       if (pTcon->ses->server->maxBuf < 
                             PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
                                inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
                        else
@@ -597,7 +608,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
 
        xid = GetXid();
 
-       if(inode)
+       if (inode)
                cifs_sb = CIFS_SB(inode->i_sb);
        else
                cifs_sb = CIFS_SB(direntry->d_sb);
@@ -723,7 +734,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
                                           when needed */
                direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
        }
-       if(inode) {
+       if (inode) {
                inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
                cifsInode = CIFS_I(inode);
                cifsInode->time = 0;    /* force revalidate of dir as well */
@@ -734,6 +745,136 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
        return rc;
 }
 
+static void posix_fill_in_inode(struct inode *tmp_inode,
+       FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
+{
+       loff_t local_size;
+       struct timespec local_mtime;
+
+       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+
+       __u32 type = le32_to_cpu(pData->Type);
+       __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
+       __u64 end_of_file = le64_to_cpu(pData->EndOfFile);
+       cifsInfo->time = jiffies;
+       atomic_inc(&cifsInfo->inUse);
+
+       /* save mtime and size */
+       local_mtime = tmp_inode->i_mtime;
+       local_size  = tmp_inode->i_size;
+
+       tmp_inode->i_atime =
+           cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
+       tmp_inode->i_mtime =
+           cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
+       tmp_inode->i_ctime =
+           cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
+
+       tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
+       /* since we set the inode type below we need to mask off type
+           to avoid strange results if bits above were corrupt */
+        tmp_inode->i_mode &= ~S_IFMT;
+       if (type == UNIX_FILE) {
+               *pobject_type = DT_REG;
+               tmp_inode->i_mode |= S_IFREG;
+       } else if (type == UNIX_SYMLINK) {
+               *pobject_type = DT_LNK;
+               tmp_inode->i_mode |= S_IFLNK;
+       } else if (type == UNIX_DIR) {
+               *pobject_type = DT_DIR;
+               tmp_inode->i_mode |= S_IFDIR;
+       } else if (type == UNIX_CHARDEV) {
+               *pobject_type = DT_CHR;
+               tmp_inode->i_mode |= S_IFCHR;
+               tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
+                               le64_to_cpu(pData->DevMinor) & MINORMASK);
+       } else if (type == UNIX_BLOCKDEV) {
+               *pobject_type = DT_BLK;
+               tmp_inode->i_mode |= S_IFBLK;
+               tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
+                               le64_to_cpu(pData->DevMinor) & MINORMASK);
+       } else if (type == UNIX_FIFO) {
+               *pobject_type = DT_FIFO;
+               tmp_inode->i_mode |= S_IFIFO;
+       } else if (type == UNIX_SOCKET) {
+               *pobject_type = DT_SOCK;
+               tmp_inode->i_mode |= S_IFSOCK;
+       } else {
+               /* safest to just call it a file */
+               *pobject_type = DT_REG;
+               tmp_inode->i_mode |= S_IFREG;
+               cFYI(1,("unknown inode type %d",type)); 
+       }
+
+#ifdef CONFIG_CIFS_DEBUG2
+       cFYI(1,("object type: %d", type));
+#endif
+       tmp_inode->i_uid = le64_to_cpu(pData->Uid);
+       tmp_inode->i_gid = le64_to_cpu(pData->Gid);
+       tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
+
+       spin_lock(&tmp_inode->i_lock);
+       if (is_size_safe_to_change(cifsInfo, end_of_file)) {
+               /* can not safely change the file size here if the 
+               client is writing to it due to potential races */
+               i_size_write(tmp_inode, end_of_file);
+
+       /* 512 bytes (2**9) is the fake blocksize that must be used */
+       /* for this calculation, not the real blocksize */
+               tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
+       }
+       spin_unlock(&tmp_inode->i_lock);
+
+       if (S_ISREG(tmp_inode->i_mode)) {
+               cFYI(1, ("File inode"));
+               tmp_inode->i_op = &cifs_file_inode_ops;
+
+               if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+                       if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                               tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
+                       else
+                               tmp_inode->i_fop = &cifs_file_direct_ops;
+               
+               } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                       tmp_inode->i_fop = &cifs_file_nobrl_ops;
+               else
+                       tmp_inode->i_fop = &cifs_file_ops;
+
+               if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
+                  (cifs_sb->tcon->ses->server->maxBuf < 
+                       PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
+                       tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+               else
+                       tmp_inode->i_data.a_ops = &cifs_addr_ops;
+
+               if(isNewInode)
+                       return; /* No sense invalidating pages for new inode since we
+                                          have not started caching readahead file data yet */
+
+               if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+                       (local_size == tmp_inode->i_size)) {
+                       cFYI(1, ("inode exists but unchanged"));
+               } else {
+                       /* file may have changed on server */
+                       cFYI(1, ("invalidate inode, readdir detected change"));
+                       invalidate_remote_inode(tmp_inode);
+               }
+       } else if (S_ISDIR(tmp_inode->i_mode)) {
+               cFYI(1, ("Directory inode"));
+               tmp_inode->i_op = &cifs_dir_inode_ops;
+               tmp_inode->i_fop = &cifs_dir_ops;
+       } else if (S_ISLNK(tmp_inode->i_mode)) {
+               cFYI(1, ("Symbolic Link inode"));
+               tmp_inode->i_op = &cifs_symlink_inode_ops;
+/* tmp_inode->i_fop = *//* do not need to set to anything */
+       } else {
+               cFYI(1, ("Special inode")); 
+               init_special_inode(tmp_inode, tmp_inode->i_mode,
+                                  tmp_inode->i_rdev);
+       }       
+}
+
 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 {
        int rc = 0;
@@ -755,6 +896,71 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                FreeXid(xid);
                return -ENOMEM;
        }
+       
+       if((pTcon->ses->capabilities & CAP_UNIX) && 
+               (CIFS_UNIX_POSIX_PATH_OPS_CAP & 
+                       le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
+               u32 oplock = 0;
+               FILE_UNIX_BASIC_INFO * pInfo = 
+                       kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+               if(pInfo == NULL) {
+                       rc = -ENOMEM;
+                       goto mkdir_out;
+               }
+                       
+               rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
+                               mode, NULL /* netfid */, pInfo, &oplock,
+                               full_path, cifs_sb->local_nls, 
+                               cifs_sb->mnt_cifs_flags & 
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (rc) {
+                       cFYI(1, ("posix mkdir returned 0x%x", rc));
+                       d_drop(direntry);
+               } else {
+                       int obj_type;
+                       if (pInfo->Type == -1) /* no return info - go query */
+                               goto mkdir_get_info; 
+/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
+                       inc_nlink(inode);
+                       if (pTcon->nocase)
+                               direntry->d_op = &cifs_ci_dentry_ops;
+                       else
+                               direntry->d_op = &cifs_dentry_ops;
+
+                       newinode = new_inode(inode->i_sb);
+                       if (newinode == NULL)
+                               goto mkdir_get_info;
+                       /* Is an i_ino of zero legal? */
+                       /* Are there sanity checks we can use to ensure that
+                          the server is really filling in that field? */
+                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+                               newinode->i_ino =
+                                       (unsigned long)pInfo->UniqueId;
+                       } /* note ino incremented to unique num in new_inode */
+                       if(inode->i_sb->s_flags & MS_NOATIME)
+                               newinode->i_flags |= S_NOATIME | S_NOCMTIME;
+                       newinode->i_nlink = 2;
+
+                       insert_inode_hash(newinode);
+                       d_instantiate(direntry, newinode);
+
+                       /* we already checked in POSIXCreate whether
+                          frame was long enough */
+                       posix_fill_in_inode(direntry->d_inode,
+                                       pInfo, &obj_type, 1 /* NewInode */);
+#ifdef CONFIG_CIFS_DEBUG2
+                       cFYI(1,("instantiated dentry %p %s to inode %p",
+                               direntry, direntry->d_name.name, newinode));
+
+                       if(newinode->i_nlink != 2)
+                               cFYI(1,("unexpected number of links %d",
+                                       newinode->i_nlink));
+#endif
+               }
+               kfree(pInfo);
+               goto mkdir_out;
+       }       
+       
        /* BB add setting the equivalent of mode via CreateX w/ACLs */
        rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -762,6 +968,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                cFYI(1, ("cifs_mkdir returned 0x%x", rc));
                d_drop(direntry);
        } else {
+mkdir_get_info:                
                inc_nlink(inode);
                if (pTcon->ses->capabilities & CAP_UNIX)
                        rc = cifs_get_inode_info_unix(&newinode, full_path,
@@ -775,8 +982,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                else
                        direntry->d_op = &cifs_dentry_ops;
                d_instantiate(direntry, newinode);
-               if (direntry->d_inode)
-                       direntry->d_inode->i_nlink = 2;
+                /* setting nlink not necessary except in cases where we
+                 * failed to get it from the server or was set bogus */ 
+               if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
+                               direntry->d_inode->i_nlink = 2; 
                if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                                CIFSSMBUnixSetPerms(xid, pTcon, full_path,
@@ -812,6 +1021,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        }
                }
        }
+mkdir_out:     
        kfree(full_path);
        FreeXid(xid);
        return rc;
@@ -1339,17 +1549,17 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                                        cpu_to_le32(cifsInode->cifsAttrs |
                                                    ATTR_READONLY);
                        }
-               } else if ((mode & S_IWUGO) == S_IWUGO) {
-                       if (cifsInode->cifsAttrs & ATTR_READONLY) {
-                               set_dosattr = TRUE;
-                               time_buf.Attributes =
-                                       cpu_to_le32(cifsInode->cifsAttrs &
-                                                   (~ATTR_READONLY));
-                               /* Windows ignores set to zero */
-                               if(time_buf.Attributes == 0)
-                                       time_buf.Attributes |= 
-                                               cpu_to_le32(ATTR_NORMAL);
-                       }
+               } else if (cifsInode->cifsAttrs & ATTR_READONLY) {
+                       /* If file is readonly on server, we would
+                       not be able to write to it - so if any write
+                       bit is enabled for user or group or other we
+                       need to at least try to remove r/o dos attr */
+                       set_dosattr = TRUE;
+                       time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
+                                           (~ATTR_READONLY));
+                       /* Windows ignores set to zero */
+                       if(time_buf.Attributes == 0)
+                               time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
                }
                /* BB to be implemented -
                   via Windows security descriptors or streams */
index 992e80e..53e304d 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/fs.h>
 #include <asm/div64.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+#include <linux/inet.h>
+#endif
 #include "cifsfs.h"
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -129,11 +132,27 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
 /* Convert string containing dotted ip address to binary form */
 /* returns 0 if invalid address */
 
-/* BB add address family, change rc to status flag and return union or for ipv6 */
-/*  will need parent to call something like inet_pton to convert ipv6 address  BB */
 int
 cifs_inet_pton(int address_family, char *cp,void *dst)
 {
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       int ret = 0;
+
+       /* calculate length by finding first slash or NULL */
+       /* BB Should we convert '/' slash to '\' here since it seems already done
+          before this */
+       if( address_family == AF_INET ){
+               ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);     
+       } else if( address_family == AF_INET6 ){
+               ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
+       }
+#ifdef CONFIG_CIFS_DEBUG2
+       cFYI(1,("address conversion returned %d for %s", ret, cp));
+#endif
+       if (ret > 0)
+               ret = 1;
+       return ret;
+#else
        int value;
        int digit;
        int i;
@@ -192,6 +211,7 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
 
        *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
        return 1; /* success */
+#endif /* EXPERIMENTAL */      
 }
 
 /*****************************************************************************
index 2a374d5..b5364f9 100644 (file)
@@ -37,19 +37,19 @@ static void dump_cifs_file_struct(struct file *file, char *label)
 {
        struct cifsFileInfo * cf;
 
-       if(file) {
+       if (file) {
                cf = file->private_data;
-               if(cf == NULL) {
+               if (cf == NULL) {
                        cFYI(1,("empty cifs private file data"));
                        return;
                }
-               if(cf->invalidHandle) {
+               if (cf->invalidHandle) {
                        cFYI(1,("invalid handle"));
                }
-               if(cf->srch_inf.endOfSearch) {
+               if (cf->srch_inf.endOfSearch) {
                        cFYI(1,("end of search"));
                }
-               if(cf->srch_inf.emptyDir) {
+               if (cf->srch_inf.emptyDir) {
                        cFYI(1,("empty dir"));
                }
                
@@ -77,17 +77,17 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
                cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
                *ptmp_inode = tmp_dentry->d_inode;
 /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
-               if(*ptmp_inode == NULL) {
+               if (*ptmp_inode == NULL) {
                        *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
-                       if(*ptmp_inode == NULL)
+                       if (*ptmp_inode == NULL)
                                return rc;
                        rc = 1;
                }
-               if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
+               if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
                        (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
        } else {
                tmp_dentry = d_alloc(file->f_path.dentry, qstring);
-               if(tmp_dentry == NULL) {
+               if (tmp_dentry == NULL) {
                        cERROR(1,("Failed allocating dentry"));
                        *ptmp_inode = NULL;
                        return rc;
@@ -98,9 +98,9 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
                        tmp_dentry->d_op = &cifs_ci_dentry_ops;
                else
                        tmp_dentry->d_op = &cifs_dentry_ops;
-               if(*ptmp_inode == NULL)
+               if (*ptmp_inode == NULL)
                        return rc;
-               if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
+               if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
                        (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;                       
                rc = 2;
        }
@@ -112,7 +112,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
 
 static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
 {
-       if((tcon) && (tcon->ses) && (tcon->ses->server)) {
+       if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
                inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
                inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
                inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
@@ -137,7 +137,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
        local_mtime = tmp_inode->i_mtime;
        local_size  = tmp_inode->i_size;
 
-       if(new_buf_type) {
+       if (new_buf_type) {
                FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
 
                attr = le32_to_cpu(pfindData->ExtFileAttributes);
@@ -193,7 +193,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
        if (attr & ATTR_DIRECTORY) {
                *pobject_type = DT_DIR;
                /* override default perms since we do not lock dirs */
-               if(atomic_read(&cifsInfo->inUse) == 0) {
+               if (atomic_read(&cifsInfo->inUse) == 0) {
                        tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
                }
                tmp_inode->i_mode |= S_IFDIR;
@@ -250,25 +250,25 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
        if (S_ISREG(tmp_inode->i_mode)) {
                cFYI(1, ("File inode"));
                tmp_inode->i_op = &cifs_file_inode_ops;
-               if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                       if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
                        else
                                tmp_inode->i_fop = &cifs_file_direct_ops;
                
-               } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                        tmp_inode->i_fop = &cifs_file_nobrl_ops;
                else
                        tmp_inode->i_fop = &cifs_file_ops;
 
-               if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
+               if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
                   (cifs_sb->tcon->ses->server->maxBuf <
                        PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
                        tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
                else
                        tmp_inode->i_data.a_ops = &cifs_addr_ops;
 
-               if(isNewInode)
+               if (isNewInode)
                        return; /* No sense invalidating pages for new inode
                                   since have not started caching readahead file
                                   data yet */
@@ -357,8 +357,14 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
                cFYI(1,("unknown inode type %d",type)); 
        }
 
-       tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
-       tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
+               tmp_inode->i_uid = cifs_sb->mnt_uid;
+       else
+               tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
+               tmp_inode->i_gid = cifs_sb->mnt_gid;
+       else
+               tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
        tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
 
        spin_lock(&tmp_inode->i_lock);
@@ -377,25 +383,24 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
                cFYI(1, ("File inode"));
                tmp_inode->i_op = &cifs_file_inode_ops;
 
-               if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                       if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
                        else
                                tmp_inode->i_fop = &cifs_file_direct_ops;
-               
-               } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                        tmp_inode->i_fop = &cifs_file_nobrl_ops;
                else
                        tmp_inode->i_fop = &cifs_file_ops;
 
-               if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
+               if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
                   (cifs_sb->tcon->ses->server->maxBuf < 
                        PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
                        tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
                else
                        tmp_inode->i_data.a_ops = &cifs_addr_ops;
 
-               if(isNewInode)
+               if (isNewInode)
                        return; /* No sense invalidating pages for new inode since we
                                           have not started caching readahead file data yet */
 
@@ -430,34 +435,28 @@ static int initiate_cifs_search(const int xid, struct file *file)
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *pTcon;
 
-       if(file->private_data == NULL) {
+       if (file->private_data == NULL) {
                file->private_data = 
-                       kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
+                       kzalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
        }
 
-       if(file->private_data == NULL) {
+       if (file->private_data == NULL)
                return -ENOMEM;
-       } else {
-               memset(file->private_data,0,sizeof(struct cifsFileInfo));
-       }
        cifsFile = file->private_data;
        cifsFile->invalidHandle = TRUE;
        cifsFile->srch_inf.endOfSearch = FALSE;
 
-       if(file->f_path.dentry == NULL)
-               return -ENOENT;
-
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-       if(cifs_sb == NULL)
+       if (cifs_sb == NULL)
                return -EINVAL;
 
        pTcon = cifs_sb->tcon;
-       if(pTcon == NULL)
+       if (pTcon == NULL)
                return -EINVAL;
 
        full_path = build_path_from_dentry(file->f_path.dentry);
 
-       if(full_path == NULL) {
+       if (full_path == NULL) {
                return -ENOMEM;
        }
 
@@ -480,9 +479,9 @@ ffirst_retry:
                &cifsFile->netfid, &cifsFile->srch_inf,
                cifs_sb->mnt_cifs_flags & 
                        CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
-       if(rc == 0)
+       if (rc == 0)
                cifsFile->invalidHandle = FALSE;
-       if((rc == -EOPNOTSUPP) && 
+       if ((rc == -EOPNOTSUPP) && 
                (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
                cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
                goto ffirst_retry;
@@ -498,7 +497,7 @@ static int cifs_unicode_bytelen(char *str)
        __le16 * ustr = (__le16 *)str;
 
        for(len=0;len <= PATH_MAX;len++) {
-               if(ustr[len] == 0)
+               if (ustr[len] == 0)
                        return len << 1;
        }
        cFYI(1,("Unicode string longer than PATH_MAX found"));
@@ -510,7 +509,7 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
        char * new_entry;
        FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
 
-       if(level == SMB_FIND_FILE_INFO_STANDARD) {
+       if (level == SMB_FIND_FILE_INFO_STANDARD) {
                FIND_FILE_STANDARD_INFO * pfData;
                pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
 
@@ -520,12 +519,12 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
                new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
        cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
        /* validate that new_entry is not past end of SMB */
-       if(new_entry >= end_of_smb) {
+       if (new_entry >= end_of_smb) {
                cERROR(1,
                      ("search entry %p began after end of SMB %p old entry %p",
                        new_entry, end_of_smb, old_entry)); 
                return NULL;
-       } else if(((level == SMB_FIND_FILE_INFO_STANDARD) &&
+       } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
                   (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
                  ((level != SMB_FIND_FILE_INFO_STANDARD) &&
                   (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb)))  {
@@ -546,39 +545,39 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
        char * filename = NULL;
        int len = 0; 
 
-       if(cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
+       if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
                FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
                filename = &pFindData->FileName[0];
-               if(cfile->srch_inf.unicode) {
+               if (cfile->srch_inf.unicode) {
                        len = cifs_unicode_bytelen(filename);
                } else {
                        /* BB should we make this strnlen of PATH_MAX? */
                        len = strnlen(filename, 5);
                }
-       } else if(cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
+       } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
                FILE_DIRECTORY_INFO * pFindData = 
                        (FILE_DIRECTORY_INFO *)current_entry;
                filename = &pFindData->FileName[0];
                len = le32_to_cpu(pFindData->FileNameLength);
-       } else if(cfile->srch_inf.info_level == 
+       } else if (cfile->srch_inf.info_level == 
                        SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
                FILE_FULL_DIRECTORY_INFO * pFindData = 
                        (FILE_FULL_DIRECTORY_INFO *)current_entry;
                filename = &pFindData->FileName[0];
                len = le32_to_cpu(pFindData->FileNameLength);
-       } else if(cfile->srch_inf.info_level ==
+       } else if (cfile->srch_inf.info_level ==
                        SMB_FIND_FILE_ID_FULL_DIR_INFO) {
                SEARCH_ID_FULL_DIR_INFO * pFindData = 
                        (SEARCH_ID_FULL_DIR_INFO *)current_entry;
                filename = &pFindData->FileName[0];
                len = le32_to_cpu(pFindData->FileNameLength);
-       } else if(cfile->srch_inf.info_level == 
+       } else if (cfile->srch_inf.info_level == 
                        SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
                FILE_BOTH_DIRECTORY_INFO * pFindData = 
                        (FILE_BOTH_DIRECTORY_INFO *)current_entry;
                filename = &pFindData->FileName[0];
                len = le32_to_cpu(pFindData->FileNameLength);
-       } else if(cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
+       } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
                FIND_FILE_STANDARD_INFO * pFindData =
                        (FIND_FILE_STANDARD_INFO *)current_entry;
                filename = &pFindData->FileName[0];
@@ -587,25 +586,25 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
                cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
        }
 
-       if(filename) {
-               if(cfile->srch_inf.unicode) {
+       if (filename) {
+               if (cfile->srch_inf.unicode) {
                        __le16 *ufilename = (__le16 *)filename;
-                       if(len == 2) {
+                       if (len == 2) {
                                /* check for . */
-                               if(ufilename[0] == UNICODE_DOT)
+                               if (ufilename[0] == UNICODE_DOT)
                                        rc = 1;
-                       } else if(len == 4) {
+                       } else if (len == 4) {
                                /* check for .. */
-                               if((ufilename[0] == UNICODE_DOT)
+                               if ((ufilename[0] == UNICODE_DOT)
                                   &&(ufilename[1] == UNICODE_DOT))
                                        rc = 2;
                        }
                } else /* ASCII */ {
-                       if(len == 1) {
-                               if(filename[0] == '.') 
+                       if (len == 1) {
+                               if (filename[0] == '.') 
                                        rc = 1;
-                       } else if(len == 2) {
-                               if((filename[0] == '.') && (filename[1] == '.')) 
+                       } else if (len == 2) {
+                               if((filename[0] == '.') && (filename[1] == '.'))
                                        rc = 2;
                        }
                }
@@ -618,20 +617,10 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
    whether we can use the cached search results from the previous search */
 static int is_dir_changed(struct file * file)
 {
-       struct inode * inode;
-       struct cifsInodeInfo *cifsInfo;
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
 
-       if(file->f_path.dentry == NULL)
-               return 0;
-
-       inode = file->f_path.dentry->d_inode;
-
-       if(inode == NULL)
-               return 0;
-
-       cifsInfo = CIFS_I(inode);
-
-       if(cifsInfo->time == 0)
+       if (cifsInfo->time == 0)
                return 1; /* directory was changed, perhaps due to unlink */
        else
                return 0;
@@ -654,7 +643,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
        struct cifsFileInfo * cifsFile = file->private_data;
        /* check if index in the buffer */
        
-       if((cifsFile == NULL) || (ppCurrentEntry == NULL) || 
+       if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || 
           (num_to_ret == NULL))
                return -ENOENT;
        
@@ -672,7 +661,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
 #ifdef CONFIG_CIFS_DEBUG2
        dump_cifs_file_struct(file, "In fce ");
 #endif
-       if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 
+       if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 
             is_dir_changed(file)) || 
           (index_to_find < first_entry_in_buffer)) {
                /* close and restart search */
@@ -681,9 +670,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
                CIFSFindClose(xid, pTcon, cifsFile->netfid);
                kfree(cifsFile->search_resume_name);
                cifsFile->search_resume_name = NULL;
-               if(cifsFile->srch_inf.ntwrk_buf_start) {
+               if (cifsFile->srch_inf.ntwrk_buf_start) {
                        cFYI(1,("freeing SMB ff cache buf on search rewind"));
-                       if(cifsFile->srch_inf.smallBuf)
+                       if (cifsFile->srch_inf.smallBuf)
                                cifs_small_buf_release(cifsFile->srch_inf.
                                                ntwrk_buf_start);
                        else
@@ -691,7 +680,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
                                                ntwrk_buf_start);
                }
                rc = initiate_cifs_search(xid,file);
-               if(rc) {
+               if (rc) {
                        cFYI(1,("error %d reinitiating a search on rewind",rc));
                        return rc;
                }
@@ -702,10 +691,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
                cFYI(1,("calling findnext2"));
                rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, 
                                  &cifsFile->srch_inf);
-               if(rc)
+               if (rc)
                        return -ENOENT;
        }
-       if(index_to_find < cifsFile->srch_inf.index_of_last_entry) {
+       if (index_to_find < cifsFile->srch_inf.index_of_last_entry) {
                /* we found the buffer that contains the entry */
                /* scan and find it */
                int i;
@@ -851,9 +840,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
        if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
                return -ENOENT;
 
-       if(file->f_path.dentry == NULL)
-               return -ENOENT;
-
        rc = cifs_entry_is_dot(pfindEntry,pCifsF);
        /* skip . and .. since we added them first */
        if(rc != 0) 
@@ -997,11 +983,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 
        xid = GetXid();
 
-       if(file->f_path.dentry == NULL) {
-               FreeXid(xid);
-               return -EIO;
-       }
-
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
        if(pTcon == NULL)
index 040a8be..72e5e69 100644 (file)
@@ -371,13 +371,14 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd,
                        fn = "?";
        }
 
-       sprintf(buf,"'%c'", (cmd>>24) & 0x3f);
+       sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);
        if (!isprint(buf[1]))
                sprintf(buf, "%02x", buf[1]);
        compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
-                       "cmd(%08x){%s} arg(%08x) on %s\n",
+                       "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n",
                        current->comm, current->pid,
                        (int)fd, (unsigned int)cmd, buf,
+                       (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK,
                        (unsigned int)arg, fn);
 
        if (path)
index c68b055..464c04a 100644 (file)
@@ -2396,6 +2396,14 @@ lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 #define ULONG_IOCTL(cmd) \
        { (cmd), (ioctl_trans_handler_t)sys_ioctl },
 
+/* ioctl should not be warned about even if it's not implemented.
+   Valid reasons to use this:
+   - It is implemented with ->compat_ioctl on some device, but programs
+   call it on others too.
+   - The ioctl is not implemented in the native kernel, but programs
+   call it commonly anyways.
+   Most other reasons are not valid. */
+#define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd)
 
 struct ioctl_trans ioctl_start[] = {
 #include <linux/compat_ioctl.h>
@@ -2594,6 +2602,8 @@ HANDLE_IOCTL(SIOCGIWENCODEEXT, do_wireless_ioctl)
 HANDLE_IOCTL(SIOCSIWPMKSA, do_wireless_ioctl)
 HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
 HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
+/* Not implemented in the native kernel */
+IGNORE_IOCTL(SIOCGIFCOUNT)
 HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl)
 HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl)
 HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl)
@@ -2617,6 +2627,15 @@ COMPATIBLE_IOCTL(LPRESET)
 /*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/
 COMPATIBLE_IOCTL(LPGETFLAGS)
 HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans)
+
+/* fat 'r' ioctls. These are handled by fat with ->compat_ioctl,
+   but we don't want warnings on other file systems. So declare
+   them as compatible here. */
+#define VFAT_IOCTL_READDIR_BOTH32       _IOR('r', 1, struct compat_dirent[2])
+#define VFAT_IOCTL_READDIR_SHORT32      _IOR('r', 2, struct compat_dirent[2])
+
+IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
+IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
 };
 
 int ioctl_table_size = ARRAY_SIZE(ioctl_start);
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,123 +218,150 @@ 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
@@ -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 d960507..523e109 100644 (file)
@@ -514,7 +514,7 @@ static int __init parse_crash_elf64_headers(void)
        /* Do some basic Verification. */
        if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
                (ehdr.e_type != ET_CORE) ||
-               !elf_check_arch(&ehdr) ||
+               !vmcore_elf_check_arch(&ehdr) ||
                ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
                ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
                ehdr.e_version != EV_CURRENT ||
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 fe249e9..0bd7bd2 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/system.h>
 #include <asm/machvec.h>
 #include <asm/compiler.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * Force a context reload. This is needed when we change the page
index 651ebb1..48348fe 100644 (file)
@@ -1,20 +1,6 @@
 #ifndef __ALPHA_PERCPU_H
 #define __ALPHA_PERCPU_H
 
-/*
- * Increase the per cpu area for Alpha so that
- * modules using percpu area can load.
- */
-#ifdef CONFIG_MODULES
-# define PERCPU_MODULE_RESERVE 8192
-#else
-# define PERCPU_MODULE_RESERVE 0
-#endif
-
-#define PERCPU_ENOUGH_ROOM \
-       (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
-        PERCPU_MODULE_RESERVE)
-
 #include <asm-generic/percpu.h>
 
 #endif /* __ALPHA_PERCPU_H */
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;
diff --git a/include/asm-arm/arch-at91/at91_adc.h b/include/asm-arm/arch-at91/at91_adc.h
new file mode 100644 (file)
index 0000000..1ed66ea
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * include/asm-arm/arch-at91/at91_adc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Analog-to-Digital Converter (ADC) registers.
+ * Based on AT91SAM9260 datasheet revision D.
+ *
+ * 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 AT91_ADC_H
+#define AT91_ADC_H
+
+#define AT91_ADC_CR            0x00            /* Control Register */
+#define                AT91_ADC_SWRST          (1 << 0)        /* Software Reset */
+#define                AT91_ADC_START          (1 << 1)        /* Start Conversion */
+
+#define AT91_ADC_MR            0x04            /* Mode Register */
+#define                AT91_ADC_TRGEN          (1 << 0)        /* Trigger Enable */
+#define                AT91_ADC_TRGSEL         (7 << 1)        /* Trigger Selection */
+#define                        AT91_ADC_TRGSEL_TC0             (0 << 1)
+#define                        AT91_ADC_TRGSEL_TC1             (1 << 1)
+#define                        AT91_ADC_TRGSEL_TC2             (2 << 1)
+#define                        AT91_ADC_TRGSEL_EXTERNAL        (6 << 1)
+#define                AT91_ADC_LOWRES         (1 << 4)        /* Low Resolution */
+#define                AT91_ADC_SLEEP          (1 << 5)        /* Sleep Mode */
+#define                AT91_ADC_PRESCAL        (0x3f << 8)     /* Prescalar Rate Selection */
+#define                        AT91_ADC_PRESCAL_(x)    ((x) << 8)
+#define                AT91_ADC_STARTUP        (0x1f << 16)    /* Startup Up Time */
+#define                        AT91_ADC_STARTUP_(x)    ((x) << 16)
+#define                AT91_ADC_SHTIM          (0xf  << 24)    /* Sample & Hold Time */
+#define                        AT91_ADC_SHTIM_(x)      ((x) << 24)
+
+#define AT91_ADC_CHER          0x10            /* Channel Enable Register */
+#define AT91_ADC_CHDR          0x14            /* Channel Disable Register */
+#define AT91_ADC_CHSR          0x18            /* Channel Status Register */
+#define                AT91_ADC_CH(n)          (1 << (n))      /* Channel Number */
+
+#define AT91_ADC_SR            0x1C            /* Status Register */
+#define                AT91_ADC_EOC(n)         (1 << (n))      /* End of Conversion on Channel N */
+#define                AT91_ADC_OVRE(n)        (1 << ((n) + 8))/* Overrun Error on Channel N */
+#define                AT91_ADC_DRDY           (1 << 16)       /* Data Ready */
+#define                AT91_ADC_GOVRE          (1 << 17)       /* General Overrun Error */
+#define                AT91_ADC_ENDRX          (1 << 18)       /* End of RX Buffer */
+#define                AT91_ADC_RXFUFF         (1 << 19)       /* RX Buffer Full */
+
+#define AT91_ADC_LCDR          0x20            /* Last Converted Data Register */
+#define                AT91_ADC_LDATA          (0x3ff)
+
+#define AT91_ADC_IER           0x24            /* Interrupt Enable Register */
+#define AT91_ADC_IDR           0x28            /* Interrupt Disable Register */
+#define AT91_ADC_IMR           0x2C            /* Interrupt Mask Register */
+
+#define AT91_ADC_CHR(n)                (0x30 + ((n) * 4)       /* Channel Data Register N */
+#define                AT91_ADC_DATA           (0x3ff)
+
+#endif
index 7b9903c..7a34a5b 100644 (file)
@@ -62,7 +62,7 @@ struct at91_mmc_data {
 };
 extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
 
- /* Ethernet */
+ /* Ethernet (EMAC & MACB) */
 struct at91_eth_data {
        u8              phy_irq_pin;    /* PHY IRQ */
        u8              is_rmii;        /* using RMII interface? */
@@ -114,6 +114,16 @@ struct atmel_uart_data {
 };
 extern void __init at91_add_device_serial(void);
 
+ /* LCD Controller */
+struct atmel_lcdfb_info;
+extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
+
+ /* AC97 */
+struct atmel_ac97_data {
+       u8              reset_pin;      /* reset */
+}
+extern void __init at91_add_device_ac97(struct atmel_ac97_data *data);
+
  /* LEDs */
 extern u8 at91_leds_cpu;
 extern u8 at91_leds_timer;
index 722c5e0..44a4001 100644 (file)
@@ -81,4 +81,12 @@ extern void outsb(unsigned int port, const void *buf, int sz);
 extern void outsw(unsigned int port, const void *buf, int sz);
 extern void outsl(unsigned int port, const void *buf, int sz);
 
+/* can't support writesb atm */
+extern void writesw(void __iomem *addr, const void *data, int wordlen);
+extern void writesl(void __iomem *addr, const void *data, int longlen);
+
+/* can't support readsb atm */
+extern void readsw(const void __iomem *addr, void *data, int wordlen);
+extern void readsl(const void __iomem *addr, void *data, int longlen);
+
 #endif
index e56a4e2..de6494a 100644 (file)
 #define LCDISR_EOF     (1<<1)
 #define LCDISR_BOF     (1<<0)
 
-/*
- *  UART Module. Takes the UART base address as argument
- */
-#define URXD0(x) __REG( 0x0 + (x)) /* Receiver Register */
-#define URTX0(x) __REG( 0x40 + (x)) /* Transmitter Register */
-#define UCR1(x)  __REG( 0x80 + (x)) /* Control Register 1 */
-#define UCR2(x)  __REG( 0x84 + (x)) /* Control Register 2 */
-#define UCR3(x)  __REG( 0x88 + (x)) /* Control Register 3 */
-#define UCR4(x)  __REG( 0x8c + (x)) /* Control Register 4 */
-#define UFCR(x)  __REG( 0x90 + (x)) /* FIFO Control Register */
-#define USR1(x)  __REG( 0x94 + (x)) /* Status Register 1 */
-#define USR2(x)  __REG( 0x98 + (x)) /* Status Register 2 */
-#define UESC(x)  __REG( 0x9c + (x)) /* Escape Character Register */
-#define UTIM(x)  __REG( 0xa0 + (x)) /* Escape Timer Register */
-#define UBIR(x)  __REG( 0xa4 + (x)) /* BRM Incremental Register */
-#define UBMR(x)  __REG( 0xa8 + (x)) /* BRM Modulator Register */
-#define UBRC(x)  __REG( 0xac + (x)) /* Baud Rate Count Register */
-#define BIPR1(x) __REG( 0xb0 + (x)) /* Incremental Preset Register 1 */
-#define BIPR2(x) __REG( 0xb4 + (x)) /* Incremental Preset Register 2 */
-#define BIPR3(x) __REG( 0xb8 + (x)) /* Incremental Preset Register 3 */
-#define BIPR4(x) __REG( 0xbc + (x)) /* Incremental Preset Register 4 */
-#define BMPR1(x) __REG( 0xc0 + (x)) /* BRM Modulator Register 1 */
-#define BMPR2(x) __REG( 0xc4 + (x)) /* BRM Modulator Register 2 */
-#define BMPR3(x) __REG( 0xc8 + (x)) /* BRM Modulator Register 3 */
-#define BMPR4(x) __REG( 0xcc + (x)) /* BRM Modulator Register 4 */
-#define UTS(x)   __REG( 0xd0 + (x)) /* UART Test Register */
-
-/* UART Control Register Bit Fields.*/
-#define  URXD_CHARRDY    (1<<15)
-#define  URXD_ERR        (1<<14)
-#define  URXD_OVRRUN     (1<<13)
-#define  URXD_FRMERR     (1<<12)
-#define  URXD_BRK        (1<<11)
-#define  URXD_PRERR      (1<<10)
-#define  UCR1_ADEN       (1<<15) /* Auto dectect interrupt */
-#define  UCR1_ADBR       (1<<14) /* Auto detect baud rate */
-#define  UCR1_TRDYEN     (1<<13) /* Transmitter ready interrupt enable */
-#define  UCR1_IDEN       (1<<12) /* Idle condition interrupt */
-#define  UCR1_RRDYEN     (1<<9)         /* Recv ready interrupt enable */
-#define  UCR1_RDMAEN     (1<<8)         /* Recv ready DMA enable */
-#define  UCR1_IREN       (1<<7)         /* Infrared interface enable */
-#define  UCR1_TXMPTYEN   (1<<6)         /* Transimitter empty interrupt enable */
-#define  UCR1_RTSDEN     (1<<5)         /* RTS delta interrupt enable */
-#define  UCR1_SNDBRK     (1<<4)         /* Send break */
-#define  UCR1_TDMAEN     (1<<3)         /* Transmitter ready DMA enable */
-#define  UCR1_UARTCLKEN  (1<<2)         /* UART clock enabled */
-#define  UCR1_DOZE       (1<<1)         /* Doze */
-#define  UCR1_UARTEN     (1<<0)         /* UART enabled */
-#define  UCR2_ESCI              (1<<15) /* Escape seq interrupt enable */
-#define  UCR2_IRTS      (1<<14) /* Ignore RTS pin */
-#define  UCR2_CTSC      (1<<13) /* CTS pin control */
-#define  UCR2_CTS        (1<<12) /* Clear to send */
-#define  UCR2_ESCEN      (1<<11) /* Escape enable */
-#define  UCR2_PREN       (1<<8)  /* Parity enable */
-#define  UCR2_PROE       (1<<7)  /* Parity odd/even */
-#define  UCR2_STPB       (1<<6)         /* Stop */
-#define  UCR2_WS         (1<<5)         /* Word size */
-#define  UCR2_RTSEN      (1<<4)         /* Request to send interrupt enable */
-#define  UCR2_TXEN       (1<<2)         /* Transmitter enabled */
-#define  UCR2_RXEN       (1<<1)         /* Receiver enabled */
-#define  UCR2_SRST      (1<<0)  /* SW reset */
-#define  UCR3_DTREN     (1<<13) /* DTR interrupt enable */
-#define  UCR3_PARERREN   (1<<12) /* Parity enable */
-#define  UCR3_FRAERREN   (1<<11) /* Frame error interrupt enable */
-#define  UCR3_DSR        (1<<10) /* Data set ready */
-#define  UCR3_DCD        (1<<9)  /* Data carrier detect */
-#define  UCR3_RI         (1<<8)  /* Ring indicator */
-#define  UCR3_TIMEOUTEN  (1<<7)  /* Timeout interrupt enable */
-#define  UCR3_RXDSEN    (1<<6)  /* Receive status interrupt enable */
-#define  UCR3_AIRINTEN   (1<<5)  /* Async IR wake interrupt enable */
-#define  UCR3_AWAKEN    (1<<4)  /* Async wake interrupt enable */
-#define  UCR3_REF25     (1<<3)  /* Ref freq 25 MHz */
-#define  UCR3_REF30     (1<<2)  /* Ref Freq 30 MHz */
-#define  UCR3_INVT      (1<<1)  /* Inverted Infrared transmission */
-#define  UCR3_BPEN      (1<<0)  /* Preset registers enable */
-#define  UCR4_CTSTL_32   (32<<10) /* CTS trigger level (32 chars) */
-#define  UCR4_INVR      (1<<9)  /* Inverted infrared reception */
-#define  UCR4_ENIRI     (1<<8)  /* Serial infrared interrupt enable */
-#define  UCR4_WKEN      (1<<7)  /* Wake interrupt enable */
-#define  UCR4_REF16     (1<<6)  /* Ref freq 16 MHz */
-#define  UCR4_IRSC      (1<<5)  /* IR special case */
-#define  UCR4_TCEN      (1<<3)  /* Transmit complete interrupt enable */
-#define  UCR4_BKEN      (1<<2)  /* Break condition interrupt enable */
-#define  UCR4_OREN      (1<<1)  /* Receiver overrun interrupt enable */
-#define  UCR4_DREN      (1<<0)  /* Recv data ready interrupt enable */
-#define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
-#define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
-#define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
-#define  USR1_PARITYERR  (1<<15) /* Parity error interrupt flag */
-#define  USR1_RTSS      (1<<14) /* RTS pin status */
-#define  USR1_TRDY      (1<<13) /* Transmitter ready interrupt/dma flag */
-#define  USR1_RTSD      (1<<12) /* RTS delta */
-#define  USR1_ESCF      (1<<11) /* Escape seq interrupt flag */
-#define  USR1_FRAMERR    (1<<10) /* Frame error interrupt flag */
-#define  USR1_RRDY       (1<<9)         /* Receiver ready interrupt/dma flag */
-#define  USR1_TIMEOUT    (1<<7)         /* Receive timeout interrupt status */
-#define  USR1_RXDS      (1<<6)  /* Receiver idle interrupt flag */
-#define  USR1_AIRINT    (1<<5)  /* Async IR wake interrupt flag */
-#define  USR1_AWAKE     (1<<4)  /* Aysnc wake interrupt flag */
-#define  USR2_ADET      (1<<15) /* Auto baud rate detect complete */
-#define  USR2_TXFE      (1<<14) /* Transmit buffer FIFO empty */
-#define  USR2_DTRF      (1<<13) /* DTR edge interrupt flag */
-#define  USR2_IDLE      (1<<12) /* Idle condition */
-#define  USR2_IRINT     (1<<8)  /* Serial infrared interrupt flag */
-#define  USR2_WAKE      (1<<7)  /* Wake */
-#define  USR2_RTSF      (1<<4)  /* RTS edge interrupt flag */
-#define  USR2_TXDC      (1<<3)  /* Transmitter complete */
-#define  USR2_BRCD      (1<<2)  /* Break condition */
-#define  USR2_ORE        (1<<1)         /* Overrun error */
-#define  USR2_RDR        (1<<0)         /* Recv data ready */
-#define  UTS_FRCPERR    (1<<13) /* Force parity error */
-#define  UTS_LOOP        (1<<12) /* Loop tx and rx */
-#define  UTS_TXEMPTY    (1<<6)  /* TxFIFO empty */
-#define  UTS_RXEMPTY    (1<<5)  /* RxFIFO empty */
-#define  UTS_TXFULL     (1<<4)  /* TxFIFO full */
-#define  UTS_RXFULL     (1<<3)  /* RxFIFO full */
-#define  UTS_SOFTRST    (1<<0)  /* Software reset */
-
 #endif                         // _IMX_REGS_H
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 5a7bdb5..7dfff4a 100644 (file)
@@ -26,7 +26,6 @@
 #define __mem_isa(a) (a)
 
 extern void __iomem * __iop13xx_io(unsigned long io_addr);
-extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
 extern void __iomem *__iop13xx_ioremap(unsigned long cookie, size_t size,
        unsigned long flags);
 extern void __iop13xx_iounmap(void __iomem *addr);
index d26b755..85707e9 100644 (file)
@@ -8,6 +8,7 @@ extern u32 iop13xx_atue_pmmr_offset;
 void iop13xx_init_irq(void);
 void iop13xx_map_io(void);
 void iop13xx_platform_init(void);
+void iop13xx_add_tpmi_devices(void);
 void iop13xx_init_irq(void);
 
 /* CPUID CP6 R0 Page 0 */
@@ -27,19 +28,24 @@ static inline int iop13xx_cpu_id(void)
 #define IOP13XX_PCI_OFFSET      IOP13XX_MAX_RAM_SIZE
 
 /* PCI MAP
- * 0x0000.0000 - 0x8000.0000           1:1 mapping with Physical RAM
- * 0x8000.0000 - 0x8800.0000           PCIX/PCIE memory window (128MB)
-*/
+ * bus range           cpu phys        cpu virt        note
+ * 0x0000.0000 + 2GB   (n/a)           (n/a)           inbound, 1:1 mapping with Physical RAM
+ * 0x8000.0000 + 928M  0x1.8000.0000   (ioremap)       PCIX outbound memory window
+ * 0x8000.0000 + 928M  0x2.8000.0000   (ioremap)       PCIE outbound memory window
+ *
+ * IO MAP
+ * 0x1000 + 64K        0x0.fffb.1000   0xfec6.1000     PCIX outbound i/o window
+ * 0x1000 + 64K        0x0.fffd.1000   0xfed7.1000     PCIE outbound i/o window
+ */
 #define IOP13XX_PCIX_IO_WINDOW_SIZE   0x10000UL
 #define IOP13XX_PCIX_LOWER_IO_PA      0xfffb0000UL
 #define IOP13XX_PCIX_LOWER_IO_VA      0xfec60000UL
-#define IOP13XX_PCIX_LOWER_IO_BA      0x0fff0000UL
+#define IOP13XX_PCIX_LOWER_IO_BA      0x0UL /* OIOTVR */
+#define IOP13XX_PCIX_IO_BUS_OFFSET    0x1000UL
 #define IOP13XX_PCIX_UPPER_IO_PA      (IOP13XX_PCIX_LOWER_IO_PA +\
                                       IOP13XX_PCIX_IO_WINDOW_SIZE - 1)
 #define IOP13XX_PCIX_UPPER_IO_VA      (IOP13XX_PCIX_LOWER_IO_VA +\
                                       IOP13XX_PCIX_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIX_IO_OFFSET        (IOP13XX_PCIX_LOWER_IO_VA -\
-                                      IOP13XX_PCIX_LOWER_IO_BA)
 #define IOP13XX_PCIX_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
                                           (IOP13XX_PCIX_LOWER_IO_PA\
                                           - IOP13XX_PCIX_LOWER_IO_VA))
@@ -65,15 +71,14 @@ static inline int iop13xx_cpu_id(void)
 #define IOP13XX_PCIE_IO_WINDOW_SIZE     0x10000UL
 #define IOP13XX_PCIE_LOWER_IO_PA        0xfffd0000UL
 #define IOP13XX_PCIE_LOWER_IO_VA        0xfed70000UL
-#define IOP13XX_PCIE_LOWER_IO_BA        0x0fff0000UL
+#define IOP13XX_PCIE_LOWER_IO_BA        0x0UL  /* OIOTVR */
+#define IOP13XX_PCIE_IO_BUS_OFFSET      0x1000UL
 #define IOP13XX_PCIE_UPPER_IO_PA        (IOP13XX_PCIE_LOWER_IO_PA +\
                                         IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
 #define IOP13XX_PCIE_UPPER_IO_VA        (IOP13XX_PCIE_LOWER_IO_VA +\
                                         IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
 #define IOP13XX_PCIE_UPPER_IO_BA        (IOP13XX_PCIE_LOWER_IO_BA +\
                                         IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIE_IO_OFFSET          (IOP13XX_PCIE_LOWER_IO_VA -\
-                                        IOP13XX_PCIE_LOWER_IO_BA)
 #define IOP13XX_PCIE_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
                                           (IOP13XX_PCIE_LOWER_IO_PA\
                                           - IOP13XX_PCIE_LOWER_IO_VA))
@@ -451,4 +456,5 @@ static inline int iop13xx_cpu_id(void)
 #define IOP13XX_PBI_BAR1               IOP13XX_PBI_OFFSET(0x10)
 #define IOP13XX_PBI_LR1                IOP13XX_PBI_OFFSET(0x14)
 
+#define IOP13XX_PROCESSOR_FREQ         IOP13XX_REG_ADDR32(0x2180)
 #endif /* _IOP13XX_HW_H_ */
index 77a837a..49213d9 100644 (file)
@@ -7,9 +7,65 @@
 #define IOP_TMR_PRIVILEGED 0x08
 #define IOP_TMR_RATIO_1_1  0x00
 
+#define IOP13XX_XSI_FREQ_RATIO_MASK    (3 << 19)
+#define IOP13XX_XSI_FREQ_RATIO_2       (0 << 19)
+#define IOP13XX_XSI_FREQ_RATIO_3       (1 << 19)
+#define IOP13XX_XSI_FREQ_RATIO_4       (2 << 19)
+#define IOP13XX_CORE_FREQ_MASK         (7 << 16)
+#define IOP13XX_CORE_FREQ_600          (0 << 16)
+#define IOP13XX_CORE_FREQ_667          (1 << 16)
+#define IOP13XX_CORE_FREQ_800          (2 << 16)
+#define IOP13XX_CORE_FREQ_933          (3 << 16)
+#define IOP13XX_CORE_FREQ_1000         (4 << 16)
+#define IOP13XX_CORE_FREQ_1200         (5 << 16)
+
 void iop_init_time(unsigned long tickrate);
 unsigned long iop_gettimeoffset(void);
 
+static inline unsigned long iop13xx_core_freq(void)
+{
+       unsigned long freq = __raw_readl(IOP13XX_PROCESSOR_FREQ);
+       freq &= IOP13XX_CORE_FREQ_MASK;
+       switch (freq) {
+       case IOP13XX_CORE_FREQ_600:
+               return 600000000;
+       case IOP13XX_CORE_FREQ_667:
+               return 667000000;
+       case IOP13XX_CORE_FREQ_800:
+               return 800000000;
+       case IOP13XX_CORE_FREQ_933:
+               return 933000000;
+       case IOP13XX_CORE_FREQ_1000:
+               return 1000000000;
+       case IOP13XX_CORE_FREQ_1200:
+               return 1200000000;
+       default:
+               printk("%s: warning unknown frequency, defaulting to 800Mhz\n",
+                       __FUNCTION__);
+       }
+
+       return 800000000;
+}
+
+static inline unsigned long iop13xx_xsi_bus_ratio(void)
+{
+       unsigned long  ratio = __raw_readl(IOP13XX_PROCESSOR_FREQ);
+       ratio &= IOP13XX_XSI_FREQ_RATIO_MASK;
+       switch (ratio) {
+       case IOP13XX_XSI_FREQ_RATIO_2:
+               return 2;
+       case IOP13XX_XSI_FREQ_RATIO_3:
+               return 3;
+       case IOP13XX_XSI_FREQ_RATIO_4:
+               return 4;
+       default:
+               printk("%s: warning unknown ratio, defaulting to 2\n",
+                       __FUNCTION__);
+       }
+
+       return 2;
+}
+
 static inline void write_tmr0(u32 val)
 {
        asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (val));
index 5f570a5..994f16a 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/hardware.h>
 
-extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
 extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
        unsigned long flags);
 extern void __iop3xx_iounmap(void __iomem *addr);
index 2e94690..0d8af57 100644 (file)
 
 #include <asm/hardware/iop3xx.h>
 
+/* ATU Parameters
+ * set up a 1:1 bus to physical ram relationship
+ * w/ physical ram on top of pci in the memory map
+ */
+#define IOP32X_MAX_RAM_SIZE            0x40000000UL
+#define IOP3XX_MAX_RAM_SIZE            IOP32X_MAX_RAM_SIZE
+#define IOP3XX_PCI_LOWER_MEM_BA        0x80000000
+#define IOP32X_PCI_MEM_WINDOW_SIZE     0x04000000
+#define IOP3XX_PCI_MEM_WINDOW_SIZE     IOP32X_PCI_MEM_WINDOW_SIZE
 
 #endif
index 764cd3f..c51072a 100644 (file)
@@ -19,8 +19,8 @@
  * bus_to_virt: Used to convert an address for DMA operations
  *             to an address that the kernel can use.
  */
-#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)       (__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+#define __virt_to_bus(x)       (__virt_to_phys(x))
+#define __bus_to_virt(x)       (__phys_to_virt(x))
 
 
 #endif
index 1bb5071..993f758 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/hardware.h>
 
-extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
 extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
        unsigned long flags);
 extern void __iop3xx_iounmap(void __iomem *addr);
index 7ac6e93..766985b 100644 (file)
 #define IOP33X_UART1_PHYS      (IOP3XX_PERIPHERAL_PHYS_BASE + 0x1740)
 #define IOP33X_UART1_VIRT      (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1740)
 
+/* ATU Parameters
+ * set up a 1:1 bus to physical ram relationship
+ * w/ pci on top of physical ram in memory map
+ */
+#define IOP33X_MAX_RAM_SIZE            0x80000000UL
+#define IOP3XX_MAX_RAM_SIZE            IOP33X_MAX_RAM_SIZE
+#define IOP3XX_PCI_LOWER_MEM_BA        (PHYS_OFFSET + IOP33X_MAX_RAM_SIZE)
+#define IOP33X_PCI_MEM_WINDOW_SIZE     0x08000000
+#define IOP3XX_PCI_MEM_WINDOW_SIZE     IOP33X_PCI_MEM_WINDOW_SIZE
+
 
 #endif
index 0d39139..c874912 100644 (file)
@@ -19,8 +19,8 @@
  * bus_to_virt: Used to convert an address for DMA operations
  *             to an address that the kernel can use.
  */
-#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)       (__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+#define __virt_to_bus(x)       (__virt_to_phys(x))
+#define __bus_to_virt(x)       (__phys_to_virt(x))
 
 
 #endif
index 18415a8..66f5baf 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/kernel.h>      /* For BUG */
 
 static inline void __iomem *
-ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned long flags)
+ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned int mtype)
 {
        if (addr >= IXP23XX_PCI_MEM_START &&
                addr <= IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE) {
@@ -34,7 +34,7 @@ ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned long flags)
                        ((addr - IXP23XX_PCI_MEM_START) + IXP23XX_PCI_MEM_VIRT);
        }
 
-       return __ioremap(addr, size, flags);
+       return __arm_ioremap(addr, size, mtype);
 }
 
 static inline void
diff --git a/include/asm-arm/arch-ixp4xx/cpu.h b/include/asm-arm/arch-ixp4xx/cpu.h
new file mode 100644 (file)
index 0000000..d2523b3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * include/asm-arm/arch-ixp4xx/cpu.h
+ *
+ * IXP4XX cpu type detection
+ *
+ * Copyright (C) 2007 MontaVista 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 __ASM_ARCH_CPU_H__
+#define __ASM_ARCH_CPU_H__
+
+extern unsigned int processor_id;
+/* Processor id value in CP15 Register 0 */
+#define IXP425_PROCESSOR_ID_VALUE      0x690541c0
+#define IXP435_PROCESSOR_ID_VALUE      0x69054040
+#define IXP465_PROCESSOR_ID_VALUE      0x69054200
+#define IXP4XX_PROCESSOR_ID_MASK       0xfffffff0
+
+#define cpu_is_ixp42x()        ((processor_id & IXP4XX_PROCESSOR_ID_MASK) == \
+                         IXP425_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp43x()        ((processor_id & IXP4XX_PROCESSOR_ID_MASK) == \
+                         IXP435_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp46x()        ((processor_id & IXP4XX_PROCESSOR_ID_MASK) == \
+                         IXP465_PROCESSOR_ID_VALUE)
+
+#endif  /* _ASM_ARCH_CPU_H */
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>
diff --git a/include/asm-arm/arch-ixp4xx/dsmg600.h b/include/asm-arm/arch-ixp4xx/dsmg600.h
new file mode 100644 (file)
index 0000000..a19605a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * DSM-G600 platform specific definitions
+ *
+ * Copyright (C) 2006 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on ixdp425.h:
+ *     Copyright 2004 (C) MontaVista, Software, Inc.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
+#define DSMG600_SDA_PIN                5
+#define DSMG600_SCL_PIN                4
+
+/*
+ * DSMG600 PCI IRQs
+ */
+#define DSMG600_PCI_MAX_DEV    4
+#define DSMG600_PCI_IRQ_LINES  3
+
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define DSMG600_PCI_INTA_PIN   11
+#define DSMG600_PCI_INTB_PIN   10
+#define DSMG600_PCI_INTC_PIN   9
+#define DSMG600_PCI_INTD_PIN   8
+#define DSMG600_PCI_INTE_PIN   7
+#define DSMG600_PCI_INTF_PIN   6
+
+/* DSM-G600 Timer Setting */
+#define DSMG600_FREQ 66000000
+
+/* Buttons */
+
+#define DSMG600_PB_GPIO                15      /* power button */
+#define DSMG600_PB_BM          (1L << DSMG600_PB_GPIO)
+
+#define DSMG600_RB_GPIO                3       /* reset button */
+
+#define DSMG600_RB_IRQ         IRQ_IXP4XX_GPIO3
+
+#define DSMG600_PO_GPIO                2       /* power off */
+
+/* LEDs */
+
+#define DSMG600_LED_PWR_GPIO   0
+#define DSMG600_LED_PWR_BM     (1L << DSMG600_LED_PWR_GPIO)
+
+#define DSMG600_LED_WLAN_GPIO  14
+#define DSMG600_LED_WLAN_BM    (1L << DSMG600_LED_WLAN_GPIO)
index dadb568..f144a00 100644 (file)
@@ -31,9 +31,9 @@
 
 1001:
                /*
-                * IXP465 has an upper IRQ status register
+                * IXP465/IXP435 has an upper IRQ status register
                 */
-#if defined(CONFIG_CPU_IXP46X)
+#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
                ldr     \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP2_OFFSET)
                ldr     \irqstat, [\irqstat]            @ get upper interrupts
                mov     \irqnr, #63
diff --git a/include/asm-arm/arch-ixp4xx/gpio.h b/include/asm-arm/arch-ixp4xx/gpio.h
new file mode 100644 (file)
index 0000000..3a4c5b8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * linux/include/asm-arm/arch-ixp4xx/gpio.h
+ *
+ * IXP4XX GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Milan Svoboda <msvoboda@ra.rockwell.com>
+ * Based on PXA implementation by Philipp Zabel <philipp.zabel@gmail.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_ARCH_IXP4XX_GPIO_H
+#define __ASM_ARCH_IXP4XX_GPIO_H
+
+#include <asm/hardware.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+       return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+       return;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+       gpio_line_config(gpio, IXP4XX_GPIO_IN);
+       return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int level)
+{
+       gpio_line_set(gpio, level);
+       gpio_line_config(gpio, IXP4XX_GPIO_OUT);
+       return 0;
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+       int value;
+
+       gpio_line_get(gpio, &value);
+
+       return value;
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       gpio_line_set(gpio, value);
+}
+
+#include <asm-generic/gpio.h>                  /* cansleep wrappers */
+
+extern int gpio_to_irq(int gpio);
+extern int irq_to_gpio(int gpio);
+
+#endif
+
index 88fd087..297ceda 100644 (file)
@@ -17,8 +17,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H__
 #define __ASM_ARCH_HARDWARE_H__
 
-#define PCIBIOS_MIN_IO                 0x00001000
-#define PCIBIOS_MIN_MEM                        0x48000000
+#define PCIBIOS_MIN_IO         0x00001000
+#define PCIBIOS_MIN_MEM                (cpu_is_ixp43x() ? 0x40000000 : 0x48000000)
 
 /*
  * We override the standard dma-mask routines for bouncing.
 
 #define pcibios_assign_all_busses()    1
 
-#if defined(CONFIG_CPU_IXP46X) && !defined(__ASSEMBLY__)
-extern unsigned int processor_id;
-#define cpu_is_ixp465() ((processor_id & 0xffffffc0) == 0x69054200)
-#else
-#define        cpu_is_ixp465() (0)
+#ifndef __ASSEMBLER__
+#include <asm/arch/cpu.h>
 #endif
 
 /* Register locations and bits */
@@ -47,5 +44,6 @@ extern unsigned int processor_id;
 #include "prpmc1100.h"
 #include "nslu2.h"
 #include "nas100d.h"
+#include "dsmg600.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
index a41ba22..c72f9d7 100644 (file)
@@ -59,10 +59,10 @@ extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
  * fallback to the default.
  */
 static inline void __iomem *
-__ixp4xx_ioremap(unsigned long addr, size_t size, unsigned long flags)
+__ixp4xx_ioremap(unsigned long addr, size_t size, unsigned int mtype)
 {
-       if((addr < 0x48000000) || (addr > 0x4fffffff))
-               return __ioremap(addr, size, flags);
+       if((addr < PCIBIOS_MIN_MEM) || (addr > 0x4fffffff))
+               return __arm_ioremap(addr, size, mtype);
 
        return (void *)addr;
 }
index e44a563..1180160 100644 (file)
 /*
  * Only first 32 sources are valid if running on IXP42x systems
  */
-#ifndef        CONFIG_CPU_IXP46X
-#define NR_IRQS                        32
-#else
+#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
 #define NR_IRQS                        64
+#else
+#define NR_IRQS                        32
 #endif
 
 #define        XSCALE_PMU_IRQ          (IRQ_IXP4XX_XSCALE_PMU)
 #define        IRQ_NAS100D_PCI_INTD    IRQ_IXP4XX_GPIO8
 #define        IRQ_NAS100D_PCI_INTE    IRQ_IXP4XX_GPIO7
 
+/*
+ * D-Link DSM-G600 RevA board IRQs
+ */
+#define        IRQ_DSMG600_PCI_INTA    IRQ_IXP4XX_GPIO11
+#define        IRQ_DSMG600_PCI_INTB    IRQ_IXP4XX_GPIO10
+#define        IRQ_DSMG600_PCI_INTC    IRQ_IXP4XX_GPIO9
+#define        IRQ_DSMG600_PCI_INTD    IRQ_IXP4XX_GPIO8
+#define        IRQ_DSMG600_PCI_INTE    IRQ_IXP4XX_GPIO7
+#define        IRQ_DSMG600_PCI_INTF    IRQ_IXP4XX_GPIO6
+
 #endif
index ed35e5c..5d949d7 100644 (file)
 
 #define DCMD_LENGTH    0x01fff         /* length mask (max = 8K - 1) */
 
-#ifndef __ASSEMBLY__
-static inline int cpu_is_ixp46x(void)
-{
-#ifdef CONFIG_CPU_IXP46X
-       unsigned int processor_id;
-
-       asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
-
-       if ((processor_id & 0xffffff00) == 0x69054200)
-               return 1;
-#endif
-       return 0;
-}
-#endif
-
 #endif
index 8ab45be..fc9aa21 100644 (file)
 #define NETX_SYSTEM_IOC_MR          NETX_SYSTEM_REG(0x08)
 
 /* FIXME: Docs are not consistent */
-#define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x08)
-/* #define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x0c) */
+/* #define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x08) */
+#define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x0c)
 
 #define NETX_SYSTEM_PHY_CONTROL     NETX_SYSTEM_REG(0x10)
 #define NETX_SYSTEM_REV             NETX_SYSTEM_REG(0x34)
index 91dc8fb..716f34f 100644 (file)
@@ -15,4 +15,6 @@
 
 #define board_is_a9m9750dev()  (machine_is_cc9p9360dev())
 
+#define board_is_jscc9p9360()  (machine_is_cc9p9360js())
+
 #endif /* ifndef __ASM_ARCH_BOARD_H */
index a7c5ab3..bf30cbd 100644 (file)
 #ifndef __ASM_ARCH_CLOCK_H
 #define __ASM_ARCH_CLOCK_H
 
+#include <asm/arch-ns9xxx/regs-sys.h>
+
+#define CRYSTAL 29491200 /* Hz */
+
+/* The HRM calls this value f_vco */
 static inline u32 ns9xxx_systemclock(void) __attribute__((const));
 static inline u32 ns9xxx_systemclock(void)
 {
+       u32 pll = SYS_PLL;
+
        /*
-        * This should be a multiple of HZ * TIMERCLOCKSELECT (in time.c)
+        * The system clock should be a multiple of HZ * TIMERCLOCKSELECT (in
+        * time.c).
+        *
+        * The following values are given:
+        *   - TIMERCLOCKSELECT == 2^i for an i in {0 .. 6}
+        *   - CRYSTAL == 29491200 == 2^17 * 3^2 * 5^2
+        *   - ND in {0 .. 31}
+        *   - FS in {0 .. 3}
+        *
+        * Assuming the worst, we consider:
+        *   - TIMERCLOCKSELECT == 64
+        *   - ND == 0
+        *   - FS == 3
+        *
+        * So HZ should be a divisor of:
+        *      (CRYSTAL * (ND + 1) >> FS) / TIMERCLOCKSELECT
+        *   == (2^17 * 3^2 * 5^2 * 1 >> 3) / 64
+        *   == 2^8 * 3^2 * 5^2
+        *   == 57600
+        *
+        * Currently HZ is defined to be 100 for this platform.
+        *
+        * Fine.
         */
-       return 353894400;
+       return CRYSTAL * (REGGET(pll, SYS_PLL, ND) + 1)
+               >> REGGET(pll, SYS_PLL, FS);
 }
 
 static inline u32 ns9xxx_cpuclock(void) __attribute__((const));
index 6819da7..2560055 100644 (file)
@@ -51,8 +51,9 @@
                       ~(__REGVAL(reg ## _ ## field, value))))          \
                  | (__REGVAL(reg ## _ ## field, value))))
 
-#  define REGGET(reg, field)                                           \
-       ((reg & (reg ## _ ## field)) / (field & (-field)))
+#  define REGGET(var, reg, field)                                      \
+       ((var & (reg ## _ ## field)) /                                  \
+        ((reg ## _ ## field) & (-(reg ## _ ## field))))
 
 #else
 
index 716c106..223e51b 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <asm/mach-types.h>
 
-#define processor_is_ns9360()  (machine_is_cc9p9360dev())
+#define processor_is_ns9360()  (machine_is_cc9p9360dev()               \
+               || machine_is_cc9p9360js())
 
 #endif /* ifndef __ASM_ARCH_PROCESSOR_H */
index 8162a50..a42546a 100644 (file)
 /* PLL Configuration register */
 #define SYS_PLL                __REG(0xa0900188)
 
+/* PLL FS status */
+#define SYS_PLL_FS             __REGBITS(24, 23)
+
+/* PLL ND status */
+#define SYS_PLL_ND             __REGBITS(20, 16)
+
 /* PLL Configuration register: PLL SW change */
 #define SYS_PLL_SWC            __REGBIT(15)
 #define SYS_PLL_SWC_NO                 __REGVAL(SYS_PLL_SWC, 0)
index 46ec224..e404b23 100644 (file)
@@ -64,6 +64,7 @@ struct i2c_slave_client;
 struct i2c_pxa_platform_data {
        unsigned int            slave_addr;
        struct i2c_slave_client *slave;
+       unsigned int            class;
 };
 
 extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
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;
index 139c9d9..dbcc929 100644 (file)
 #define CCCR_M_MASK    0x0060          /* Memory Frequency to Run Mode Frequency Multiplier */
 #define CCCR_L_MASK    0x001f          /* Crystal Frequency to Memory Frequency Multiplier */
 
-#define CKEN24_CAMERA  (1 << 24)       /* Camera Interface Clock Enable */
-#define CKEN23_SSP1    (1 << 23)       /* SSP1 Unit Clock Enable */
-#define CKEN22_MEMC    (1 << 22)       /* Memory Controller Clock Enable */
-#define CKEN21_MEMSTK  (1 << 21)       /* Memory Stick Host Controller */
-#define CKEN20_IM      (1 << 20)       /* Internal Memory Clock Enable */
-#define CKEN19_KEYPAD  (1 << 19)       /* Keypad Interface Clock Enable */
-#define CKEN18_USIM    (1 << 18)       /* USIM Unit Clock Enable */
-#define CKEN17_MSL     (1 << 17)       /* MSL Unit Clock Enable */
-#define CKEN16_LCD     (1 << 16)       /* LCD Unit Clock Enable */
-#define CKEN15_PWRI2C  (1 << 15)       /* PWR I2C Unit Clock Enable */
-#define CKEN14_I2C     (1 << 14)       /* I2C Unit Clock Enable */
-#define CKEN13_FICP    (1 << 13)       /* FICP Unit Clock Enable */
-#define CKEN12_MMC     (1 << 12)       /* MMC Unit Clock Enable */
-#define CKEN11_USB     (1 << 11)       /* USB Unit Clock Enable */
-#define CKEN10_ASSP    (1 << 10)       /* ASSP (SSP3) Clock Enable */
-#define CKEN10_USBHOST (1 << 10)       /* USB Host Unit Clock Enable */
-#define CKEN9_OSTIMER  (1 << 9)        /* OS Timer Unit Clock Enable */
-#define CKEN9_NSSP     (1 << 9)        /* NSSP (SSP2) Clock Enable */
-#define CKEN8_I2S      (1 << 8)        /* I2S Unit Clock Enable */
-#define CKEN7_BTUART   (1 << 7)        /* BTUART Unit Clock Enable */
-#define CKEN6_FFUART   (1 << 6)        /* FFUART Unit Clock Enable */
-#define CKEN5_STUART   (1 << 5)        /* STUART Unit Clock Enable */
-#define CKEN4_HWUART   (1 << 4)        /* HWUART Unit Clock Enable */
-#define CKEN4_SSP3     (1 << 4)        /* SSP3 Unit Clock Enable */
-#define CKEN3_SSP      (1 << 3)        /* SSP Unit Clock Enable */
-#define CKEN3_SSP2     (1 << 3)        /* SSP2 Unit Clock Enable */
-#define CKEN2_AC97     (1 << 2)        /* AC97 Unit Clock Enable */
-#define CKEN1_PWM1     (1 << 1)        /* PWM1 Clock Enable */
-#define CKEN0_PWM0     (1 << 0)        /* PWM0 Clock Enable */
+#define CKEN_CAMERA    (24)    /* Camera Interface Clock Enable */
+#define CKEN_SSP1      (23)    /* SSP1 Unit Clock Enable */
+#define CKEN_MEMC      (22)    /* Memory Controller Clock Enable */
+#define CKEN_MEMSTK    (21)    /* Memory Stick Host Controller */
+#define CKEN_IM                (20)    /* Internal Memory Clock Enable */
+#define CKEN_KEYPAD    (19)    /* Keypad Interface Clock Enable */
+#define CKEN_USIM      (18)    /* USIM Unit Clock Enable */
+#define CKEN_MSL       (17)    /* MSL Unit Clock Enable */
+#define CKEN_LCD       (16)    /* LCD Unit Clock Enable */
+#define CKEN_PWRI2C    (15)    /* PWR I2C Unit Clock Enable */
+#define CKEN_I2C       (14)    /* I2C Unit Clock Enable */
+#define CKEN_FICP      (13)    /* FICP Unit Clock Enable */
+#define CKEN_MMC       (12)    /* MMC Unit Clock Enable */
+#define CKEN_USB       (11)    /* USB Unit Clock Enable */
+#define CKEN_ASSP      (10)    /* ASSP (SSP3) Clock Enable */
+#define CKEN_USBHOST   (10)    /* USB Host Unit Clock Enable */
+#define CKEN_OSTIMER   (9)     /* OS Timer Unit Clock Enable */
+#define CKEN_NSSP      (9)     /* NSSP (SSP2) Clock Enable */
+#define CKEN_I2S       (8)     /* I2S Unit Clock Enable */
+#define CKEN_BTUART    (7)     /* BTUART Unit Clock Enable */
+#define CKEN_FFUART    (6)     /* FFUART Unit Clock Enable */
+#define CKEN_STUART    (5)     /* STUART Unit Clock Enable */
+#define CKEN_HWUART    (4)     /* HWUART Unit Clock Enable */
+#define CKEN_SSP3      (4)     /* SSP3 Unit Clock Enable */
+#define CKEN_SSP       (3)     /* SSP Unit Clock Enable */
+#define CKEN_SSP2      (3)     /* SSP2 Unit Clock Enable */
+#define CKEN_AC97      (2)     /* AC97 Unit Clock Enable */
+#define CKEN_PWM1      (1)     /* PWM1 Clock Enable */
+#define CKEN_PWM0      (0)     /* PWM0 Clock Enable */
 
 #define OSCC_OON       (1 << 1)        /* 32.768kHz OON (write-once only bit) */
 #define OSCC_OOK       (1 << 0)        /* 32.768kHz OOK (read-only bit) */
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 bdd6a4f..b004dee 100644 (file)
 #ifndef __ASM_ARCH_REGS_AC97_H
 #define __ASM_ARCH_REGS_AC97_H __FILE__
 
-#define S3C_AC97_GLBCTRL       (0x00)
-#define S3C_AC97_GLBSTAT       (0x04)
-#define S3C_AC97_CODEC_CMD     (0x08)
-#define S3C_AC97_PCM_ADDR      (0x10)
-#define S3C_AC97_PCM_DATA      (0x18)
-#define S3C_AC97_MIC_DATA      (0x1C)
+#define S3C_AC97_GLBCTRL                               (0x00)
+
+#define S3C_AC97_GLBCTRL_CODECREADYIE                  (1<<22)
+#define S3C_AC97_GLBCTRL_PCMOUTURIE                    (1<<21)
+#define S3C_AC97_GLBCTRL_PCMINORIE                     (1<<20)
+#define S3C_AC97_GLBCTRL_MICINORIE                     (1<<19)
+#define S3C_AC97_GLBCTRL_PCMOUTTIE                     (1<<18)
+#define S3C_AC97_GLBCTRL_PCMINTIE                      (1<<17)
+#define S3C_AC97_GLBCTRL_MICINTIE                      (1<<16)
+#define S3C_AC97_GLBCTRL_PCMOUTTM_OFF                  (0<<12)
+#define S3C_AC97_GLBCTRL_PCMOUTTM_PIO                  (1<<12)
+#define S3C_AC97_GLBCTRL_PCMOUTTM_DMA                  (2<<12)
+#define S3C_AC97_GLBCTRL_PCMOUTTM_MASK                 (3<<12)
+#define S3C_AC97_GLBCTRL_PCMINTM_OFF                   (0<<10)
+#define S3C_AC97_GLBCTRL_PCMINTM_PIO                   (1<<10)
+#define S3C_AC97_GLBCTRL_PCMINTM_DMA                   (2<<10)
+#define S3C_AC97_GLBCTRL_PCMINTM_MASK                  (3<<10)
+#define S3C_AC97_GLBCTRL_MICINTM_OFF                   (0<<8)
+#define S3C_AC97_GLBCTRL_MICINTM_PIO                   (1<<8)
+#define S3C_AC97_GLBCTRL_MICINTM_DMA                   (2<<8)
+#define S3C_AC97_GLBCTRL_MICINTM_MASK                  (3<<8)
+#define S3C_AC97_GLBCTRL_TRANSFERDATAENABLE            (1<<3)
+#define S3C_AC97_GLBCTRL_ACLINKON                      (1<<2)
+#define S3C_AC97_GLBCTRL_WARMRESET                     (1<<1)
+#define S3C_AC97_GLBCTRL_COLDRESET                     (1<<0)
+
+#define S3C_AC97_GLBSTAT                               (0x04)
+
+#define S3C_AC97_GLBSTAT_CODECREADY                    (1<<22)
+#define S3C_AC97_GLBSTAT_PCMOUTUR                      (1<<21)
+#define S3C_AC97_GLBSTAT_PCMINORI                      (1<<20)
+#define S3C_AC97_GLBSTAT_MICINORI                      (1<<19)
+#define S3C_AC97_GLBSTAT_PCMOUTTI                      (1<<18)
+#define S3C_AC97_GLBSTAT_PCMINTI                       (1<<17)
+#define S3C_AC97_GLBSTAT_MICINTI                       (1<<16)
+#define S3C_AC97_GLBSTAT_MAINSTATE_IDLE                        (0<<0)
+#define S3C_AC97_GLBSTAT_MAINSTATE_INIT                        (1<<0)
+#define S3C_AC97_GLBSTAT_MAINSTATE_READY               (2<<0)
+#define S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE              (3<<0)
+#define S3C_AC97_GLBSTAT_MAINSTATE_LP                  (4<<0)
+#define S3C_AC97_GLBSTAT_MAINSTATE_WARM                        (5<<0)
+
+#define S3C_AC97_CODEC_CMD                             (0x08)
+
+#define S3C_AC97_CODEC_CMD_READ                                (1<<23)
+
+#define S3C_AC97_STAT                                  (0x0c)
+#define S3C_AC97_PCM_ADDR                              (0x10)
+#define S3C_AC97_PCM_DATA                              (0x18)
+#define S3C_AC97_MIC_DATA                              (0x1C)
 
 #endif /* __ASM_ARCH_REGS_AC97_H */
index 3c83546..e1e9805 100644 (file)
@@ -75,7 +75,7 @@
 #define S3C2410_UDC_OUT_FIFO_CNT1_REG  S3C2410_USBDREG(0x0198)
 #define S3C2410_UDC_OUT_FIFO_CNT2_REG  S3C2410_USBDREG(0x019c)
 
-
+#define S3C2410_UDC_FUNCADDR_UPDATE    (1<<7)
 
 #define S3C2410_UDC_PWR_ISOUP          (1<<7) // R/W
 #define S3C2410_UDC_PWR_RESET          (1<<3) // R
 #define S3C2410_UDC_OCSR2_ISO          (1<<6) // R/W
 #define S3C2410_UDC_OCSR2_DMAIEN       (1<<5) // R/W
 
-#define S3C2410_UDC_SETIX(base,x)          \
-       writel(S3C2410_UDC_INDEX_ ## x, base+S3C2410_UDC_INDEX_REG);
-
-
 #define S3C2410_UDC_EP0_CSR_OPKRDY     (1<<0)
 #define S3C2410_UDC_EP0_CSR_IPKRDY     (1<<1)
 #define S3C2410_UDC_EP0_CSR_SENTSTL    (1<<2)
index a0ae2b9..3a6d3eb 100644 (file)
@@ -160,6 +160,7 @@ struct expansion_card {
        unsigned char           irqmask;        /* IRQ mask                     */
        unsigned char           fiqmask;        /* FIQ mask                     */
        unsigned char           claimed;        /* Card claimed?                */
+       unsigned char           easi;           /* EASI card                    */
 
        void                    *irq_data;      /* Data for use for IRQ by card */
        void                    *fiq_data;      /* Data for use for FIQ by card */
@@ -169,7 +170,6 @@ struct expansion_card {
        CONST unsigned int      dma;            /* DMA number (for request_dma) */
        CONST unsigned int      irq;            /* IRQ number (for request_irq) */
        CONST unsigned int      fiq;            /* FIQ number (for request_irq) */
-       CONST card_type_t       type;           /* Type of card                 */
        CONST struct in_ecid    cid;            /* Card Identification          */
 
        /* Private internal data */
@@ -224,56 +224,6 @@ ecard_address(struct expansion_card *ec, card_type_t type, card_speed_t speed)
 extern int ecard_request_resources(struct expansion_card *ec);
 extern void ecard_release_resources(struct expansion_card *ec);
 
-#ifdef ECARD_C
-/* Definitions internal to ecard.c - for it's use only!!
- *
- * External expansion card header as read from the card
- */
-struct ex_ecid {
-       unsigned char   r_irq:1;
-       unsigned char   r_zero:1;
-       unsigned char   r_fiq:1;
-       unsigned char   r_id:4;
-       unsigned char   r_a:1;
-
-       unsigned char   r_cd:1;
-       unsigned char   r_is:1;
-       unsigned char   r_w:2;
-       unsigned char   r_r1:4;
-
-       unsigned char   r_r2:8;
-
-       unsigned char   r_prod[2];
-
-       unsigned char   r_manu[2];
-
-       unsigned char   r_country;
-
-       unsigned char   r_fiqmask;
-       unsigned char   r_fiqoff[3];
-
-       unsigned char   r_irqmask;
-       unsigned char   r_irqoff[3];
-};
-
-/*
- * Chunk directory entry as read from the card
- */
-struct ex_chunk_dir {
-       unsigned char r_id;
-       unsigned char r_len[3];
-       unsigned long r_start;
-       union {
-               char string[256];
-               char data[1];
-       } d;
-#define c_id(x)                ((x)->r_id)
-#define c_len(x)       ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16))
-#define c_start(x)     ((x)->r_start)
-};
-
-#endif
-
 extern struct bus_type ecard_bus_type;
 
 #define ECARD_DEV(_d)  container_of((_d), struct expansion_card, dev)
index 15141a9..63feceb 100644 (file)
@@ -28,6 +28,7 @@
 extern void gpio_line_config(int line, int direction);
 extern int  gpio_line_get(int line);
 extern void gpio_line_set(int line, int value);
+extern int init_atu;
 #endif
 
 
@@ -41,7 +42,7 @@ extern void gpio_line_set(int line, int value);
                                        IOP3XX_PERIPHERAL_SIZE - 1)
 #define IOP3XX_PERIPHERAL_UPPER_VA (IOP3XX_PERIPHERAL_VIRT_BASE +\
                                        IOP3XX_PERIPHERAL_SIZE - 1)
-#define IOP3XX_PMMR_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+#define IOP3XX_PMMR_PHYS_TO_VIRT(addr) (u32) ((u32) (addr) -\
                                        (IOP3XX_PERIPHERAL_PHYS_BASE\
                                        - IOP3XX_PERIPHERAL_VIRT_BASE))
 #define IOP3XX_REG_ADDR(reg)           (IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
@@ -103,6 +104,21 @@ extern void gpio_line_set(int line, int value);
 #define IOP3XX_PCIXCMD         (volatile u16 *)IOP3XX_REG_ADDR(0x01e2)
 #define IOP3XX_PCIXSR          (volatile u32 *)IOP3XX_REG_ADDR(0x01e4)
 #define IOP3XX_PCIIRSR         (volatile u32 *)IOP3XX_REG_ADDR(0x01ec)
+#define IOP3XX_PCSR_OUT_Q_BUSY (1 << 15)
+#define IOP3XX_PCSR_IN_Q_BUSY  (1 << 14)
+#define IOP3XX_ATUCR_OUT_EN    (1 << 1)
+
+#define IOP3XX_INIT_ATU_DEFAULT 0
+#define IOP3XX_INIT_ATU_DISABLE -1
+#define IOP3XX_INIT_ATU_ENABLE  1
+
+#ifdef CONFIG_IOP3XX_ATU
+#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+                               IOP3XX_INIT_ATU_ENABLE : init_atu)
+#else
+#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+                               IOP3XX_INIT_ATU_DISABLE : init_atu)
+#endif
 
 /* Messaging Unit  */
 #define IOP3XX_IMR0            (volatile u32 *)IOP3XX_REG_ADDR(0x0310)
@@ -253,14 +269,12 @@ extern void gpio_line_set(int line, int value);
 /*
  * IOP3XX I/O and Mem space regions for PCI autoconfiguration
  */
-#define IOP3XX_PCI_MEM_WINDOW_SIZE     0x04000000
-#define IOP3XX_PCI_LOWER_MEM_PA                0x80000000
-#define IOP3XX_PCI_LOWER_MEM_BA                (*IOP3XX_OMWTVR0)
+#define IOP3XX_PCI_LOWER_MEM_PA        0x80000000
 
 #define IOP3XX_PCI_IO_WINDOW_SIZE      0x00010000
 #define IOP3XX_PCI_LOWER_IO_PA         0x90000000
 #define IOP3XX_PCI_LOWER_IO_VA         0xfe000000
-#define IOP3XX_PCI_LOWER_IO_BA         (*IOP3XX_OIOWTVR)
+#define IOP3XX_PCI_LOWER_IO_BA         0x90000000
 #define IOP3XX_PCI_UPPER_IO_PA         (IOP3XX_PCI_LOWER_IO_PA +\
                                        IOP3XX_PCI_IO_WINDOW_SIZE - 1)
 #define IOP3XX_PCI_UPPER_IO_VA         (IOP3XX_PCI_LOWER_IO_VA +\
index 5f60b42..8261ff9 100644 (file)
@@ -56,13 +56,22 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
 /*
  * Architecture ioremap implementation.
- *
- * __ioremap takes CPU physical address.
- *
- * __ioremap_pfn takes a Page Frame Number and an offset into that page
  */
-extern void __iomem * __ioremap_pfn(unsigned long, unsigned long, size_t, unsigned long);
-extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+#define MT_DEVICE              0
+#define MT_DEVICE_NONSHARED    1
+#define MT_DEVICE_CACHED       2
+#define MT_DEVICE_IXP2000      3
+/*
+ * types 4 onwards can be found in asm/mach/map.h and are undefined
+ * for ioremap
+ */
+
+/*
+ * __arm_ioremap takes CPU physical address.
+ * __arm_ioremap_pfn takes a Page Frame Number and an offset into that page
+ */
+extern void __iomem * __arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
+extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
 extern void __iounmap(volatile void __iomem *addr);
 
 /*
@@ -203,14 +212,14 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  *
  */
 #ifndef __arch_ioremap
-#define ioremap(cookie,size)           __ioremap(cookie,size,0)
-#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0)
-#define ioremap_cached(cookie,size)    __ioremap(cookie,size,L_PTE_CACHEABLE)
+#define ioremap(cookie,size)           __arm_ioremap(cookie, size, MT_DEVICE)
+#define ioremap_nocache(cookie,size)   __arm_ioremap(cookie, size, MT_DEVICE)
+#define ioremap_cached(cookie,size)    __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
 #define iounmap(cookie)                        __iounmap(cookie)
 #else
-#define ioremap(cookie,size)           __arch_ioremap((cookie),(size),0)
-#define ioremap_nocache(cookie,size)   __arch_ioremap((cookie),(size),0)
-#define ioremap_cached(cookie,size)    __arch_ioremap((cookie),(size),L_PTE_CACHEABLE)
+#define ioremap(cookie,size)           __arch_ioremap((cookie), (size), MT_DEVICE)
+#define ioremap_nocache(cookie,size)   __arch_ioremap((cookie), (size), MT_DEVICE)
+#define ioremap_cached(cookie,size)    __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define iounmap(cookie)                        __arch_iounmap(cookie)
 #endif
 
index cef5364..7ef3c83 100644 (file)
@@ -9,6 +9,8 @@
  *
  *  Page table mapping constructs and function prototypes
  */
+#include <asm/io.h>
+
 struct map_desc {
        unsigned long virtual;
        unsigned long pfn;
@@ -16,15 +18,16 @@ struct map_desc {
        unsigned int type;
 };
 
-#define MT_DEVICE              0
-#define MT_CACHECLEAN          1
-#define MT_MINICLEAN           2
-#define MT_LOW_VECTORS         3
-#define MT_HIGH_VECTORS                4
-#define MT_MEMORY              5
-#define MT_ROM                 6
-#define MT_IXP2000_DEVICE      7
-#define MT_NONSHARED_DEVICE    8
+/* types 0-3 are defined in asm/io.h */
+#define MT_CACHECLEAN          4
+#define MT_MINICLEAN           5
+#define MT_LOW_VECTORS         6
+#define MT_HIGH_VECTORS                7
+#define MT_MEMORY              8
+#define MT_ROM                 9
+
+#define MT_NONSHARED_DEVICE    MT_DEVICE_NONSHARED
+#define MT_IXP2000_DEVICE      MT_DEVICE_IXP2000
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
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 d1a65b1..f8755c8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/compiler.h>
 #include <asm/cacheflush.h>
 #include <asm/proc-fns.h>
+#include <asm-generic/mm_hooks.h>
 
 void __check_kvm_seq(struct mm_struct *mm);
 
index f6135db..235b753 100644 (file)
@@ -56,6 +56,7 @@ extern struct mutex clocks_mutex;
 extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
 
 extern int s3c24xx_register_clock(struct clk *clk);
+extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
 
 extern int s3c24xx_setup_clocks(unsigned long xtal,
                                unsigned long fclk,
index 15dd188..23e420e 100644 (file)
@@ -40,22 +40,6 @@ extern void s3c24xx_init_uartdevs(char *name,
                                  struct s3c24xx_uart_resources *res,
                                  struct s3c2410_uartcfg *cfg, int no);
 
-/* the board structure is used at first initialsation time
- * to get info such as the devices to register for this
- * board. This is done because platfrom_add_devices() cannot
- * be called from the map_io entry.
-*/
-
-struct s3c24xx_board {
-       struct platform_device  **devices;
-       unsigned int              devices_count;
-
-       struct clk              **clocks;
-       unsigned int              clocks_count;
-};
-
-extern void s3c24xx_set_board(struct s3c24xx_board *board);
-
 /* timer for 2410/2440 */
 
 struct sys_timer;
index 5a8ef78..2d0dad8 100644 (file)
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
-
 #define PTRACE_GETREGS         12
 #define PTRACE_SETREGS         13
 #define PTRACE_GETFPREGS       14
 #define PTRACE_SETFPREGS       15
-
+/* PTRACE_ATTACH is 16 */
+/* PTRACE_DETACH is 17 */
 #define PTRACE_GETWMMXREGS     18
 #define PTRACE_SETWMMXREGS     19
-
+/* 20 is unused */
 #define PTRACE_OLDSETOPTIONS   21
-
 #define PTRACE_GET_THREAD_AREA 22
-
 #define PTRACE_SET_SYSCALL     23
-
 /* PTRACE_SYSCALL is 24 */
-
 #define PTRACE_GETCRUNCHREGS   25
 #define PTRACE_SETCRUNCHREGS   26
 
index 69134c7..63b3080 100644 (file)
@@ -76,6 +76,8 @@
 #include <linux/linkage.h>
 #include <linux/irqflags.h>
 
+#define __exception    __attribute__((section(".exception.text")))
+
 struct thread_info;
 struct task_struct;
 
index 5014794..eae85b0 100644 (file)
@@ -57,6 +57,7 @@ struct thread_info {
        __u32                   cpu;            /* cpu */
        __u32                   cpu_domain;     /* cpu domain */
        struct cpu_context_save cpu_context;    /* cpu context */
+       __u32                   syscall;        /* syscall number */
        __u8                    used_cp[16];    /* thread used copro */
        unsigned long           tp_value;
        struct crunch_state     crunchstate;
index 1a929bf..16c821f 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARM_MMU_CONTEXT_H
 #define __ASM_ARM_MMU_CONTEXT_H
 
+#include <asm-generic/mm_hooks.h>
+
 #define init_new_context(tsk,mm)       0
 #define destroy_context(mm)            do { } while(0)
 
index 31add1a..c37c391 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/tlbflush.h>
 #include <asm/pgalloc.h>
 #include <asm/sysreg.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * The MMU "context" consists of two things:
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 e6e659d..72ba08d 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __CRIS_MMU_CONTEXT_H
 #define __CRIS_MMU_CONTEXT_H
 
+#include <asm-generic/mm_hooks.h>
+
 extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 extern void get_mmu_context(struct mm_struct *mm);
 extern void destroy_context(struct mm_struct *mm);
index 72edcaa..c7daa39 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm-generic/mm_hooks.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
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.
diff --git a/include/asm-generic/mm_hooks.h b/include/asm-generic/mm_hooks.h
new file mode 100644 (file)
index 0000000..67dea81
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Define generic no-op hooks for arch_dup_mmap and arch_exit_mmap, to
+ * be included in asm-FOO/mmu_context.h for any arch FOO which doesn't
+ * need to hook these.
+ */
+#ifndef _ASM_GENERIC_MM_HOOKS_H
+#define _ASM_GENERIC_MM_HOOKS_H
+
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+                                struct mm_struct *mm)
+{
+}
+
+static inline void arch_exit_mmap(struct mm_struct *mm)
+{
+}
+
+#endif /* _ASM_GENERIC_MM_HOOKS_H */
index 1963762..d984a90 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_GENERIC_PERCPU_H_
 #define _ASM_GENERIC_PERCPU_H_
 #include <linux/compiler.h>
+#include <linux/threads.h>
 
 #define __GENERIC_PER_CPU
 #ifdef CONFIG_SMP
index 9fcc8d9..f3806a7 100644 (file)
        }
 
 #define NOTES                                                          \
-               .notes : { *(.note.*) } :note
+       .notes : { *(.note.*) } :note
 
 #define INITCALLS                                                      \
        *(.initcall0.init)                                              \
index 5c165f7..f44b730 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm-generic/mm_hooks.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
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 5ae93af..cbf6e8f 100644 (file)
@@ -3,8 +3,10 @@ include include/asm-generic/Kbuild.asm
 header-y += boot.h
 header-y += debugreg.h
 header-y += ldt.h
+header-y += msr-index.h
 header-y += ptrace-abi.h
 header-y += ucontext.h
 
+unifdef-y += msr.h
 unifdef-y += mtrr.h
 unifdef-y += vm86.h
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 b8fa955..0f70b37 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _I386_ALTERNATIVE_H
 #define _I386_ALTERNATIVE_H
 
-#ifdef __KERNEL__
-
 #include <asm/types.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
@@ -16,6 +14,7 @@ struct alt_instr {
        u8  pad;
 };
 
+extern void alternative_instructions(void);
 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
 
 struct module;
@@ -31,9 +30,7 @@ static inline void alternatives_smp_module_add(struct module *mod, char *name,
                                        void *text, void *text_end) {}
 static inline void alternatives_smp_module_del(struct module *mod) {}
 static inline void alternatives_smp_switch(int smp) {}
-#endif
-
-#endif
+#endif /* CONFIG_SMP */
 
 /*
  * Alternative instructions for different CPU types or capabilities.
@@ -85,6 +82,21 @@ static inline void alternatives_smp_switch(int smp) {}
                      "663:\n\t" newinstr "\n664:\n"   /* replacement */\
                      ".previous" :: "i" (feature), ##input)
 
+/* Like alternative_input, but with a single output argument */
+#define alternative_io(oldinstr, newinstr, feature, output, input...) \
+       asm volatile ("661:\n\t" oldinstr "\n662:\n"                    \
+                     ".section .altinstructions,\"a\"\n"               \
+                     "  .align 4\n"                                    \
+                     "  .long 661b\n"            /* label */           \
+                     "  .long 663f\n"            /* new instruction */ \
+                     "  .byte %c[feat]\n"        /* feature bit */     \
+                     "  .byte 662b-661b\n"       /* sourcelen */       \
+                     "  .byte 664f-663f\n"       /* replacementlen */  \
+                     ".previous\n"                                     \
+                     ".section .altinstr_replacement,\"ax\"\n"         \
+                     "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+                     ".previous" : output : [feat] "i" (feature), ##input)
+
 /*
  * Alternative inline assembly for SMP.
  *
@@ -118,15 +130,17 @@ static inline void alternatives_smp_switch(int smp) {}
 #define LOCK_PREFIX ""
 #endif
 
-struct paravirt_patch;
+struct paravirt_patch_site;
 #ifdef CONFIG_PARAVIRT
-void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
+void apply_paravirt(struct paravirt_patch_site *start,
+                   struct paravirt_patch_site *end);
 #else
 static inline void
-apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
+apply_paravirt(struct paravirt_patch_site *start,
+              struct paravirt_patch_site *end)
 {}
-#define __start_parainstructions NULL
-#define __stop_parainstructions NULL
+#define __parainstructions     NULL
+#define __parainstructions_end NULL
 #endif
 
 #endif /* _I386_ALTERNATIVE_H */
index a19810a..1e8f6f2 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_APIC_H
 
 #include <linux/pm.h>
+#include <linux/delay.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/processor.h>
@@ -64,12 +65,8 @@ static __inline fastcall unsigned long native_apic_read(unsigned long reg)
        return *((volatile unsigned long *)(APIC_BASE+reg));
 }
 
-static __inline__ void apic_wait_icr_idle(void)
-{
-       while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY )
-               cpu_relax();
-}
-
+void apic_wait_icr_idle(void);
+unsigned long safe_apic_wait_icr_idle(void);
 int get_physical_broadcast(void);
 
 #ifdef CONFIG_X86_GOOD_APIC
index c90c7c4..d28979f 100644 (file)
-/*
- *  include/asm-i386/bugs.h
- *
- *  Copyright (C) 1994  Linus Torvalds
- *
- *  Cyrix stuff, June 1998 by:
- *     - Rafael R. Reilova (moved everything from head.S),
- *        <rreilova@ececs.uc.edu>
- *     - Channing Corn (tests & fixes),
- *     - Andrew D. Balsa (code cleanup).
- */
-
 /*
  * This is included by init/main.c to check for architecture-dependent bugs.
  *
  * Needs:
  *     void check_bugs(void);
  */
+#ifndef _ASM_I386_BUG_H
+#define _ASM_I386_BUG_H
 
-#include <linux/init.h>
-#include <asm/processor.h>
-#include <asm/i387.h>
-#include <asm/msr.h>
-#include <asm/paravirt.h>
-
-static int __init no_halt(char *s)
-{
-       boot_cpu_data.hlt_works_ok = 0;
-       return 1;
-}
-
-__setup("no-hlt", no_halt);
-
-static int __init mca_pentium(char *s)
-{
-       mca_pentium_flag = 1;
-       return 1;
-}
-
-__setup("mca-pentium", mca_pentium);
-
-static int __init no_387(char *s)
-{
-       boot_cpu_data.hard_math = 0;
-       write_cr0(0xE | read_cr0());
-       return 1;
-}
-
-__setup("no387", no_387);
-
-static double __initdata x = 4195835.0;
-static double __initdata y = 3145727.0;
-
-/*
- * This used to check for exceptions.. 
- * However, it turns out that to support that,
- * the XMM trap handlers basically had to
- * be buggy. So let's have a correct XMM trap
- * handler, and forget about printing out
- * some status at boot.
- *
- * We should really only care about bugs here
- * anyway. Not features.
- */
-static void __init check_fpu(void)
-{
-       if (!boot_cpu_data.hard_math) {
-#ifndef CONFIG_MATH_EMULATION
-               printk(KERN_EMERG "No coprocessor found and no math emulation present.\n");
-               printk(KERN_EMERG "Giving up.\n");
-               for (;;) ;
-#endif
-               return;
-       }
-
-/* trap_init() enabled FXSR and company _before_ testing for FP problems here. */
-       /* Test for the divl bug.. */
-       __asm__("fninit\n\t"
-               "fldl %1\n\t"
-               "fdivl %2\n\t"
-               "fmull %2\n\t"
-               "fldl %1\n\t"
-               "fsubp %%st,%%st(1)\n\t"
-               "fistpl %0\n\t"
-               "fwait\n\t"
-               "fninit"
-               : "=m" (*&boot_cpu_data.fdiv_bug)
-               : "m" (*&x), "m" (*&y));
-       if (boot_cpu_data.fdiv_bug)
-               printk("Hmm, FPU with FDIV bug.\n");
-}
-
-static void __init check_hlt(void)
-{
-       if (paravirt_enabled())
-               return;
-
-       printk(KERN_INFO "Checking 'hlt' instruction... ");
-       if (!boot_cpu_data.hlt_works_ok) {
-               printk("disabled\n");
-               return;
-       }
-       halt();
-       halt();
-       halt();
-       halt();
-       printk("OK.\n");
-}
-
-/*
- *     Most 386 processors have a bug where a POPAD can lock the 
- *     machine even from user space.
- */
-static void __init check_popad(void)
-{
-#ifndef CONFIG_X86_POPAD_OK
-       int res, inp = (int) &res;
-
-       printk(KERN_INFO "Checking for popad bug... ");
-       __asm__ __volatile__( 
-         "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
-         : "=&a" (res)
-         : "d" (inp)
-         : "ecx", "edi" );
-       /* If this fails, it means that any user program may lock the CPU hard. Too bad. */
-       if (res != 12345678) printk( "Buggy.\n" );
-                       else printk( "OK.\n" );
-#endif
-}
-
-/*
- * Check whether we are able to run this kernel safely on SMP.
- *
- * - In order to run on a i386, we need to be compiled for i386
- *   (for due to lack of "invlpg" and working WP on a i386)
- * - In order to run on anything without a TSC, we need to be
- *   compiled for a i486.
- * - In order to support the local APIC on a buggy Pentium machine,
- *   we need to be compiled with CONFIG_X86_GOOD_APIC disabled,
- *   which happens implicitly if compiled for a Pentium or lower
- *   (unless an advanced selection of CPU features is used) as an
- *   otherwise config implies a properly working local APIC without
- *   the need to do extra reads from the APIC.
-*/
-
-static void __init check_config(void)
-{
-/*
- * We'd better not be a i386 if we're configured to use some
- * i486+ only features! (WP works in supervisor mode and the
- * new "invlpg" and "bswap" instructions)
- */
-#if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP)
-       if (boot_cpu_data.x86 == 3)
-               panic("Kernel requires i486+ for 'invlpg' and other features");
-#endif
-
-/*
- * If we configured ourselves for a TSC, we'd better have one!
- */
-#ifdef CONFIG_X86_TSC
-       if (!cpu_has_tsc && !tsc_disable)
-               panic("Kernel compiled for Pentium+, requires TSC feature!");
-#endif
-
-/*
- * If we were told we had a good local APIC, check for buggy Pentia,
- * i.e. all B steppings and the C2 stepping of P54C when using their
- * integrated APIC (see 11AP erratum in "Pentium Processor
- * Specification Update").
- */
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
-           && cpu_has_apic
-           && boot_cpu_data.x86 == 5
-           && boot_cpu_data.x86_model == 2
-           && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
-               panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
-#endif
-}
-
-extern void alternative_instructions(void);
+void check_bugs(void);
 
-static void __init check_bugs(void)
-{
-       identify_cpu(&boot_cpu_data);
-#ifndef CONFIG_SMP
-       printk("CPU: ");
-       print_cpu_info(&boot_cpu_data);
-#endif
-       check_config();
-       check_fpu();
-       check_hlt();
-       check_popad();
-       init_utsname()->machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
-       alternative_instructions(); 
-}
+#endif /* _ASM_I386_BUG_H */
index d1b8e4a..f514e90 100644 (file)
@@ -7,7 +7,10 @@
 #ifndef __ASM_I386_CPUFEATURE_H
 #define __ASM_I386_CPUFEATURE_H
 
+#ifndef __ASSEMBLY__
 #include <linux/bitops.h>
+#endif
+#include <asm/required-features.h>
 
 #define NCAPINTS       7       /* N 32-bit words worth of info */
 
@@ -49,6 +52,7 @@
 #define X86_FEATURE_MP         (1*32+19) /* MP Capable. */
 #define X86_FEATURE_NX         (1*32+20) /* Execute Disable */
 #define X86_FEATURE_MMXEXT     (1*32+22) /* AMD MMX extensions */
+#define X86_FEATURE_RDTSCP     (1*32+27) /* RDTSCP */
 #define X86_FEATURE_LM         (1*32+29) /* Long Mode (x86-64) */
 #define X86_FEATURE_3DNOWEXT   (1*32+30) /* AMD 3DNow! extensions */
 #define X86_FEATURE_3DNOW      (1*32+31) /* 3DNow! */
@@ -76,6 +80,7 @@
 #define X86_FEATURE_PEBS       (3*32+12)  /* Precise-Event Based Sampling */
 #define X86_FEATURE_BTS                (3*32+13)  /* Branch Trace Store */
 #define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
+#define X86_FEATURE_SYNC_RDTSC (3*32+15)  /* RDTSC synchronizes the CPU */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_LAHF_LM    (6*32+ 0) /* LAHF/SAHF in long mode */
 #define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */
 
-#define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
-#define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
+#define cpu_has(c, bit)                                        \
+       ((__builtin_constant_p(bit) && (bit) < 32 &&    \
+               (1UL << (bit)) & REQUIRED_MASK1) ?      \
+               1 :                                     \
+       test_bit(bit, (c)->x86_capability))
+#define boot_cpu_has(bit)      cpu_has(&boot_cpu_data, bit)
 
 #define cpu_has_fpu            boot_cpu_has(X86_FEATURE_FPU)
 #define cpu_has_vme            boot_cpu_has(X86_FEATURE_VME)
index 5252ee0..d352485 100644 (file)
@@ -1,14 +1,15 @@
 #ifndef _I386_CURRENT_H
 #define _I386_CURRENT_H
 
-#include <asm/pda.h>
 #include <linux/compiler.h>
+#include <asm/percpu.h>
 
 struct task_struct;
 
+DECLARE_PER_CPU(struct task_struct *, current_task);
 static __always_inline struct task_struct *get_current(void)
 {
-       return read_pda(pcurrent);
+       return x86_read_percpu(current_task);
 }
  
 #define current get_current()
index 050831f..c547403 100644 (file)
 
 #include <asm/mmu.h>
 
-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
-
 struct Xgt_desc_struct {
        unsigned short size;
        unsigned long address __attribute__((packed));
        unsigned short pad;
 } __attribute__ ((packed));
 
-extern struct Xgt_desc_struct idt_descr;
-DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
-extern struct Xgt_desc_struct early_gdt_descr;
+struct gdt_page
+{
+       struct desc_struct gdt[GDT_ENTRIES];
+} __attribute__((aligned(PAGE_SIZE)));
+DECLARE_PER_CPU(struct gdt_page, gdt_page);
 
 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
 {
-       return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
+       return per_cpu(gdt_page, cpu).gdt;
 }
 
+extern struct Xgt_desc_struct idt_descr;
 extern struct desc_struct idt_table[];
 extern void set_intr_gate(unsigned int irq, void * addr);
 
@@ -58,45 +59,33 @@ static inline void pack_gate(__u32 *a, __u32 *b,
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
-#define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
-
-#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
-#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+#define load_TR_desc() native_load_tr_desc()
+#define load_gdt(dtr) native_load_gdt(dtr)
+#define load_idt(dtr) native_load_idt(dtr)
 #define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
 #define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
 
-#define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
-#define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
-#define store_tr(tr) __asm__ ("str %0":"=m" (tr))
+#define store_gdt(dtr) native_store_gdt(dtr)
+#define store_idt(dtr) native_store_idt(dtr)
+#define store_tr(tr) (tr = native_store_tr())
 #define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
 
-#if TLS_SIZE != 24
-# error update this code.
-#endif
-
-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
-{
-#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
-       C(0); C(1); C(2);
-#undef C
-}
+#define load_TLS(t, cpu) native_load_tls(t, cpu)
+#define set_ldt native_set_ldt
 
 #define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
 #define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
 #define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#endif
 
-static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
+static inline void write_dt_entry(struct desc_struct *dt,
+                                 int entry, u32 entry_low, u32 entry_high)
 {
-       __u32 *lp = (__u32 *)((char *)dt + entry*8);
-       *lp = entry_a;
-       *(lp+1) = entry_b;
+       dt[entry].a = entry_low;
+       dt[entry].b = entry_high;
 }
 
-#define set_ldt native_set_ldt
-#endif /* CONFIG_PARAVIRT */
-
-static inline fastcall void native_set_ldt(const void *addr,
-                                          unsigned int entries)
+static inline void native_set_ldt(const void *addr, unsigned int entries)
 {
        if (likely(entries == 0))
                __asm__ __volatile__("lldt %w0"::"q" (0));
@@ -112,6 +101,48 @@ static inline fastcall void native_set_ldt(const void *addr,
        }
 }
 
+
+static inline void native_load_tr_desc(void)
+{
+       asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
+{
+       asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
+{
+       asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
+{
+       asm ("sgdt %0":"=m" (*dtr));
+}
+
+static inline void native_store_idt(struct Xgt_desc_struct *dtr)
+{
+       asm ("sidt %0":"=m" (*dtr));
+}
+
+static inline unsigned long native_store_tr(void)
+{
+       unsigned long tr;
+       asm ("str %0":"=r" (tr));
+       return tr;
+}
+
+static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+       unsigned int i;
+       struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+       for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+               gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+}
+
 static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
 {
        __u32 a, b;
index c5b8fc6..096a2a8 100644 (file)
@@ -38,6 +38,7 @@ extern struct e820map e820;
 
 extern int e820_all_mapped(unsigned long start, unsigned long end,
                           unsigned type);
+extern int e820_any_mapped(u64 start, u64 end, unsigned type);
 extern void find_max_pfn(void);
 extern void register_bootmem_low_pages(unsigned long max_low_pfn);
 extern void e820_register_memory(void);
index 952b3ee..d304ab4 100644 (file)
@@ -133,39 +133,31 @@ extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct
 #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
 
 #define VDSO_HIGH_BASE         (__fix_to_virt(FIX_VDSO))
-#define VDSO_BASE              ((unsigned long)current->mm->context.vdso)
-
-#ifdef CONFIG_COMPAT_VDSO
-# define VDSO_COMPAT_BASE      VDSO_HIGH_BASE
-# define VDSO_PRELINK          VDSO_HIGH_BASE
-#else
-# define VDSO_COMPAT_BASE      VDSO_BASE
-# define VDSO_PRELINK          0
-#endif
+#define VDSO_CURRENT_BASE      ((unsigned long)current->mm->context.vdso)
+#define VDSO_PRELINK           0
 
 #define VDSO_SYM(x) \
-               (VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
+               (VDSO_CURRENT_BASE + (unsigned long)(x) - VDSO_PRELINK)
 
 #define VDSO_HIGH_EHDR         ((const struct elfhdr *) VDSO_HIGH_BASE)
-#define VDSO_EHDR              ((const struct elfhdr *) VDSO_COMPAT_BASE)
+#define VDSO_EHDR              ((const struct elfhdr *) VDSO_CURRENT_BASE)
 
 extern void __kernel_vsyscall;
 
 #define VDSO_ENTRY             VDSO_SYM(&__kernel_vsyscall)
 
-#ifndef CONFIG_COMPAT_VDSO
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
 struct linux_binprm;
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
                                        int executable_stack);
-#endif
 
 extern unsigned int vdso_enabled;
 
-#define ARCH_DLINFO                                            \
-do if (vdso_enabled) {                                         \
-               NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY);            \
-               NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE); \
+#define ARCH_DLINFO                                                    \
+do if (vdso_enabled) {                                                 \
+               NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY);                    \
+               NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);        \
 } while (0)
 
 #endif
index 3e9f610..80ea052 100644 (file)
  * Leave one empty page between vmalloc'ed areas and
  * the start of the fixmap.
  */
-#ifndef CONFIG_COMPAT_VDSO
 extern unsigned long __FIXADDR_TOP;
-#else
-#define __FIXADDR_TOP  0xfffff000
-#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
-#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
-#endif
+#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
+#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
 
 #ifndef __ASSEMBLY__
 #include <linux/kernel.h>
@@ -87,6 +83,9 @@ enum fixed_addresses {
 #endif
 #ifdef CONFIG_PCI_MMCONFIG
        FIX_PCIE_MCFG,
+#endif
+#ifdef CONFIG_PARAVIRT
+       FIX_PARAVIRT_BOOTMAP,
 #endif
        __end_of_permanent_fixed_addresses,
        /* temporary boot-time mappings, used before ioremap() is functional */
index fd2be59..33e3ffe 100644 (file)
@@ -36,7 +36,7 @@ struct genapic {
        void (*init_apic_ldr)(void);
        physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map);
 
-       void (*clustered_apic_check)(void);
+       void (*setup_apic_routing)(void);
        int (*multi_timer_check)(int apic, int irq);
        int (*apicid_to_node)(int logical_apicid); 
        int (*cpu_to_logical_apicid)(int cpu);
@@ -99,7 +99,7 @@ struct genapic {
        APICFUNC(check_apicid_present) \
        APICFUNC(init_apic_ldr) \
        APICFUNC(ioapic_phys_id_map) \
-       APICFUNC(clustered_apic_check) \
+       APICFUNC(setup_apic_routing) \
        APICFUNC(multi_timer_check) \
        APICFUNC(apicid_to_node) \
        APICFUNC(cpu_to_logical_apicid) \
@@ -122,6 +122,6 @@ struct genapic {
        APICFUNC(phys_pkg_id) \
        }
 
-extern struct genapic *genapic, apic_default;
+extern struct genapic *genapic;
 
 #endif
index e9a34eb..13cdcd6 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
 #include <asm/tlbflush.h>
+#include <asm/paravirt.h>
 
 /* declarations for highmem.c */
 extern unsigned long highstart_pfn, highend_pfn;
@@ -67,11 +68,16 @@ extern void FASTCALL(kunmap_high(struct page *page));
 
 void *kmap(struct page *page);
 void kunmap(struct page *page);
+void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
 void *kmap_atomic(struct page *page, enum km_type type);
 void kunmap_atomic(void *kvaddr, enum km_type type);
 void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
 struct page *kmap_atomic_to_page(void *ptr);
 
+#ifndef CONFIG_PARAVIRT
+#define kmap_atomic_pte(page, type)    kmap_atomic(page, type)
+#endif
+
 #define flush_cache_kmaps()    do { } while (0)
 
 #endif /* __KERNEL__ */
index fc03cf9..dddeedf 100644 (file)
@@ -28,8 +28,6 @@
 
 #include <linux/timex.h>
 
-#include <asm/fixmap.h>
-
 /*
  * Documentation on HPET can be found at:
  *      http://www.intel.com/ial/home/sp/pcmmspec.htm
index 434936c..cdd1e24 100644 (file)
@@ -74,17 +74,18 @@ static inline void __save_init_fpu( struct task_struct *tsk )
        task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
-#define __unlazy_fpu( tsk ) do { \
-       if (task_thread_info(tsk)->status & TS_USEDFPU) \
-               save_init_fpu( tsk );                   \
-       else                                            \
-               tsk->fpu_counter = 0;                   \
+#define __unlazy_fpu( tsk ) do {                               \
+       if (task_thread_info(tsk)->status & TS_USEDFPU) {       \
+               __save_init_fpu(tsk);                           \
+               stts();                                         \
+       } else                                                  \
+               tsk->fpu_counter = 0;                           \
 } while (0)
 
 #define __clear_fpu( tsk )                                     \
 do {                                                           \
-       if (task_thread_info(tsk)->status & TS_USEDFPU) {               \
-               asm volatile("fnclex ; fwait");                         \
+       if (task_thread_info(tsk)->status & TS_USEDFPU) {       \
+               asm volatile("fnclex ; fwait");                 \
                task_thread_info(tsk)->status &= ~TS_USEDFPU;   \
                stts();                                         \
        }                                                       \
@@ -113,7 +114,7 @@ static inline void save_init_fpu( struct task_struct *tsk )
        __clear_fpu( tsk );     \
        preempt_enable();       \
 } while (0)
-                                       \
+
 /*
  * FPU state interaction...
  */
index 59fe616..e797586 100644 (file)
@@ -250,19 +250,22 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
+static inline void native_io_delay(void)
+{
+       asm volatile("outb %%al,$0x80" : : : "memory");
+}
+
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
 #else
 
-#define __SLOW_DOWN_IO "outb %%al,$0x80;"
-
 static inline void slow_down_io(void) {
-       __asm__ __volatile__(
-               __SLOW_DOWN_IO
+       native_io_delay();
 #ifdef REALLY_SLOW_IO
-               __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+       native_io_delay();
+       native_io_delay();
+       native_io_delay();
 #endif
-               : : );
 }
 
 #endif
index 11761cd..9e15ce0 100644 (file)
@@ -37,8 +37,6 @@ static __inline__ int irq_canonicalize(int irq)
 extern int irqbalance_disable(char *str);
 #endif
 
-extern void quirk_intel_irqbalance(void);
-
 #ifdef CONFIG_HOTPLUG_CPU
 extern void fixup_irqs(cpumask_t map);
 #endif
index a1b3f7f..3368b20 100644 (file)
@@ -1,25 +1,27 @@
 /*
  * Per-cpu current frame pointer - the location of the last exception frame on
- * the stack, stored in the PDA.
+ * the stack, stored in the per-cpu area.
  *
  * Jeremy Fitzhardinge <jeremy@goop.org>
  */
 #ifndef _ASM_I386_IRQ_REGS_H
 #define _ASM_I386_IRQ_REGS_H
 
-#include <asm/pda.h>
+#include <asm/percpu.h>
+
+DECLARE_PER_CPU(struct pt_regs *, irq_regs);
 
 static inline struct pt_regs *get_irq_regs(void)
 {
-       return read_pda(irq_regs);
+       return x86_read_percpu(irq_regs);
 }
 
 static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
 {
        struct pt_regs *old_regs;
 
-       old_regs = read_pda(irq_regs);
-       write_pda(irq_regs, new_regs);
+       old_regs = get_irq_regs();
+       x86_write_percpu(irq_regs, new_regs);
 
        return old_regs;
 }
index 17b18cf..eff8585 100644 (file)
@@ -9,6 +9,43 @@
  */
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
+#include <asm/processor-flags.h>
+
+#ifndef __ASSEMBLY__
+static inline unsigned long native_save_fl(void)
+{
+       unsigned long f;
+       asm volatile("pushfl ; popl %0":"=g" (f): /* no input */);
+       return f;
+}
+
+static inline void native_restore_fl(unsigned long f)
+{
+       asm volatile("pushl %0 ; popfl": /* no output */
+                            :"g" (f)
+                            :"memory", "cc");
+}
+
+static inline void native_irq_disable(void)
+{
+       asm volatile("cli": : :"memory");
+}
+
+static inline void native_irq_enable(void)
+{
+       asm volatile("sti": : :"memory");
+}
+
+static inline void native_safe_halt(void)
+{
+       asm volatile("sti; hlt": : :"memory");
+}
+
+static inline void native_halt(void)
+{
+       asm volatile("hlt": : :"memory");
+}
+#endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 
 static inline unsigned long __raw_local_save_flags(void)
 {
-       unsigned long flags;
-
-       __asm__ __volatile__(
-               "pushfl ; popl %0"
-               : "=g" (flags)
-               : /* no input */
-       );
-
-       return flags;
+       return native_save_fl();
 }
 
 static inline void raw_local_irq_restore(unsigned long flags)
 {
-       __asm__ __volatile__(
-               "pushl %0 ; popfl"
-               : /* no output */
-               :"g" (flags)
-               :"memory", "cc"
-       );
+       native_restore_fl(flags);
 }
 
 static inline void raw_local_irq_disable(void)
 {
-       __asm__ __volatile__("cli" : : : "memory");
+       native_irq_disable();
 }
 
 static inline void raw_local_irq_enable(void)
 {
-       __asm__ __volatile__("sti" : : : "memory");
+       native_irq_enable();
 }
 
 /*
@@ -54,7 +78,7 @@ static inline void raw_local_irq_enable(void)
  */
 static inline void raw_safe_halt(void)
 {
-       __asm__ __volatile__("sti; hlt" : : : "memory");
+       native_safe_halt();
 }
 
 /*
@@ -63,7 +87,7 @@ static inline void raw_safe_halt(void)
  */
 static inline void halt(void)
 {
-       __asm__ __volatile__("hlt": : :"memory");
+       native_halt();
 }
 
 /*
@@ -96,7 +120,7 @@ static inline unsigned long __raw_local_irq_save(void)
 
 static inline int raw_irqs_disabled_flags(unsigned long flags)
 {
-       return !(flags & (1 << 9));
+       return !(flags & X86_EFLAGS_IF);
 }
 
 static inline int raw_irqs_disabled(void)
index 4dfc9f5..bcb5b21 100644 (file)
@@ -21,7 +21,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <asm/fixmap.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
 
  * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
  * I.e. Maximum page that is mapped directly into kernel memory,
  * and kmap is not required.
- *
- * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
- * calculation for the amount of memory directly mappable into the
- * kernel memory space.
  */
 
 /* Maximum physical address we can use pages from */
@@ -47,6 +42,9 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_386
 
+/* We can also handle crash dumps from 64 bit kernel. */
+#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
+
 #define MAX_NOTE_BYTES 1024
 
 /* CPU does not save ss and esp on stack if execution is already
index 18b19a7..ebd319f 100644 (file)
@@ -71,7 +71,7 @@ static inline void init_apic_ldr(void)
        apic_write_around(APIC_LDR, val);
 }
 
-static inline void clustered_apic_check(void)
+static inline void setup_apic_routing(void)
 {
        printk("Enabling APIC mode:  %s.  Using %d I/O APICs\n",
                "Physflat", nr_ioapics);
index 3ef6292..6db1c3b 100644 (file)
@@ -54,7 +54,7 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
        return phys_map;
 }
 
-static inline void clustered_apic_check(void)
+static inline void setup_apic_routing(void)
 {
        printk("Enabling APIC mode:  %s.  Using %d I/O APICs\n",
                                        "Flat", nr_ioapics);
index 2633368..2d97892 100644 (file)
@@ -73,15 +73,8 @@ static inline void init_apic_ldr(void)
        apic_write_around(APIC_LDR, val);
 }
 
-extern void es7000_sw_apic(void);
-static inline void enable_apic_mode(void)
-{
-       es7000_sw_apic();
-       return;
-}
-
 extern int apic_version [MAX_APICS];
-static inline void clustered_apic_check(void)
+static inline void setup_apic_routing(void)
 {
        int apic = bios_cpu_apicid[smp_processor_id()];
        printk("Enabling APIC mode:  %s.  Using %d I/O APICs, target cpus %lx\n",
index 24990e5..b9fb784 100644 (file)
@@ -18,18 +18,6 @@ extern int parse_unisys_oem (char *oemptr);
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
 extern void setup_unisys(void);
 
-static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
-               char *productid)
-{
-       if (mpc->mpc_oemptr) {
-               struct mp_config_oemtable *oem_table =
-                       (struct mp_config_oemtable *)mpc->mpc_oemptr;
-               if (!strncmp(oem, "UNISYS", 6))
-                       return parse_unisys_oem((char *)oem_table);
-       }
-       return 0;
-}
-
 #ifdef CONFIG_ACPI
 
 static inline int es7000_check_dsdt(void)
@@ -41,26 +29,6 @@ static inline int es7000_check_dsdt(void)
                return 1;
        return 0;
 }
-
-/* Hook from generic ACPI tables.c */
-static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
-       unsigned long oem_addr;
-       if (!find_unisys_acpi_oem_table(&oem_addr)) {
-               if (es7000_check_dsdt())
-                       return parse_unisys_oem((char *)oem_addr);
-               else {
-                       setup_unisys();
-                       return 1;
-               }
-       }
-       return 0;
-}
-#else
-static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
-       return 0;
-}
 #endif
 
 #endif /* __ASM_MACH_MPPARSE_H */
index d9dc039..a236e70 100644 (file)
@@ -13,7 +13,7 @@
 #define apic_id_registered (genapic->apic_id_registered)
 #define init_apic_ldr (genapic->init_apic_ldr)
 #define ioapic_phys_id_map (genapic->ioapic_phys_id_map)
-#define clustered_apic_check (genapic->clustered_apic_check) 
+#define setup_apic_routing (genapic->setup_apic_routing)
 #define multi_timer_check (genapic->multi_timer_check)
 #define apicid_to_node (genapic->apicid_to_node)
 #define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) 
index 9d15809..5e5e7dd 100644 (file)
@@ -34,7 +34,7 @@ static inline void init_apic_ldr(void)
        /* Already done in NUMA-Q firmware */
 }
 
-static inline void clustered_apic_check(void)
+static inline void setup_apic_routing(void)
 {
        printk("Enabling APIC mode:  %s.  Using %d I/O APICs\n",
                "NUMA-Q", nr_ioapics);
index 43e5bd8..732f776 100644 (file)
@@ -80,7 +80,7 @@ static inline int apic_id_registered(void)
        return 1;
 }
 
-static inline void clustered_apic_check(void)
+static inline void setup_apic_routing(void)
 {
        printk("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
                                                nr_ioapics);
index 9426839..c252053 100644 (file)
@@ -30,7 +30,7 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
                        (!strncmp(productid, "VIGIL SMP", 9) 
                         || !strncmp(productid, "EXA", 3)
                         || !strncmp(productid, "RUTHLESS SMP", 12))){
-               mark_tsc_unstable();
+               mark_tsc_unstable("Summit based system");
                use_cyclone = 1; /*enable cyclone-timer*/
                setup_summit();
                return 1;
@@ -44,7 +44,7 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        if (!strncmp(oem_id, "IBM", 3) &&
            (!strncmp(oem_table_id, "SERVIGIL", 8)
             || !strncmp(oem_table_id, "EXA", 3))){
-               mark_tsc_unstable();
+               mark_tsc_unstable("Summit based system");
                use_cyclone = 1; /*enable cyclone-timer*/
                setup_summit();
                return 1;
index 18afe6b..efac6f0 100644 (file)
@@ -47,7 +47,7 @@ static inline void summit_check(char *oem, char *productid)
 {
 }
 
-static inline void clustered_apic_check(void)
+static inline void setup_apic_routing(void)
 {
 }
 
index e6aa30f..8198d1c 100644 (file)
@@ -5,6 +5,16 @@
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#include <asm/paravirt.h>
+#ifndef CONFIG_PARAVIRT
+#include <asm-generic/mm_hooks.h>
+
+static inline void paravirt_activate_mm(struct mm_struct *prev,
+                                       struct mm_struct *next)
+{
+}
+#endif /* !CONFIG_PARAVIRT */
+
 
 /*
  * Used for LDT copy/destruction.
@@ -65,7 +75,10 @@ static inline void switch_mm(struct mm_struct *prev,
 #define deactivate_mm(tsk, mm)                 \
        asm("movl %0,%%gs": :"r" (0));
 
-#define activate_mm(prev, next) \
-       switch_mm((prev),(next),NULL)
+#define activate_mm(prev, next)                                \
+       do {                                            \
+               paravirt_activate_mm(prev, next);       \
+               switch_mm((prev),(next),NULL);          \
+       } while(0);
 
 #endif
index 02f8f54..7e5fda6 100644 (file)
@@ -54,6 +54,8 @@ struct mod_arch_specific
 #define MODULE_PROC_FAMILY "CYRIXIII "
 #elif defined CONFIG_MVIAC3_2
 #define MODULE_PROC_FAMILY "VIAC3-2 "
+#elif defined CONFIG_MVIAC7
+#define MODULE_PROC_FAMILY "VIAC7 "
 #elif defined CONFIG_MGEODEGX1
 #define MODULE_PROC_FAMILY "GEODEGX1 "
 #elif defined CONFIG_MGEODE_LX
diff --git a/include/asm-i386/msr-index.h b/include/asm-i386/msr-index.h
new file mode 100644 (file)
index 0000000..a02eb29
--- /dev/null
@@ -0,0 +1,278 @@
+#ifndef __ASM_MSR_INDEX_H
+#define __ASM_MSR_INDEX_H
+
+/* CPU model specific register (MSR) numbers */
+
+/* x86-64 specific MSRs */
+#define MSR_EFER               0xc0000080 /* extended feature register */
+#define MSR_STAR               0xc0000081 /* legacy mode SYSCALL target */
+#define MSR_LSTAR              0xc0000082 /* long mode SYSCALL target */
+#define MSR_CSTAR              0xc0000083 /* compat mode SYSCALL target */
+#define MSR_SYSCALL_MASK       0xc0000084 /* EFLAGS mask for syscall */
+#define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
+#define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
+#define MSR_KERNEL_GS_BASE     0xc0000102 /* SwapGS GS shadow */
+
+/* EFER bits: */
+#define _EFER_SCE              0  /* SYSCALL/SYSRET */
+#define _EFER_LME              8  /* Long mode enable */
+#define _EFER_LMA              10 /* Long mode active (read-only) */
+#define _EFER_NX               11 /* No execute enable */
+
+#define EFER_SCE               (1<<_EFER_SCE)
+#define EFER_LME               (1<<_EFER_LME)
+#define EFER_LMA               (1<<_EFER_LMA)
+#define EFER_NX                        (1<<_EFER_NX)
+
+/* Intel MSRs. Some also available on other CPUs */
+#define MSR_IA32_PERFCTR0              0x000000c1
+#define MSR_IA32_PERFCTR1              0x000000c2
+#define MSR_FSB_FREQ                   0x000000cd
+
+#define MSR_MTRRcap                    0x000000fe
+#define MSR_IA32_BBL_CR_CTL            0x00000119
+
+#define MSR_IA32_SYSENTER_CS           0x00000174
+#define MSR_IA32_SYSENTER_ESP          0x00000175
+#define MSR_IA32_SYSENTER_EIP          0x00000176
+
+#define MSR_IA32_MCG_CAP               0x00000179
+#define MSR_IA32_MCG_STATUS            0x0000017a
+#define MSR_IA32_MCG_CTL               0x0000017b
+
+#define MSR_IA32_PEBS_ENABLE           0x000003f1
+#define MSR_IA32_DS_AREA               0x00000600
+#define MSR_IA32_PERF_CAPABILITIES     0x00000345
+
+#define MSR_MTRRfix64K_00000           0x00000250
+#define MSR_MTRRfix16K_80000           0x00000258
+#define MSR_MTRRfix16K_A0000           0x00000259
+#define MSR_MTRRfix4K_C0000            0x00000268
+#define MSR_MTRRfix4K_C8000            0x00000269
+#define MSR_MTRRfix4K_D0000            0x0000026a
+#define MSR_MTRRfix4K_D8000            0x0000026b
+#define MSR_MTRRfix4K_E0000            0x0000026c
+#define MSR_MTRRfix4K_E8000            0x0000026d
+#define MSR_MTRRfix4K_F0000            0x0000026e
+#define MSR_MTRRfix4K_F8000            0x0000026f
+#define MSR_MTRRdefType                        0x000002ff
+
+#define MSR_IA32_DEBUGCTLMSR           0x000001d9
+#define MSR_IA32_LASTBRANCHFROMIP      0x000001db
+#define MSR_IA32_LASTBRANCHTOIP                0x000001dc
+#define MSR_IA32_LASTINTFROMIP         0x000001dd
+#define MSR_IA32_LASTINTTOIP           0x000001de
+
+#define MSR_IA32_MC0_CTL               0x00000400
+#define MSR_IA32_MC0_STATUS            0x00000401
+#define MSR_IA32_MC0_ADDR              0x00000402
+#define MSR_IA32_MC0_MISC              0x00000403
+
+#define MSR_P6_PERFCTR0                        0x000000c1
+#define MSR_P6_PERFCTR1                        0x000000c2
+#define MSR_P6_EVNTSEL0                        0x00000186
+#define MSR_P6_EVNTSEL1                        0x00000187
+
+/* K7/K8 MSRs. Not complete. See the architecture manual for a more
+   complete list. */
+#define MSR_K7_EVNTSEL0                        0xc0010000
+#define MSR_K7_PERFCTR0                        0xc0010004
+#define MSR_K7_EVNTSEL1                        0xc0010001
+#define MSR_K7_PERFCTR1                        0xc0010005
+#define MSR_K7_EVNTSEL2                        0xc0010002
+#define MSR_K7_PERFCTR2                        0xc0010006
+#define MSR_K7_EVNTSEL3                        0xc0010003
+#define MSR_K7_PERFCTR3                        0xc0010007
+#define MSR_K8_TOP_MEM1                        0xc001001a
+#define MSR_K7_CLK_CTL                 0xc001001b
+#define MSR_K8_TOP_MEM2                        0xc001001d
+#define MSR_K8_SYSCFG                  0xc0010010
+
+#define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
+#define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
+#define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
+
+#define MSR_K7_HWCR                    0xc0010015
+#define MSR_K8_HWCR                    0xc0010015
+#define MSR_K7_FID_VID_CTL             0xc0010041
+#define MSR_K7_FID_VID_STATUS          0xc0010042
+#define MSR_K8_ENABLE_C1E              0xc0010055
+
+/* K6 MSRs */
+#define MSR_K6_EFER                    0xc0000080
+#define MSR_K6_STAR                    0xc0000081
+#define MSR_K6_WHCR                    0xc0000082
+#define MSR_K6_UWCCR                   0xc0000085
+#define MSR_K6_EPMR                    0xc0000086
+#define MSR_K6_PSOR                    0xc0000087
+#define MSR_K6_PFIR                    0xc0000088
+
+/* Centaur-Hauls/IDT defined MSRs. */
+#define MSR_IDT_FCR1                   0x00000107
+#define MSR_IDT_FCR2                   0x00000108
+#define MSR_IDT_FCR3                   0x00000109
+#define MSR_IDT_FCR4                   0x0000010a
+
+#define MSR_IDT_MCR0                   0x00000110
+#define MSR_IDT_MCR1                   0x00000111
+#define MSR_IDT_MCR2                   0x00000112
+#define MSR_IDT_MCR3                   0x00000113
+#define MSR_IDT_MCR4                   0x00000114
+#define MSR_IDT_MCR5                   0x00000115
+#define MSR_IDT_MCR6                   0x00000116
+#define MSR_IDT_MCR7                   0x00000117
+#define MSR_IDT_MCR_CTRL               0x00000120
+
+/* VIA Cyrix defined MSRs*/
+#define MSR_VIA_FCR                    0x00001107
+#define MSR_VIA_LONGHAUL               0x0000110a
+#define MSR_VIA_RNG                    0x0000110b
+#define MSR_VIA_BCR2                   0x00001147
+
+/* Transmeta defined MSRs */
+#define MSR_TMTA_LONGRUN_CTRL          0x80868010
+#define MSR_TMTA_LONGRUN_FLAGS         0x80868011
+#define MSR_TMTA_LRTI_READOUT          0x80868018
+#define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
+
+/* Intel defined MSRs. */
+#define MSR_IA32_P5_MC_ADDR            0x00000000
+#define MSR_IA32_P5_MC_TYPE            0x00000001
+#define MSR_IA32_TSC                   0x00000010
+#define MSR_IA32_PLATFORM_ID           0x00000017
+#define MSR_IA32_EBL_CR_POWERON                0x0000002a
+
+#define MSR_IA32_APICBASE              0x0000001b
+#define MSR_IA32_APICBASE_BSP          (1<<8)
+#define MSR_IA32_APICBASE_ENABLE       (1<<11)
+#define MSR_IA32_APICBASE_BASE         (0xfffff<<12)
+
+#define MSR_IA32_UCODE_WRITE           0x00000079
+#define MSR_IA32_UCODE_REV             0x0000008b
+
+#define MSR_IA32_PERF_STATUS           0x00000198
+#define MSR_IA32_PERF_CTL              0x00000199
+
+#define MSR_IA32_MPERF                 0x000000e7
+#define MSR_IA32_APERF                 0x000000e8
+
+#define MSR_IA32_THERM_CONTROL         0x0000019a
+#define MSR_IA32_THERM_INTERRUPT       0x0000019b
+#define MSR_IA32_THERM_STATUS          0x0000019c
+#define MSR_IA32_MISC_ENABLE           0x000001a0
+
+/* Intel Model 6 */
+#define MSR_P6_EVNTSEL0                        0x00000186
+#define MSR_P6_EVNTSEL1                        0x00000187
+
+/* P4/Xeon+ specific */
+#define MSR_IA32_MCG_EAX               0x00000180
+#define MSR_IA32_MCG_EBX               0x00000181
+#define MSR_IA32_MCG_ECX               0x00000182
+#define MSR_IA32_MCG_EDX               0x00000183
+#define MSR_IA32_MCG_ESI               0x00000184
+#define MSR_IA32_MCG_EDI               0x00000185
+#define MSR_IA32_MCG_EBP               0x00000186
+#define MSR_IA32_MCG_ESP               0x00000187
+#define MSR_IA32_MCG_EFLAGS            0x00000188
+#define MSR_IA32_MCG_EIP               0x00000189
+#define MSR_IA32_MCG_RESERVED          0x0000018a
+
+/* Pentium IV performance counter MSRs */
+#define MSR_P4_BPU_PERFCTR0            0x00000300
+#define MSR_P4_BPU_PERFCTR1            0x00000301
+#define MSR_P4_BPU_PERFCTR2            0x00000302
+#define MSR_P4_BPU_PERFCTR3            0x00000303
+#define MSR_P4_MS_PERFCTR0             0x00000304
+#define MSR_P4_MS_PERFCTR1             0x00000305
+#define MSR_P4_MS_PERFCTR2             0x00000306
+#define MSR_P4_MS_PERFCTR3             0x00000307
+#define MSR_P4_FLAME_PERFCTR0          0x00000308
+#define MSR_P4_FLAME_PERFCTR1          0x00000309
+#define MSR_P4_FLAME_PERFCTR2          0x0000030a
+#define MSR_P4_FLAME_PERFCTR3          0x0000030b
+#define MSR_P4_IQ_PERFCTR0             0x0000030c
+#define MSR_P4_IQ_PERFCTR1             0x0000030d
+#define MSR_P4_IQ_PERFCTR2             0x0000030e
+#define MSR_P4_IQ_PERFCTR3             0x0000030f
+#define MSR_P4_IQ_PERFCTR4             0x00000310
+#define MSR_P4_IQ_PERFCTR5             0x00000311
+#define MSR_P4_BPU_CCCR0               0x00000360
+#define MSR_P4_BPU_CCCR1               0x00000361
+#define MSR_P4_BPU_CCCR2               0x00000362
+#define MSR_P4_BPU_CCCR3               0x00000363
+#define MSR_P4_MS_CCCR0                        0x00000364
+#define MSR_P4_MS_CCCR1                        0x00000365
+#define MSR_P4_MS_CCCR2                        0x00000366
+#define MSR_P4_MS_CCCR3                        0x00000367
+#define MSR_P4_FLAME_CCCR0             0x00000368
+#define MSR_P4_FLAME_CCCR1             0x00000369
+#define MSR_P4_FLAME_CCCR2             0x0000036a
+#define MSR_P4_FLAME_CCCR3             0x0000036b
+#define MSR_P4_IQ_CCCR0                        0x0000036c
+#define MSR_P4_IQ_CCCR1                        0x0000036d
+#define MSR_P4_IQ_CCCR2                        0x0000036e
+#define MSR_P4_IQ_CCCR3                        0x0000036f
+#define MSR_P4_IQ_CCCR4                        0x00000370
+#define MSR_P4_IQ_CCCR5                        0x00000371
+#define MSR_P4_ALF_ESCR0               0x000003ca
+#define MSR_P4_ALF_ESCR1               0x000003cb
+#define MSR_P4_BPU_ESCR0               0x000003b2
+#define MSR_P4_BPU_ESCR1               0x000003b3
+#define MSR_P4_BSU_ESCR0               0x000003a0
+#define MSR_P4_BSU_ESCR1               0x000003a1
+#define MSR_P4_CRU_ESCR0               0x000003b8
+#define MSR_P4_CRU_ESCR1               0x000003b9
+#define MSR_P4_CRU_ESCR2               0x000003cc
+#define MSR_P4_CRU_ESCR3               0x000003cd
+#define MSR_P4_CRU_ESCR4               0x000003e0
+#define MSR_P4_CRU_ESCR5               0x000003e1
+#define MSR_P4_DAC_ESCR0               0x000003a8
+#define MSR_P4_DAC_ESCR1               0x000003a9
+#define MSR_P4_FIRM_ESCR0              0x000003a4
+#define MSR_P4_FIRM_ESCR1              0x000003a5
+#define MSR_P4_FLAME_ESCR0             0x000003a6
+#define MSR_P4_FLAME_ESCR1             0x000003a7
+#define MSR_P4_FSB_ESCR0               0x000003a2
+#define MSR_P4_FSB_ESCR1               0x000003a3
+#define MSR_P4_IQ_ESCR0                        0x000003ba
+#define MSR_P4_IQ_ESCR1                        0x000003bb
+#define MSR_P4_IS_ESCR0                        0x000003b4
+#define MSR_P4_IS_ESCR1                        0x000003b5
+#define MSR_P4_ITLB_ESCR0              0x000003b6
+#define MSR_P4_ITLB_ESCR1              0x000003b7
+#define MSR_P4_IX_ESCR0                        0x000003c8
+#define MSR_P4_IX_ESCR1                        0x000003c9
+#define MSR_P4_MOB_ESCR0               0x000003aa
+#define MSR_P4_MOB_ESCR1               0x000003ab
+#define MSR_P4_MS_ESCR0                        0x000003c0
+#define MSR_P4_MS_ESCR1                        0x000003c1
+#define MSR_P4_PMH_ESCR0               0x000003ac
+#define MSR_P4_PMH_ESCR1               0x000003ad
+#define MSR_P4_RAT_ESCR0               0x000003bc
+#define MSR_P4_RAT_ESCR1               0x000003bd
+#define MSR_P4_SAAT_ESCR0              0x000003ae
+#define MSR_P4_SAAT_ESCR1              0x000003af
+#define MSR_P4_SSU_ESCR0               0x000003be
+#define MSR_P4_SSU_ESCR1               0x000003bf /* guess: not in manual */
+
+#define MSR_P4_TBPU_ESCR0              0x000003c2
+#define MSR_P4_TBPU_ESCR1              0x000003c3
+#define MSR_P4_TC_ESCR0                        0x000003c4
+#define MSR_P4_TC_ESCR1                        0x000003c5
+#define MSR_P4_U2L_ESCR0               0x000003b0
+#define MSR_P4_U2L_ESCR1               0x000003b1
+
+/* Intel Core-based CPU performance counters */
+#define MSR_CORE_PERF_FIXED_CTR0       0x00000309
+#define MSR_CORE_PERF_FIXED_CTR1       0x0000030a
+#define MSR_CORE_PERF_FIXED_CTR2       0x0000030b
+#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x0000038d
+#define MSR_CORE_PERF_GLOBAL_STATUS    0x0000038e
+#define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
+
+/* Geode defined MSRs */
+#define MSR_GEODE_BUSCONT_CONF0                0x00001900
+
+#endif /* __ASM_MSR_INDEX_H */
index 2ad3f30..9559894 100644 (file)
@@ -1,6 +1,79 @@
 #ifndef __ASM_MSR_H
 #define __ASM_MSR_H
 
+#include <asm/msr-index.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <asm/errno.h>
+
+static inline unsigned long long native_read_msr(unsigned int msr)
+{
+       unsigned long long val;
+
+       asm volatile("rdmsr" : "=A" (val) : "c" (msr));
+       return val;
+}
+
+static inline unsigned long long native_read_msr_safe(unsigned int msr,
+                                                     int *err)
+{
+       unsigned long long val;
+
+       asm volatile("2: rdmsr ; xorl %0,%0\n"
+                    "1:\n\t"
+                    ".section .fixup,\"ax\"\n\t"
+                    "3:  movl %3,%0 ; jmp 1b\n\t"
+                    ".previous\n\t"
+                    ".section __ex_table,\"a\"\n"
+                    "   .align 4\n\t"
+                    "   .long  2b,3b\n\t"
+                    ".previous"
+                    : "=r" (*err), "=A" (val)
+                    : "c" (msr), "i" (-EFAULT));
+
+       return val;
+}
+
+static inline void native_write_msr(unsigned int msr, unsigned long long val)
+{
+       asm volatile("wrmsr" : : "c" (msr), "A"(val));
+}
+
+static inline int native_write_msr_safe(unsigned int msr,
+                                       unsigned long long val)
+{
+       int err;
+       asm volatile("2: wrmsr ; xorl %0,%0\n"
+                    "1:\n\t"
+                    ".section .fixup,\"ax\"\n\t"
+                    "3:  movl %4,%0 ; jmp 1b\n\t"
+                    ".previous\n\t"
+                    ".section __ex_table,\"a\"\n"
+                    "   .align 4\n\t"
+                    "   .long  2b,3b\n\t"
+                    ".previous"
+                    : "=a" (err)
+                    : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)),
+                      "i" (-EFAULT));
+       return err;
+}
+
+static inline unsigned long long native_read_tsc(void)
+{
+       unsigned long long val;
+       asm volatile("rdtsc" : "=A" (val));
+       return val;
+}
+
+static inline unsigned long long native_read_pmc(void)
+{
+       unsigned long long val;
+       asm volatile("rdpmc" : "=A" (val));
+       return val;
+}
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
  * pointer indirection), this allows gcc to optimize better
  */
 
-#define rdmsr(msr,val1,val2) \
-       __asm__ __volatile__("rdmsr" \
-                         : "=a" (val1), "=d" (val2) \
-                         : "c" (msr))
+#define rdmsr(msr,val1,val2)                                           \
+       do {                                                            \
+               unsigned long long __val = native_read_msr(msr);        \
+               val1 = __val;                                           \
+               val2 = __val >> 32;                                     \
+       } while(0)
 
-#define wrmsr(msr,val1,val2) \
-       __asm__ __volatile__("wrmsr" \
-                         : /* no outputs */ \
-                         : "c" (msr), "a" (val1), "d" (val2))
+#define wrmsr(msr,val1,val2)                                           \
+       native_write_msr(msr, ((unsigned long long)val2 << 32) | val1)
 
-#define rdmsrl(msr,val) do { \
-       unsigned long l__,h__; \
-       rdmsr (msr, l__, h__);  \
-       val = l__;  \
-       val |= ((u64)h__<<32);  \
-} while(0)
+#define rdmsrl(msr,val)                                        \
+       do {                                            \
+               (val) = native_read_msr(msr);           \
+       } while(0)
 
 static inline void wrmsrl (unsigned long msr, unsigned long long val)
 {
@@ -37,50 +108,41 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
 }
 
 /* wrmsr with exception handling */
-#define wrmsr_safe(msr,a,b) ({ int ret__;                                              \
-       asm volatile("2: wrmsr ; xorl %0,%0\n"                                          \
-                    "1:\n\t"                                                           \
-                    ".section .fixup,\"ax\"\n\t"                                       \
-                    "3:  movl %4,%0 ; jmp 1b\n\t"                                      \
-                    ".previous\n\t"                                                    \
-                    ".section __ex_table,\"a\"\n"                                      \
-                    "   .align 4\n\t"                                                  \
-                    "   .long  2b,3b\n\t"                                              \
-                    ".previous"                                                        \
-                    : "=a" (ret__)                                                     \
-                    : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
-       ret__; })
+#define wrmsr_safe(msr,val1,val2)                                              \
+       (native_write_msr_safe(msr, ((unsigned long long)val2 << 32) | val1))
 
 /* rdmsr with exception handling */
-#define rdmsr_safe(msr,a,b) ({ int ret__;                                              \
-       asm volatile("2: rdmsr ; xorl %0,%0\n"                                          \
-                    "1:\n\t"                                                           \
-                    ".section .fixup,\"ax\"\n\t"                                       \
-                    "3:  movl %4,%0 ; jmp 1b\n\t"                                      \
-                    ".previous\n\t"                                                    \
-                    ".section __ex_table,\"a\"\n"                                      \
-                    "   .align 4\n\t"                                                  \
-                    "   .long  2b,3b\n\t"                                              \
-                    ".previous"                                                        \
-                    : "=r" (ret__), "=a" (*(a)), "=d" (*(b))                           \
-                    : "c" (msr), "i" (-EFAULT));\
-       ret__; })
-
-#define rdtsc(low,high) \
-     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
-
-#define rdtscl(low) \
-     __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
-
-#define rdtscll(val) \
-     __asm__ __volatile__("rdtsc" : "=A" (val))
+#define rdmsr_safe(msr,p1,p2)                                          \
+       ({                                                              \
+               int __err;                                              \
+               unsigned long long __val = native_read_msr_safe(msr, &__err);\
+               (*p1) = __val;                                          \
+               (*p2) = __val >> 32;                                    \
+               __err;                                                  \
+       })
+
+#define rdtsc(low,high)                                                \
+       do {                                                    \
+               u64 _l = native_read_tsc();                     \
+               (low) = (u32)_l;                                \
+               (high) = _l >> 32;                              \
+       } while(0)
+
+#define rdtscl(low)                                            \
+       do {                                                    \
+               (low) = native_read_tsc();                      \
+       } while(0)
+
+#define rdtscll(val) ((val) = native_read_tsc())
 
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
-#define rdpmc(counter,low,high) \
-     __asm__ __volatile__("rdpmc" \
-                         : "=a" (low), "=d" (high) \
-                         : "c" (counter))
+#define rdpmc(counter,low,high)                                        \
+       do {                                                    \
+               u64 _l = native_read_pmc();                     \
+               low = (u32)_l;                                  \
+               high = _l >> 32;                                \
+       } while(0)
 #endif /* !CONFIG_PARAVIRT */
 
 #ifdef CONFIG_SMP
@@ -96,234 +158,6 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
        wrmsr(msr_no, l, h);
 }
 #endif  /*  CONFIG_SMP  */
-
-/* symbolic names for some interesting MSRs */
-/* Intel defined MSRs. */
-#define MSR_IA32_P5_MC_ADDR            0
-#define MSR_IA32_P5_MC_TYPE            1
-#define MSR_IA32_PLATFORM_ID           0x17
-#define MSR_IA32_EBL_CR_POWERON                0x2a
-
-#define MSR_IA32_APICBASE              0x1b
-#define MSR_IA32_APICBASE_BSP          (1<<8)
-#define MSR_IA32_APICBASE_ENABLE       (1<<11)
-#define MSR_IA32_APICBASE_BASE         (0xfffff<<12)
-
-#define MSR_IA32_UCODE_WRITE           0x79
-#define MSR_IA32_UCODE_REV             0x8b
-
-#define MSR_P6_PERFCTR0                0xc1
-#define MSR_P6_PERFCTR1                0xc2
-#define MSR_FSB_FREQ           0xcd
-
-
-#define MSR_IA32_BBL_CR_CTL            0x119
-
-#define MSR_IA32_SYSENTER_CS           0x174
-#define MSR_IA32_SYSENTER_ESP          0x175
-#define MSR_IA32_SYSENTER_EIP          0x176
-
-#define MSR_IA32_MCG_CAP               0x179
-#define MSR_IA32_MCG_STATUS            0x17a
-#define MSR_IA32_MCG_CTL               0x17b
-
-/* P4/Xeon+ specific */
-#define MSR_IA32_MCG_EAX               0x180
-#define MSR_IA32_MCG_EBX               0x181
-#define MSR_IA32_MCG_ECX               0x182
-#define MSR_IA32_MCG_EDX               0x183
-#define MSR_IA32_MCG_ESI               0x184
-#define MSR_IA32_MCG_EDI               0x185
-#define MSR_IA32_MCG_EBP               0x186
-#define MSR_IA32_MCG_ESP               0x187
-#define MSR_IA32_MCG_EFLAGS            0x188
-#define MSR_IA32_MCG_EIP               0x189
-#define MSR_IA32_MCG_RESERVED          0x18A
-
-#define MSR_P6_EVNTSEL0                        0x186
-#define MSR_P6_EVNTSEL1                        0x187
-
-#define MSR_IA32_PERF_STATUS           0x198
-#define MSR_IA32_PERF_CTL              0x199
-
-#define MSR_IA32_MPERF                 0xE7
-#define MSR_IA32_APERF                 0xE8
-
-#define MSR_IA32_THERM_CONTROL         0x19a
-#define MSR_IA32_THERM_INTERRUPT       0x19b
-#define MSR_IA32_THERM_STATUS          0x19c
-#define MSR_IA32_MISC_ENABLE           0x1a0
-
-#define MSR_IA32_DEBUGCTLMSR           0x1d9
-#define MSR_IA32_LASTBRANCHFROMIP      0x1db
-#define MSR_IA32_LASTBRANCHTOIP                0x1dc
-#define MSR_IA32_LASTINTFROMIP         0x1dd
-#define MSR_IA32_LASTINTTOIP           0x1de
-
-#define MSR_IA32_MC0_CTL               0x400
-#define MSR_IA32_MC0_STATUS            0x401
-#define MSR_IA32_MC0_ADDR              0x402
-#define MSR_IA32_MC0_MISC              0x403
-
-#define MSR_IA32_PEBS_ENABLE           0x3f1
-#define MSR_IA32_DS_AREA               0x600
-#define MSR_IA32_PERF_CAPABILITIES     0x345
-
-/* Pentium IV performance counter MSRs */
-#define MSR_P4_BPU_PERFCTR0            0x300
-#define MSR_P4_BPU_PERFCTR1            0x301
-#define MSR_P4_BPU_PERFCTR2            0x302
-#define MSR_P4_BPU_PERFCTR3            0x303
-#define MSR_P4_MS_PERFCTR0             0x304
-#define MSR_P4_MS_PERFCTR1             0x305
-#define MSR_P4_MS_PERFCTR2             0x306
-#define MSR_P4_MS_PERFCTR3             0x307
-#define MSR_P4_FLAME_PERFCTR0          0x308
-#define MSR_P4_FLAME_PERFCTR1          0x309
-#define MSR_P4_FLAME_PERFCTR2          0x30a
-#define MSR_P4_FLAME_PERFCTR3          0x30b
-#define MSR_P4_IQ_PERFCTR0             0x30c
-#define MSR_P4_IQ_PERFCTR1             0x30d
-#define MSR_P4_IQ_PERFCTR2             0x30e
-#define MSR_P4_IQ_PERFCTR3             0x30f
-#define MSR_P4_IQ_PERFCTR4             0x310
-#define MSR_P4_IQ_PERFCTR5             0x311
-#define MSR_P4_BPU_CCCR0               0x360
-#define MSR_P4_BPU_CCCR1               0x361
-#define MSR_P4_BPU_CCCR2               0x362
-#define MSR_P4_BPU_CCCR3               0x363
-#define MSR_P4_MS_CCCR0                0x364
-#define MSR_P4_MS_CCCR1                0x365
-#define MSR_P4_MS_CCCR2                0x366
-#define MSR_P4_MS_CCCR3                0x367
-#define MSR_P4_FLAME_CCCR0             0x368
-#define MSR_P4_FLAME_CCCR1             0x369
-#define MSR_P4_FLAME_CCCR2             0x36a
-#define MSR_P4_FLAME_CCCR3             0x36b
-#define MSR_P4_IQ_CCCR0                0x36c
-#define MSR_P4_IQ_CCCR1                0x36d
-#define MSR_P4_IQ_CCCR2                0x36e
-#define MSR_P4_IQ_CCCR3                0x36f
-#define MSR_P4_IQ_CCCR4                0x370
-#define MSR_P4_IQ_CCCR5                0x371
-#define MSR_P4_ALF_ESCR0               0x3ca
-#define MSR_P4_ALF_ESCR1               0x3cb
-#define MSR_P4_BPU_ESCR0               0x3b2
-#define MSR_P4_BPU_ESCR1               0x3b3
-#define MSR_P4_BSU_ESCR0               0x3a0
-#define MSR_P4_BSU_ESCR1               0x3a1
-#define MSR_P4_CRU_ESCR0               0x3b8
-#define MSR_P4_CRU_ESCR1               0x3b9
-#define MSR_P4_CRU_ESCR2               0x3cc
-#define MSR_P4_CRU_ESCR3               0x3cd
-#define MSR_P4_CRU_ESCR4               0x3e0
-#define MSR_P4_CRU_ESCR5               0x3e1
-#define MSR_P4_DAC_ESCR0               0x3a8
-#define MSR_P4_DAC_ESCR1               0x3a9
-#define MSR_P4_FIRM_ESCR0              0x3a4
-#define MSR_P4_FIRM_ESCR1              0x3a5
-#define MSR_P4_FLAME_ESCR0             0x3a6
-#define MSR_P4_FLAME_ESCR1             0x3a7
-#define MSR_P4_FSB_ESCR0               0x3a2
-#define MSR_P4_FSB_ESCR1               0x3a3
-#define MSR_P4_IQ_ESCR0                0x3ba
-#define MSR_P4_IQ_ESCR1                0x3bb
-#define MSR_P4_IS_ESCR0                0x3b4
-#define MSR_P4_IS_ESCR1                0x3b5
-#define MSR_P4_ITLB_ESCR0              0x3b6
-#define MSR_P4_ITLB_ESCR1              0x3b7
-#define MSR_P4_IX_ESCR0                0x3c8
-#define MSR_P4_IX_ESCR1                0x3c9
-#define MSR_P4_MOB_ESCR0               0x3aa
-#define MSR_P4_MOB_ESCR1               0x3ab
-#define MSR_P4_MS_ESCR0                0x3c0
-#define MSR_P4_MS_ESCR1                0x3c1
-#define MSR_P4_PMH_ESCR0               0x3ac
-#define MSR_P4_PMH_ESCR1               0x3ad
-#define MSR_P4_RAT_ESCR0               0x3bc
-#define MSR_P4_RAT_ESCR1               0x3bd
-#define MSR_P4_SAAT_ESCR0              0x3ae
-#define MSR_P4_SAAT_ESCR1              0x3af
-#define MSR_P4_SSU_ESCR0               0x3be
-#define MSR_P4_SSU_ESCR1               0x3bf    /* guess: not defined in manual */
-#define MSR_P4_TBPU_ESCR0              0x3c2
-#define MSR_P4_TBPU_ESCR1              0x3c3
-#define MSR_P4_TC_ESCR0                0x3c4
-#define MSR_P4_TC_ESCR1                0x3c5
-#define MSR_P4_U2L_ESCR0               0x3b0
-#define MSR_P4_U2L_ESCR1               0x3b1
-
-/* AMD Defined MSRs */
-#define MSR_K6_EFER                    0xC0000080
-#define MSR_K6_STAR                    0xC0000081
-#define MSR_K6_WHCR                    0xC0000082
-#define MSR_K6_UWCCR                   0xC0000085
-#define MSR_K6_EPMR                    0xC0000086
-#define MSR_K6_PSOR                    0xC0000087
-#define MSR_K6_PFIR                    0xC0000088
-
-#define MSR_K7_EVNTSEL0                        0xC0010000
-#define MSR_K7_EVNTSEL1                        0xC0010001
-#define MSR_K7_EVNTSEL2                        0xC0010002
-#define MSR_K7_EVNTSEL3                        0xC0010003
-#define MSR_K7_PERFCTR0                        0xC0010004
-#define MSR_K7_PERFCTR1                        0xC0010005
-#define MSR_K7_PERFCTR2                        0xC0010006
-#define MSR_K7_PERFCTR3                        0xC0010007
-#define MSR_K7_HWCR                    0xC0010015
-#define MSR_K7_CLK_CTL                 0xC001001b
-#define MSR_K7_FID_VID_CTL             0xC0010041
-#define MSR_K7_FID_VID_STATUS          0xC0010042
-
-#define MSR_K8_ENABLE_C1E              0xC0010055
-
-/* extended feature register */
-#define MSR_EFER                       0xc0000080
-
-/* EFER bits: */
-
-/* Execute Disable enable */
-#define _EFER_NX                       11
-#define EFER_NX                                (1<<_EFER_NX)
-
-/* Centaur-Hauls/IDT defined MSRs. */
-#define MSR_IDT_FCR1                   0x107
-#define MSR_IDT_FCR2                   0x108
-#define MSR_IDT_FCR3                   0x109
-#define MSR_IDT_FCR4                   0x10a
-
-#define MSR_IDT_MCR0                   0x110
-#define MSR_IDT_MCR1                   0x111
-#define MSR_IDT_MCR2                   0x112
-#define MSR_IDT_MCR3                   0x113
-#define MSR_IDT_MCR4                   0x114
-#define MSR_IDT_MCR5                   0x115
-#define MSR_IDT_MCR6                   0x116
-#define MSR_IDT_MCR7                   0x117
-#define MSR_IDT_MCR_CTRL               0x120
-
-/* VIA Cyrix defined MSRs*/
-#define MSR_VIA_FCR                    0x1107
-#define MSR_VIA_LONGHAUL               0x110a
-#define MSR_VIA_RNG                    0x110b
-#define MSR_VIA_BCR2                   0x1147
-
-/* Transmeta defined MSRs */
-#define MSR_TMTA_LONGRUN_CTRL          0x80868010
-#define MSR_TMTA_LONGRUN_FLAGS         0x80868011
-#define MSR_TMTA_LRTI_READOUT          0x80868018
-#define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
-
-/* Intel Core-based CPU performance counters */
-#define MSR_CORE_PERF_FIXED_CTR0       0x309
-#define MSR_CORE_PERF_FIXED_CTR1       0x30a
-#define MSR_CORE_PERF_FIXED_CTR2       0x30b
-#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x38d
-#define MSR_CORE_PERF_GLOBAL_STATUS    0x38e
-#define MSR_CORE_PERF_GLOBAL_CTRL      0x38f
-#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x390
-
-/* Geode defined MSRs */
-#define MSR_GEODE_BUSCONT_CONF0         0x1900
-
+#endif
+#endif
 #endif /* __ASM_MSR_H */
index 07f063a..7e9c7cc 100644 (file)
@@ -69,6 +69,8 @@ struct mtrr_gentry
 
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
+extern void mtrr_save_fixed_ranges(void *);
+extern void mtrr_save_state(void);
 extern int mtrr_add (unsigned long base, unsigned long size,
                     unsigned int type, char increment);
 extern int mtrr_add_page (unsigned long base, unsigned long size,
@@ -79,6 +81,8 @@ extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
 extern void mtrr_ap_init(void);
 extern void mtrr_bp_init(void);
 #  else
+#define mtrr_save_fixed_ranges(arg) do {} while (0)
+#define mtrr_save_state() do {} while (0)
 static __inline__ int mtrr_add (unsigned long base, unsigned long size,
                                unsigned int type, char increment)
 {
index b04333e..fb1e133 100644 (file)
@@ -50,4 +50,12 @@ void __trigger_all_cpu_backtrace(void);
 
 #endif
 
+void lapic_watchdog_stop(void);
+int lapic_watchdog_init(unsigned nmi_hz);
+int lapic_wd_event(unsigned nmi_hz);
+unsigned lapic_adjust_nmi_hz(unsigned hz);
+int lapic_watchdog_ok(void);
+void disable_lapic_nmi_watchdog(void);
+void enable_lapic_nmi_watchdog(void);
+
 #endif /* ASM_NMI_H */
index 7b19f45..818ac8b 100644 (file)
@@ -12,7 +12,6 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-
 #ifdef CONFIG_X86_USE_3DNOW
 
 #include <asm/mmx.h>
  * These are used to make use of C type-checking..
  */
 extern int nx_enabled;
+
 #ifdef CONFIG_X86_PAE
 extern unsigned long long __supported_pte_mask;
 typedef struct { unsigned long pte_low, pte_high; } pte_t;
 typedef struct { unsigned long long pmd; } pmd_t;
 typedef struct { unsigned long long pgd; } pgd_t;
 typedef struct { unsigned long long pgprot; } pgprot_t;
-#define pmd_val(x)     ((x).pmd)
-#define pte_val(x)     ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
-#define __pmd(x) ((pmd_t) { (x) } )
+
+static inline unsigned long long native_pgd_val(pgd_t pgd)
+{
+       return pgd.pgd;
+}
+
+static inline unsigned long long native_pmd_val(pmd_t pmd)
+{
+       return pmd.pmd;
+}
+
+static inline unsigned long long native_pte_val(pte_t pte)
+{
+       return pte.pte_low | ((unsigned long long)pte.pte_high << 32);
+}
+
+static inline pgd_t native_make_pgd(unsigned long long val)
+{
+       return (pgd_t) { val };
+}
+
+static inline pmd_t native_make_pmd(unsigned long long val)
+{
+       return (pmd_t) { val };
+}
+
+static inline pte_t native_make_pte(unsigned long long val)
+{
+       return (pte_t) { .pte_low = val, .pte_high = (val >> 32) } ;
+}
+
+#ifndef CONFIG_PARAVIRT
+#define pmd_val(x)     native_pmd_val(x)
+#define __pmd(x)       native_make_pmd(x)
+#endif
+
 #define HPAGE_SHIFT    21
 #include <asm-generic/pgtable-nopud.h>
-#else
+#else  /* !CONFIG_X86_PAE */
 typedef struct { unsigned long pte_low; } pte_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 #define boot_pte_t pte_t /* or would you rather have a typedef */
-#define pte_val(x)     ((x).pte_low)
+
+static inline unsigned long native_pgd_val(pgd_t pgd)
+{
+       return pgd.pgd;
+}
+
+static inline unsigned long native_pte_val(pte_t pte)
+{
+       return pte.pte_low;
+}
+
+static inline pgd_t native_make_pgd(unsigned long val)
+{
+       return (pgd_t) { val };
+}
+
+static inline pte_t native_make_pte(unsigned long val)
+{
+       return (pte_t) { .pte_low = val };
+}
+
 #define HPAGE_SHIFT    22
 #include <asm-generic/pgtable-nopmd.h>
-#endif
+#endif /* CONFIG_X86_PAE */
+
 #define PTE_MASK       PAGE_MASK
 
 #ifdef CONFIG_HUGETLB_PAGE
@@ -71,13 +125,16 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 #endif
 
-#define pgd_val(x)     ((x).pgd)
 #define pgprot_val(x)  ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
+#ifndef CONFIG_PARAVIRT
+#define pgd_val(x)     native_pgd_val(x)
+#define __pgd(x)       native_make_pgd(x)
+#define pte_val(x)     native_pte_val(x)
+#define __pte(x)       native_make_pte(x)
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
@@ -143,9 +200,7 @@ extern int page_is_ram(unsigned long pagenr);
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
-#ifndef CONFIG_COMPAT_VDSO
 #define __HAVE_ARCH_GATE_AREA 1
-#endif
 #endif /* __KERNEL__ */
 
 #endif /* _I386_PAGE_H */
index e63f1e4..e2e7f98 100644 (file)
@@ -2,20 +2,9 @@
 #define __ASM_PARAVIRT_H
 /* Various instructions on x86 need to be replaced for
  * para-virtualization: those hooks are defined here. */
-#include <linux/linkage.h>
-#include <linux/stringify.h>
-#include <asm/page.h>
 
 #ifdef CONFIG_PARAVIRT
-/* These are the most performance critical ops, so we want to be able to patch
- * callers */
-#define PARAVIRT_IRQ_DISABLE 0
-#define PARAVIRT_IRQ_ENABLE 1
-#define PARAVIRT_RESTORE_FLAGS 2
-#define PARAVIRT_SAVE_FLAGS 3
-#define PARAVIRT_SAVE_FLAGS_IRQ_DISABLE 4
-#define PARAVIRT_INTERRUPT_RETURN 5
-#define PARAVIRT_STI_SYSEXIT 6
+#include <asm/page.h>
 
 /* Bitmask of what can be clobbered: usually at least eax. */
 #define CLBR_NONE 0x0
 #define CLBR_ANY 0x7
 
 #ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <asm/kmap_types.h>
+
+struct page;
 struct thread_struct;
 struct Xgt_desc_struct;
 struct tss_struct;
 struct mm_struct;
+struct desc_struct;
+
+/* Lazy mode for batching updates / context switch */
+enum paravirt_lazy_mode {
+       PARAVIRT_LAZY_NONE = 0,
+       PARAVIRT_LAZY_MMU = 1,
+       PARAVIRT_LAZY_CPU = 2,
+       PARAVIRT_LAZY_FLUSH = 3,
+};
+
 struct paravirt_ops
 {
        unsigned int kernel_rpl;
+       int shared_kernel_pmd;
        int paravirt_enabled;
        const char *name;
 
@@ -44,24 +49,33 @@ struct paravirt_ops
         */
        unsigned (*patch)(u8 type, u16 clobber, void *firstinsn, unsigned len);
 
+       /* Basic arch-specific setup */
        void (*arch_setup)(void);
        char *(*memory_setup)(void);
        void (*init_IRQ)(void);
+       void (*time_init)(void);
 
+       /*
+        * Called before/after init_mm pagetable setup. setup_start
+        * may reset %cr3, and may pre-install parts of the pagetable;
+        * pagetable setup is expected to preserve any existing
+        * mapping.
+        */
+       void (*pagetable_setup_start)(pgd_t *pgd_base);
+       void (*pagetable_setup_done)(pgd_t *pgd_base);
+
+       /* Print a banner to identify the environment */
        void (*banner)(void);
 
+       /* Set and set time of day */
        unsigned long (*get_wallclock)(void);
        int (*set_wallclock)(unsigned long);
-       void (*time_init)(void);
-
-       /* All the function pointers here are declared as "fastcall"
-          so that we get a specific register-based calling
-          convention.  This makes it easier to implement inline
-          assembler replacements. */
 
+       /* cpuid emulation, mostly so that caps bits can be disabled */
        void (*cpuid)(unsigned int *eax, unsigned int *ebx,
                      unsigned int *ecx, unsigned int *edx);
 
+       /* hooks for various privileged instructions */
        unsigned long (*get_debugreg)(int regno);
        void (*set_debugreg)(int regno, unsigned long value);
 
@@ -80,15 +94,23 @@ struct paravirt_ops
        unsigned long (*read_cr4)(void);
        void (*write_cr4)(unsigned long);
 
+       /*
+        * Get/set interrupt state.  save_fl and restore_fl are only
+        * expected to use X86_EFLAGS_IF; all other bits
+        * returned from save_fl are undefined, and may be ignored by
+        * restore_fl.
+        */
        unsigned long (*save_fl)(void);
        void (*restore_fl)(unsigned long);
        void (*irq_disable)(void);
        void (*irq_enable)(void);
        void (*safe_halt)(void);
        void (*halt)(void);
+
        void (*wbinvd)(void);
 
-       /* err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
+       /* MSR, PMC and TSR operations.
+          err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
        u64 (*read_msr)(unsigned int msr, int *err);
        int (*write_msr)(unsigned int msr, u64 val);
 
@@ -97,6 +119,7 @@ struct paravirt_ops
        u64 (*get_scheduled_cycles)(void);
        unsigned long (*get_cpu_khz)(void);
 
+       /* Segment descriptor handling */
        void (*load_tr_desc)(void);
        void (*load_gdt)(const struct Xgt_desc_struct *);
        void (*load_idt)(const struct Xgt_desc_struct *);
@@ -105,59 +128,98 @@ struct paravirt_ops
        void (*set_ldt)(const void *desc, unsigned entries);
        unsigned long (*store_tr)(void);
        void (*load_tls)(struct thread_struct *t, unsigned int cpu);
-       void (*write_ldt_entry)(void *dt, int entrynum,
-                                        u32 low, u32 high);
-       void (*write_gdt_entry)(void *dt, int entrynum,
-                                        u32 low, u32 high);
-       void (*write_idt_entry)(void *dt, int entrynum,
-                                        u32 low, u32 high);
-       void (*load_esp0)(struct tss_struct *tss,
-                                  struct thread_struct *thread);
+       void (*write_ldt_entry)(struct desc_struct *,
+                               int entrynum, u32 low, u32 high);
+       void (*write_gdt_entry)(struct desc_struct *,
+                               int entrynum, u32 low, u32 high);
+       void (*write_idt_entry)(struct desc_struct *,
+                               int entrynum, u32 low, u32 high);
+       void (*load_esp0)(struct tss_struct *tss, struct thread_struct *t);
 
        void (*set_iopl_mask)(unsigned mask);
-
        void (*io_delay)(void);
 
+       /*
+        * Hooks for intercepting the creation/use/destruction of an
+        * mm_struct.
+        */
+       void (*activate_mm)(struct mm_struct *prev,
+                           struct mm_struct *next);
+       void (*dup_mmap)(struct mm_struct *oldmm,
+                        struct mm_struct *mm);
+       void (*exit_mmap)(struct mm_struct *mm);
+
 #ifdef CONFIG_X86_LOCAL_APIC
+       /*
+        * Direct APIC operations, principally for VMI.  Ideally
+        * these shouldn't be in this interface.
+        */
        void (*apic_write)(unsigned long reg, unsigned long v);
        void (*apic_write_atomic)(unsigned long reg, unsigned long v);
        unsigned long (*apic_read)(unsigned long reg);
        void (*setup_boot_clock)(void);
        void (*setup_secondary_clock)(void);
+
+       void (*startup_ipi_hook)(int phys_apicid,
+                                unsigned long start_eip,
+                                unsigned long start_esp);
 #endif
 
+       /* TLB operations */
        void (*flush_tlb_user)(void);
        void (*flush_tlb_kernel)(void);
-       void (*flush_tlb_single)(u32 addr);
-
-       void (*map_pt_hook)(int type, pte_t *va, u32 pfn);
+       void (*flush_tlb_single)(unsigned long addr);
+       void (*flush_tlb_others)(const cpumask_t *cpus, struct mm_struct *mm,
+                                unsigned long va);
 
+       /* Hooks for allocating/releasing pagetable pages */
        void (*alloc_pt)(u32 pfn);
        void (*alloc_pd)(u32 pfn);
        void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
        void (*release_pt)(u32 pfn);
        void (*release_pd)(u32 pfn);
 
+       /* Pagetable manipulation functions */
        void (*set_pte)(pte_t *ptep, pte_t pteval);
-       void (*set_pte_at)(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval);
+       void (*set_pte_at)(struct mm_struct *mm, unsigned long addr,
+                          pte_t *ptep, pte_t pteval);
        void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
-       void (*pte_update)(struct mm_struct *mm, u32 addr, pte_t *ptep);
-       void (*pte_update_defer)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+       void (*pte_update)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+       void (*pte_update_defer)(struct mm_struct *mm,
+                                unsigned long addr, pte_t *ptep);
+
+#ifdef CONFIG_HIGHPTE
+       void *(*kmap_atomic_pte)(struct page *page, enum km_type type);
+#endif
+
 #ifdef CONFIG_X86_PAE
        void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
-       void (*set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
+       void (*set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
        void (*set_pud)(pud_t *pudp, pud_t pudval);
-       void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+       void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
        void (*pmd_clear)(pmd_t *pmdp);
+
+       unsigned long long (*pte_val)(pte_t);
+       unsigned long long (*pmd_val)(pmd_t);
+       unsigned long long (*pgd_val)(pgd_t);
+
+       pte_t (*make_pte)(unsigned long long pte);
+       pmd_t (*make_pmd)(unsigned long long pmd);
+       pgd_t (*make_pgd)(unsigned long long pgd);
+#else
+       unsigned long (*pte_val)(pte_t);
+       unsigned long (*pgd_val)(pgd_t);
+
+       pte_t (*make_pte)(unsigned long pte);
+       pgd_t (*make_pgd)(unsigned long pgd);
 #endif
 
-       void (*set_lazy_mode)(int mode);
+       /* Set deferred update mode, used for batching operations. */
+       void (*set_lazy_mode)(enum paravirt_lazy_mode mode);
 
        /* These two are jmp to, not actually called. */
        void (*irq_enable_sysexit)(void);
        void (*iret)(void);
-
-       void (*startup_ipi_hook)(int phys_apicid, unsigned long start_eip, unsigned long start_esp);
 };
 
 /* Mark a paravirt probe function. */
@@ -167,23 +229,202 @@ struct paravirt_ops
 
 extern struct paravirt_ops paravirt_ops;
 
-#define paravirt_enabled() (paravirt_ops.paravirt_enabled)
+#define PARAVIRT_PATCH(x)                                      \
+       (offsetof(struct paravirt_ops, x) / sizeof(void *))
+
+#define paravirt_type(type)                                    \
+       [paravirt_typenum] "i" (PARAVIRT_PATCH(type))
+#define paravirt_clobber(clobber)              \
+       [paravirt_clobber] "i" (clobber)
+
+/*
+ * Generate some code, and mark it as patchable by the
+ * apply_paravirt() alternate instruction patcher.
+ */
+#define _paravirt_alt(insn_string, type, clobber)      \
+       "771:\n\t" insn_string "\n" "772:\n"            \
+       ".pushsection .parainstructions,\"a\"\n"        \
+       "  .long 771b\n"                                \
+       "  .byte " type "\n"                            \
+       "  .byte 772b-771b\n"                           \
+       "  .short " clobber "\n"                        \
+       ".popsection\n"
+
+/* Generate patchable code, with the default asm parameters. */
+#define paravirt_alt(insn_string)                                      \
+       _paravirt_alt(insn_string, "%c[paravirt_typenum]", "%c[paravirt_clobber]")
+
+unsigned paravirt_patch_nop(void);
+unsigned paravirt_patch_ignore(unsigned len);
+unsigned paravirt_patch_call(void *target, u16 tgt_clobbers,
+                            void *site, u16 site_clobbers,
+                            unsigned len);
+unsigned paravirt_patch_jmp(void *target, void *site, unsigned len);
+unsigned paravirt_patch_default(u8 type, u16 clobbers, void *site, unsigned len);
+
+unsigned paravirt_patch_insns(void *site, unsigned len,
+                             const char *start, const char *end);
+
+
+/*
+ * This generates an indirect call based on the operation type number.
+ * The type number, computed in PARAVIRT_PATCH, is derived from the
+ * offset into the paravirt_ops structure, and can therefore be freely
+ * converted back into a structure offset.
+ */
+#define PARAVIRT_CALL  "call *(paravirt_ops+%c[paravirt_typenum]*4);"
+
+/*
+ * These macros are intended to wrap calls into a paravirt_ops
+ * operation, so that they can be later identified and patched at
+ * runtime.
+ *
+ * Normally, a call to a pv_op function is a simple indirect call:
+ * (paravirt_ops.operations)(args...).
+ *
+ * Unfortunately, this is a relatively slow operation for modern CPUs,
+ * because it cannot necessarily determine what the destination
+ * address is.  In this case, the address is a runtime constant, so at
+ * the very least we can patch the call to e a simple direct call, or
+ * ideally, patch an inline implementation into the callsite.  (Direct
+ * calls are essentially free, because the call and return addresses
+ * are completely predictable.)
+ *
+ * These macros rely on the standard gcc "regparm(3)" calling
+ * convention, in which the first three arguments are placed in %eax,
+ * %edx, %ecx (in that order), and the remaining arguments are placed
+ * on the stack.  All caller-save registers (eax,edx,ecx) are expected
+ * to be modified (either clobbered or used for return values).
+ *
+ * The call instruction itself is marked by placing its start address
+ * and size into the .parainstructions section, so that
+ * apply_paravirt() in arch/i386/kernel/alternative.c can do the
+ * appropriate patching under the control of the backend paravirt_ops
+ * implementation.
+ *
+ * Unfortunately there's no way to get gcc to generate the args setup
+ * for the call, and then allow the call itself to be generated by an
+ * inline asm.  Because of this, we must do the complete arg setup and
+ * return value handling from within these macros.  This is fairly
+ * cumbersome.
+ *
+ * There are 5 sets of PVOP_* macros for dealing with 0-4 arguments.
+ * It could be extended to more arguments, but there would be little
+ * to be gained from that.  For each number of arguments, there are
+ * the two VCALL and CALL variants for void and non-void functions.
+ *
+ * When there is a return value, the invoker of the macro must specify
+ * the return type.  The macro then uses sizeof() on that type to
+ * determine whether its a 32 or 64 bit value, and places the return
+ * in the right register(s) (just %eax for 32-bit, and %edx:%eax for
+ * 64-bit).
+ *
+ * 64-bit arguments are passed as a pair of adjacent 32-bit arguments
+ * in low,high order.
+ *
+ * Small structures are passed and returned in registers.  The macro
+ * calling convention can't directly deal with this, so the wrapper
+ * functions must do this.
+ *
+ * These PVOP_* macros are only defined within this header.  This
+ * means that all uses must be wrapped in inline functions.  This also
+ * makes sure the incoming and outgoing types are always correct.
+ */
+#define __PVOP_CALL(rettype, op, pre, post, ...)                       \
+       ({                                                              \
+               rettype __ret;                                          \
+               unsigned long __eax, __edx, __ecx;                      \
+               if (sizeof(rettype) > sizeof(unsigned long)) {          \
+                       asm volatile(pre                                \
+                                    paravirt_alt(PARAVIRT_CALL)        \
+                                    post                               \
+                                    : "=a" (__eax), "=d" (__edx),      \
+                                      "=c" (__ecx)                     \
+                                    : paravirt_type(op),               \
+                                      paravirt_clobber(CLBR_ANY),      \
+                                      ##__VA_ARGS__                    \
+                                    : "memory", "cc");                 \
+                       __ret = (rettype)((((u64)__edx) << 32) | __eax); \
+               } else {                                                \
+                       asm volatile(pre                                \
+                                    paravirt_alt(PARAVIRT_CALL)        \
+                                    post                               \
+                                    : "=a" (__eax), "=d" (__edx),      \
+                                      "=c" (__ecx)                     \
+                                    : paravirt_type(op),               \
+                                      paravirt_clobber(CLBR_ANY),      \
+                                      ##__VA_ARGS__                    \
+                                    : "memory", "cc");                 \
+                       __ret = (rettype)__eax;                         \
+               }                                                       \
+               __ret;                                                  \
+       })
+#define __PVOP_VCALL(op, pre, post, ...)                               \
+       ({                                                              \
+               unsigned long __eax, __edx, __ecx;                      \
+               asm volatile(pre                                        \
+                            paravirt_alt(PARAVIRT_CALL)                \
+                            post                                       \
+                            : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \
+                            : paravirt_type(op),                       \
+                              paravirt_clobber(CLBR_ANY),              \
+                              ##__VA_ARGS__                            \
+                            : "memory", "cc");                         \
+       })
+
+#define PVOP_CALL0(rettype, op)                                                \
+       __PVOP_CALL(rettype, op, "", "")
+#define PVOP_VCALL0(op)                                                        \
+       __PVOP_VCALL(op, "", "")
+
+#define PVOP_CALL1(rettype, op, arg1)                                  \
+       __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)))
+#define PVOP_VCALL1(op, arg1)                                          \
+       __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)))
+
+#define PVOP_CALL2(rettype, op, arg1, arg2)                            \
+       __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2)))
+#define PVOP_VCALL2(op, arg1, arg2)                                    \
+       __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2)))
+
+#define PVOP_CALL3(rettype, op, arg1, arg2, arg3)                      \
+       __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)),             \
+                   "1"((u32)(arg2)), "2"((u32)(arg3)))
+#define PVOP_VCALL3(op, arg1, arg2, arg3)                              \
+       __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1"((u32)(arg2)),   \
+                    "2"((u32)(arg3)))
+
+#define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4)                        \
+       __PVOP_CALL(rettype, op,                                        \
+                   "push %[_arg4];", "lea 4(%%esp),%%esp;",            \
+                   "0" ((u32)(arg1)), "1" ((u32)(arg2)),               \
+                   "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4)))
+#define PVOP_VCALL4(op, arg1, arg2, arg3, arg4)                                \
+       __PVOP_VCALL(op,                                                \
+                   "push %[_arg4];", "lea 4(%%esp),%%esp;",            \
+                   "0" ((u32)(arg1)), "1" ((u32)(arg2)),               \
+                   "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4)))
+
+static inline int paravirt_enabled(void)
+{
+       return paravirt_ops.paravirt_enabled;
+}
 
 static inline void load_esp0(struct tss_struct *tss,
                             struct thread_struct *thread)
 {
-       paravirt_ops.load_esp0(tss, thread);
+       PVOP_VCALL2(load_esp0, tss, thread);
 }
 
 #define ARCH_SETUP                     paravirt_ops.arch_setup();
 static inline unsigned long get_wallclock(void)
 {
-       return paravirt_ops.get_wallclock();
+       return PVOP_CALL0(unsigned long, get_wallclock);
 }
 
 static inline int set_wallclock(unsigned long nowtime)
 {
-       return paravirt_ops.set_wallclock(nowtime);
+       return PVOP_CALL1(int, set_wallclock, nowtime);
 }
 
 static inline void (*choose_time_init(void))(void)
@@ -195,113 +436,208 @@ static inline void (*choose_time_init(void))(void)
 static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
                           unsigned int *ecx, unsigned int *edx)
 {
-       paravirt_ops.cpuid(eax, ebx, ecx, edx);
+       PVOP_VCALL4(cpuid, eax, ebx, ecx, edx);
 }
 
 /*
  * These special macros can be used to get or set a debugging register
  */
-#define get_debugreg(var, reg) var = paravirt_ops.get_debugreg(reg)
-#define set_debugreg(val, reg) paravirt_ops.set_debugreg(reg, val)
+static inline unsigned long paravirt_get_debugreg(int reg)
+{
+       return PVOP_CALL1(unsigned long, get_debugreg, reg);
+}
+#define get_debugreg(var, reg) var = paravirt_get_debugreg(reg)
+static inline void set_debugreg(unsigned long val, int reg)
+{
+       PVOP_VCALL2(set_debugreg, reg, val);
+}
+
+static inline void clts(void)
+{
+       PVOP_VCALL0(clts);
+}
 
-#define clts() paravirt_ops.clts()
+static inline unsigned long read_cr0(void)
+{
+       return PVOP_CALL0(unsigned long, read_cr0);
+}
 
-#define read_cr0() paravirt_ops.read_cr0()
-#define write_cr0(x) paravirt_ops.write_cr0(x)
+static inline void write_cr0(unsigned long x)
+{
+       PVOP_VCALL1(write_cr0, x);
+}
 
-#define read_cr2() paravirt_ops.read_cr2()
-#define write_cr2(x) paravirt_ops.write_cr2(x)
+static inline unsigned long read_cr2(void)
+{
+       return PVOP_CALL0(unsigned long, read_cr2);
+}
 
-#define read_cr3() paravirt_ops.read_cr3()
-#define write_cr3(x) paravirt_ops.write_cr3(x)
+static inline void write_cr2(unsigned long x)
+{
+       PVOP_VCALL1(write_cr2, x);
+}
 
-#define read_cr4() paravirt_ops.read_cr4()
-#define read_cr4_safe(x) paravirt_ops.read_cr4_safe()
-#define write_cr4(x) paravirt_ops.write_cr4(x)
+static inline unsigned long read_cr3(void)
+{
+       return PVOP_CALL0(unsigned long, read_cr3);
+}
+
+static inline void write_cr3(unsigned long x)
+{
+       PVOP_VCALL1(write_cr3, x);
+}
+
+static inline unsigned long read_cr4(void)
+{
+       return PVOP_CALL0(unsigned long, read_cr4);
+}
+static inline unsigned long read_cr4_safe(void)
+{
+       return PVOP_CALL0(unsigned long, read_cr4_safe);
+}
+
+static inline void write_cr4(unsigned long x)
+{
+       PVOP_VCALL1(write_cr4, x);
+}
 
 static inline void raw_safe_halt(void)
 {
-       paravirt_ops.safe_halt();
+       PVOP_VCALL0(safe_halt);
 }
 
 static inline void halt(void)
 {
-       paravirt_ops.safe_halt();
+       PVOP_VCALL0(safe_halt);
+}
+
+static inline void wbinvd(void)
+{
+       PVOP_VCALL0(wbinvd);
 }
-#define wbinvd() paravirt_ops.wbinvd()
 
 #define get_kernel_rpl()  (paravirt_ops.kernel_rpl)
 
-#define rdmsr(msr,val1,val2) do {                              \
-       int _err;                                               \
-       u64 _l = paravirt_ops.read_msr(msr,&_err);              \
-       val1 = (u32)_l;                                         \
-       val2 = _l >> 32;                                        \
+static inline u64 paravirt_read_msr(unsigned msr, int *err)
+{
+       return PVOP_CALL2(u64, read_msr, msr, err);
+}
+static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
+{
+       return PVOP_CALL3(int, write_msr, msr, low, high);
+}
+
+/* These should all do BUG_ON(_err), but our headers are too tangled. */
+#define rdmsr(msr,val1,val2) do {              \
+       int _err;                               \
+       u64 _l = paravirt_read_msr(msr, &_err); \
+       val1 = (u32)_l;                         \
+       val2 = _l >> 32;                        \
 } while(0)
 
-#define wrmsr(msr,val1,val2) do {                              \
-       u64 _l = ((u64)(val2) << 32) | (val1);                  \
-       paravirt_ops.write_msr((msr), _l);                      \
+#define wrmsr(msr,val1,val2) do {              \
+       paravirt_write_msr(msr, val1, val2);    \
 } while(0)
 
-#define rdmsrl(msr,val) do {                                   \
-       int _err;                                               \
-       val = paravirt_ops.read_msr((msr),&_err);               \
+#define rdmsrl(msr,val) do {                   \
+       int _err;                               \
+       val = paravirt_read_msr(msr, &_err);    \
 } while(0)
 
-#define wrmsrl(msr,val) (paravirt_ops.write_msr((msr),(val)))
-#define wrmsr_safe(msr,a,b) ({                                 \
-       u64 _l = ((u64)(b) << 32) | (a);                        \
-       paravirt_ops.write_msr((msr),_l);                       \
-})
+#define wrmsrl(msr,val)                ((void)paravirt_write_msr(msr, val, 0))
+#define wrmsr_safe(msr,a,b)    paravirt_write_msr(msr, a, b)
 
 /* rdmsr with exception handling */
-#define rdmsr_safe(msr,a,b) ({                                 \
-       int _err;                                               \
-       u64 _l = paravirt_ops.read_msr(msr,&_err);              \
-       (*a) = (u32)_l;                                         \
-       (*b) = _l >> 32;                                        \
+#define rdmsr_safe(msr,a,b) ({                 \
+       int _err;                               \
+       u64 _l = paravirt_read_msr(msr, &_err); \
+       (*a) = (u32)_l;                         \
+       (*b) = _l >> 32;                        \
        _err; })
 
-#define rdtsc(low,high) do {                                   \
-       u64 _l = paravirt_ops.read_tsc();                       \
-       low = (u32)_l;                                          \
-       high = _l >> 32;                                        \
+
+static inline u64 paravirt_read_tsc(void)
+{
+       return PVOP_CALL0(u64, read_tsc);
+}
+#define rdtsc(low,high) do {                   \
+       u64 _l = paravirt_read_tsc();           \
+       low = (u32)_l;                          \
+       high = _l >> 32;                        \
 } while(0)
 
-#define rdtscl(low) do {                                       \
-       u64 _l = paravirt_ops.read_tsc();                       \
-       low = (int)_l;                                          \
+#define rdtscl(low) do {                       \
+       u64 _l = paravirt_read_tsc();           \
+       low = (int)_l;                          \
 } while(0)
 
-#define rdtscll(val) (val = paravirt_ops.read_tsc())
+#define rdtscll(val) (val = paravirt_read_tsc())
 
 #define get_scheduled_cycles(val) (val = paravirt_ops.get_scheduled_cycles())
 #define calculate_cpu_khz() (paravirt_ops.get_cpu_khz())
 
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
-#define rdpmc(counter,low,high) do {                           \
-       u64 _l = paravirt_ops.read_pmc();                       \
-       low = (u32)_l;                                          \
-       high = _l >> 32;                                        \
+static inline unsigned long long paravirt_read_pmc(int counter)
+{
+       return PVOP_CALL1(u64, read_pmc, counter);
+}
+
+#define rdpmc(counter,low,high) do {           \
+       u64 _l = paravirt_read_pmc(counter);    \
+       low = (u32)_l;                          \
+       high = _l >> 32;                        \
 } while(0)
 
-#define load_TR_desc() (paravirt_ops.load_tr_desc())
-#define load_gdt(dtr) (paravirt_ops.load_gdt(dtr))
-#define load_idt(dtr) (paravirt_ops.load_idt(dtr))
-#define set_ldt(addr, entries) (paravirt_ops.set_ldt((addr), (entries)))
-#define store_gdt(dtr) (paravirt_ops.store_gdt(dtr))
-#define store_idt(dtr) (paravirt_ops.store_idt(dtr))
-#define store_tr(tr) ((tr) = paravirt_ops.store_tr())
-#define load_TLS(t,cpu) (paravirt_ops.load_tls((t),(cpu)))
-#define write_ldt_entry(dt, entry, low, high)                          \
-       (paravirt_ops.write_ldt_entry((dt), (entry), (low), (high)))
-#define write_gdt_entry(dt, entry, low, high)                          \
-       (paravirt_ops.write_gdt_entry((dt), (entry), (low), (high)))
-#define write_idt_entry(dt, entry, low, high)                          \
-       (paravirt_ops.write_idt_entry((dt), (entry), (low), (high)))
-#define set_iopl_mask(mask) (paravirt_ops.set_iopl_mask(mask))
+static inline void load_TR_desc(void)
+{
+       PVOP_VCALL0(load_tr_desc);
+}
+static inline void load_gdt(const struct Xgt_desc_struct *dtr)
+{
+       PVOP_VCALL1(load_gdt, dtr);
+}
+static inline void load_idt(const struct Xgt_desc_struct *dtr)
+{
+       PVOP_VCALL1(load_idt, dtr);
+}
+static inline void set_ldt(const void *addr, unsigned entries)
+{
+       PVOP_VCALL2(set_ldt, addr, entries);
+}
+static inline void store_gdt(struct Xgt_desc_struct *dtr)
+{
+       PVOP_VCALL1(store_gdt, dtr);
+}
+static inline void store_idt(struct Xgt_desc_struct *dtr)
+{
+       PVOP_VCALL1(store_idt, dtr);
+}
+static inline unsigned long paravirt_store_tr(void)
+{
+       return PVOP_CALL0(unsigned long, store_tr);
+}
+#define store_tr(tr)   ((tr) = paravirt_store_tr())
+static inline void load_TLS(struct thread_struct *t, unsigned cpu)
+{
+       PVOP_VCALL2(load_tls, t, cpu);
+}
+static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
+{
+       PVOP_VCALL4(write_ldt_entry, dt, entry, low, high);
+}
+static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
+{
+       PVOP_VCALL4(write_gdt_entry, dt, entry, low, high);
+}
+static inline void write_idt_entry(void *dt, int entry, u32 low, u32 high)
+{
+       PVOP_VCALL4(write_idt_entry, dt, entry, low, high);
+}
+static inline void set_iopl_mask(unsigned mask)
+{
+       PVOP_VCALL1(set_iopl_mask, mask);
+}
 
 /* The paravirtualized I/O functions */
 static inline void slow_down_io(void) {
@@ -319,215 +655,390 @@ static inline void slow_down_io(void) {
  */
 static inline void apic_write(unsigned long reg, unsigned long v)
 {
-       paravirt_ops.apic_write(reg,v);
+       PVOP_VCALL2(apic_write, reg, v);
 }
 
 static inline void apic_write_atomic(unsigned long reg, unsigned long v)
 {
-       paravirt_ops.apic_write_atomic(reg,v);
+       PVOP_VCALL2(apic_write_atomic, reg, v);
 }
 
 static inline unsigned long apic_read(unsigned long reg)
 {
-       return paravirt_ops.apic_read(reg);
+       return PVOP_CALL1(unsigned long, apic_read, reg);
 }
 
 static inline void setup_boot_clock(void)
 {
-       paravirt_ops.setup_boot_clock();
+       PVOP_VCALL0(setup_boot_clock);
 }
 
 static inline void setup_secondary_clock(void)
 {
-       paravirt_ops.setup_secondary_clock();
+       PVOP_VCALL0(setup_secondary_clock);
 }
 #endif
 
+static inline void paravirt_pagetable_setup_start(pgd_t *base)
+{
+       if (paravirt_ops.pagetable_setup_start)
+               (*paravirt_ops.pagetable_setup_start)(base);
+}
+
+static inline void paravirt_pagetable_setup_done(pgd_t *base)
+{
+       if (paravirt_ops.pagetable_setup_done)
+               (*paravirt_ops.pagetable_setup_done)(base);
+}
+
 #ifdef CONFIG_SMP
 static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
                                    unsigned long start_esp)
 {
-       return paravirt_ops.startup_ipi_hook(phys_apicid, start_eip, start_esp);
+       PVOP_VCALL3(startup_ipi_hook, phys_apicid, start_eip, start_esp);
 }
 #endif
 
-#define __flush_tlb() paravirt_ops.flush_tlb_user()
-#define __flush_tlb_global() paravirt_ops.flush_tlb_kernel()
-#define __flush_tlb_single(addr) paravirt_ops.flush_tlb_single(addr)
+static inline void paravirt_activate_mm(struct mm_struct *prev,
+                                       struct mm_struct *next)
+{
+       PVOP_VCALL2(activate_mm, prev, next);
+}
 
-#define paravirt_map_pt_hook(type, va, pfn) paravirt_ops.map_pt_hook(type, va, pfn)
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+                                struct mm_struct *mm)
+{
+       PVOP_VCALL2(dup_mmap, oldmm, mm);
+}
 
-#define paravirt_alloc_pt(pfn) paravirt_ops.alloc_pt(pfn)
-#define paravirt_release_pt(pfn) paravirt_ops.release_pt(pfn)
+static inline void arch_exit_mmap(struct mm_struct *mm)
+{
+       PVOP_VCALL1(exit_mmap, mm);
+}
 
-#define paravirt_alloc_pd(pfn) paravirt_ops.alloc_pd(pfn)
-#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) \
-       paravirt_ops.alloc_pd_clone(pfn, clonepfn, start, count)
-#define paravirt_release_pd(pfn) paravirt_ops.release_pd(pfn)
+static inline void __flush_tlb(void)
+{
+       PVOP_VCALL0(flush_tlb_user);
+}
+static inline void __flush_tlb_global(void)
+{
+       PVOP_VCALL0(flush_tlb_kernel);
+}
+static inline void __flush_tlb_single(unsigned long addr)
+{
+       PVOP_VCALL1(flush_tlb_single, addr);
+}
 
-static inline void set_pte(pte_t *ptep, pte_t pteval)
+static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+                                   unsigned long va)
 {
-       paravirt_ops.set_pte(ptep, pteval);
+       PVOP_VCALL3(flush_tlb_others, &cpumask, mm, va);
 }
 
-static inline void set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
+static inline void paravirt_alloc_pt(unsigned pfn)
 {
-       paravirt_ops.set_pte_at(mm, addr, ptep, pteval);
+       PVOP_VCALL1(alloc_pt, pfn);
+}
+static inline void paravirt_release_pt(unsigned pfn)
+{
+       PVOP_VCALL1(release_pt, pfn);
 }
 
-static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
+static inline void paravirt_alloc_pd(unsigned pfn)
 {
-       paravirt_ops.set_pmd(pmdp, pmdval);
+       PVOP_VCALL1(alloc_pd, pfn);
 }
 
-static inline void pte_update(struct mm_struct *mm, u32 addr, pte_t *ptep)
+static inline void paravirt_alloc_pd_clone(unsigned pfn, unsigned clonepfn,
+                                          unsigned start, unsigned count)
 {
-       paravirt_ops.pte_update(mm, addr, ptep);
+       PVOP_VCALL4(alloc_pd_clone, pfn, clonepfn, start, count);
+}
+static inline void paravirt_release_pd(unsigned pfn)
+{
+       PVOP_VCALL1(release_pd, pfn);
 }
 
-static inline void pte_update_defer(struct mm_struct *mm, u32 addr, pte_t *ptep)
+#ifdef CONFIG_HIGHPTE
+static inline void *kmap_atomic_pte(struct page *page, enum km_type type)
 {
-       paravirt_ops.pte_update_defer(mm, addr, ptep);
+       unsigned long ret;
+       ret = PVOP_CALL2(unsigned long, kmap_atomic_pte, page, type);
+       return (void *)ret;
+}
+#endif
+
+static inline void pte_update(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep)
+{
+       PVOP_VCALL3(pte_update, mm, addr, ptep);
+}
+
+static inline void pte_update_defer(struct mm_struct *mm, unsigned long addr,
+                                   pte_t *ptep)
+{
+       PVOP_VCALL3(pte_update_defer, mm, addr, ptep);
 }
 
 #ifdef CONFIG_X86_PAE
+static inline pte_t __pte(unsigned long long val)
+{
+       unsigned long long ret = PVOP_CALL2(unsigned long long, make_pte,
+                                           val, val >> 32);
+       return (pte_t) { ret, ret >> 32 };
+}
+
+static inline pmd_t __pmd(unsigned long long val)
+{
+       return (pmd_t) { PVOP_CALL2(unsigned long long, make_pmd, val, val >> 32) };
+}
+
+static inline pgd_t __pgd(unsigned long long val)
+{
+       return (pgd_t) { PVOP_CALL2(unsigned long long, make_pgd, val, val >> 32) };
+}
+
+static inline unsigned long long pte_val(pte_t x)
+{
+       return PVOP_CALL2(unsigned long long, pte_val, x.pte_low, x.pte_high);
+}
+
+static inline unsigned long long pmd_val(pmd_t x)
+{
+       return PVOP_CALL2(unsigned long long, pmd_val, x.pmd, x.pmd >> 32);
+}
+
+static inline unsigned long long pgd_val(pgd_t x)
+{
+       return PVOP_CALL2(unsigned long long, pgd_val, x.pgd, x.pgd >> 32);
+}
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+       PVOP_VCALL3(set_pte, ptep, pteval.pte_low, pteval.pte_high);
+}
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pteval)
+{
+       /* 5 arg words */
+       paravirt_ops.set_pte_at(mm, addr, ptep, pteval);
+}
+
 static inline void set_pte_atomic(pte_t *ptep, pte_t pteval)
 {
-       paravirt_ops.set_pte_atomic(ptep, pteval);
+       PVOP_VCALL3(set_pte_atomic, ptep, pteval.pte_low, pteval.pte_high);
 }
 
-static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+static inline void set_pte_present(struct mm_struct *mm, unsigned long addr,
+                                  pte_t *ptep, pte_t pte)
 {
+       /* 5 arg words */
        paravirt_ops.set_pte_present(mm, addr, ptep, pte);
 }
 
+static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+       PVOP_VCALL3(set_pmd, pmdp, pmdval.pmd, pmdval.pmd >> 32);
+}
+
 static inline void set_pud(pud_t *pudp, pud_t pudval)
 {
-       paravirt_ops.set_pud(pudp, pudval);
+       PVOP_VCALL3(set_pud, pudp, pudval.pgd.pgd, pudval.pgd.pgd >> 32);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-       paravirt_ops.pte_clear(mm, addr, ptep);
+       PVOP_VCALL3(pte_clear, mm, addr, ptep);
 }
 
 static inline void pmd_clear(pmd_t *pmdp)
 {
-       paravirt_ops.pmd_clear(pmdp);
+       PVOP_VCALL1(pmd_clear, pmdp);
 }
-#endif
 
-/* Lazy mode for batching updates / context switch */
-#define PARAVIRT_LAZY_NONE 0
-#define PARAVIRT_LAZY_MMU  1
-#define PARAVIRT_LAZY_CPU  2
-#define PARAVIRT_LAZY_FLUSH 3
+#else  /* !CONFIG_X86_PAE */
+
+static inline pte_t __pte(unsigned long val)
+{
+       return (pte_t) { PVOP_CALL1(unsigned long, make_pte, val) };
+}
+
+static inline pgd_t __pgd(unsigned long val)
+{
+       return (pgd_t) { PVOP_CALL1(unsigned long, make_pgd, val) };
+}
+
+static inline unsigned long pte_val(pte_t x)
+{
+       return PVOP_CALL1(unsigned long, pte_val, x.pte_low);
+}
+
+static inline unsigned long pgd_val(pgd_t x)
+{
+       return PVOP_CALL1(unsigned long, pgd_val, x.pgd);
+}
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+       PVOP_VCALL2(set_pte, ptep, pteval.pte_low);
+}
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pteval)
+{
+       PVOP_VCALL4(set_pte_at, mm, addr, ptep, pteval.pte_low);
+}
+
+static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+       PVOP_VCALL2(set_pmd, pmdp, pmdval.pud.pgd.pgd);
+}
+#endif /* CONFIG_X86_PAE */
 
 #define  __HAVE_ARCH_ENTER_LAZY_CPU_MODE
-#define arch_enter_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_CPU)
-#define arch_leave_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_NONE)
-#define arch_flush_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_FLUSH)
+static inline void arch_enter_lazy_cpu_mode(void)
+{
+       PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_CPU);
+}
+
+static inline void arch_leave_lazy_cpu_mode(void)
+{
+       PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_NONE);
+}
+
+static inline void arch_flush_lazy_cpu_mode(void)
+{
+       PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_FLUSH);
+}
+
 
 #define  __HAVE_ARCH_ENTER_LAZY_MMU_MODE
-#define arch_enter_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_MMU)
-#define arch_leave_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_NONE)
-#define arch_flush_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_FLUSH)
+static inline void arch_enter_lazy_mmu_mode(void)
+{
+       PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_MMU);
+}
+
+static inline void arch_leave_lazy_mmu_mode(void)
+{
+       PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_NONE);
+}
+
+static inline void arch_flush_lazy_mmu_mode(void)
+{
+       PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_FLUSH);
+}
+
+void _paravirt_nop(void);
+#define paravirt_nop   ((void *)_paravirt_nop)
 
 /* These all sit in the .parainstructions section to tell us what to patch. */
-struct paravirt_patch {
+struct paravirt_patch_site {
        u8 *instr;              /* original instructions */
        u8 instrtype;           /* type of this instruction */
        u8 len;                 /* length of original instruction */
        u16 clobbers;           /* what registers you may clobber */
 };
 
-#define paravirt_alt(insn_string, typenum, clobber)    \
-       "771:\n\t" insn_string "\n" "772:\n"            \
-       ".pushsection .parainstructions,\"a\"\n"        \
-       "  .long 771b\n"                                \
-       "  .byte " __stringify(typenum) "\n"            \
-       "  .byte 772b-771b\n"                           \
-       "  .short " __stringify(clobber) "\n"           \
-       ".popsection"
+extern struct paravirt_patch_site __parainstructions[],
+       __parainstructions_end[];
 
 static inline unsigned long __raw_local_save_flags(void)
 {
        unsigned long f;
 
-       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
-                                          "call *%1;"
-                                          "popl %%edx; popl %%ecx",
-                                         PARAVIRT_SAVE_FLAGS, CLBR_NONE)
-                            : "=a"(f): "m"(paravirt_ops.save_fl)
-                            : "memory", "cc");
+       asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
+                                 PARAVIRT_CALL
+                                 "popl %%edx; popl %%ecx")
+                    : "=a"(f)
+                    : paravirt_type(save_fl),
+                      paravirt_clobber(CLBR_EAX)
+                    : "memory", "cc");
        return f;
 }
 
 static inline void raw_local_irq_restore(unsigned long f)
 {
-       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
-                                          "call *%1;"
-                                          "popl %%edx; popl %%ecx",
-                                         PARAVIRT_RESTORE_FLAGS, CLBR_EAX)
-                            : "=a"(f) : "m" (paravirt_ops.restore_fl), "0"(f)
-                            : "memory", "cc");
+       asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
+                                 PARAVIRT_CALL
+                                 "popl %%edx; popl %%ecx")
+                    : "=a"(f)
+                    : "0"(f),
+                      paravirt_type(restore_fl),
+                      paravirt_clobber(CLBR_EAX)
+                    : "memory", "cc");
 }
 
 static inline void raw_local_irq_disable(void)
 {
-       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
-                                          "call *%0;"
-                                          "popl %%edx; popl %%ecx",
-                                         PARAVIRT_IRQ_DISABLE, CLBR_EAX)
-                            : : "m" (paravirt_ops.irq_disable)
-                            : "memory", "eax", "cc");
+       asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
+                                 PARAVIRT_CALL
+                                 "popl %%edx; popl %%ecx")
+                    :
+                    : paravirt_type(irq_disable),
+                      paravirt_clobber(CLBR_EAX)
+                    : "memory", "eax", "cc");
 }
 
 static inline void raw_local_irq_enable(void)
 {
-       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
-                                          "call *%0;"
-                                          "popl %%edx; popl %%ecx",
-                                         PARAVIRT_IRQ_ENABLE, CLBR_EAX)
-                            : : "m" (paravirt_ops.irq_enable)
-                            : "memory", "eax", "cc");
+       asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
+                                 PARAVIRT_CALL
+                                 "popl %%edx; popl %%ecx")
+                    :
+                    : paravirt_type(irq_enable),
+                      paravirt_clobber(CLBR_EAX)
+                    : "memory", "eax", "cc");
 }
 
 static inline unsigned long __raw_local_irq_save(void)
 {
        unsigned long f;
 
-       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
-                                          "call *%1; pushl %%eax;"
-                                          "call *%2; popl %%eax;"
-                                          "popl %%edx; popl %%ecx",
-                                         PARAVIRT_SAVE_FLAGS_IRQ_DISABLE,
-                                         CLBR_NONE)
-                            : "=a"(f)
-                            : "m" (paravirt_ops.save_fl),
-                              "m" (paravirt_ops.irq_disable)
-                            : "memory", "cc");
+       f = __raw_local_save_flags();
+       raw_local_irq_disable();
        return f;
 }
 
-#define CLI_STRING paravirt_alt("pushl %%ecx; pushl %%edx;"            \
-                    "call *paravirt_ops+%c[irq_disable];"              \
-                    "popl %%edx; popl %%ecx",                          \
-                    PARAVIRT_IRQ_DISABLE, CLBR_EAX)
+#define CLI_STRING                                                     \
+       _paravirt_alt("pushl %%ecx; pushl %%edx;"                       \
+                     "call *paravirt_ops+%c[paravirt_cli_type]*4;"     \
+                     "popl %%edx; popl %%ecx",                         \
+                     "%c[paravirt_cli_type]", "%c[paravirt_clobber]")
+
+#define STI_STRING                                                     \
+       _paravirt_alt("pushl %%ecx; pushl %%edx;"                       \
+                     "call *paravirt_ops+%c[paravirt_sti_type]*4;"     \
+                     "popl %%edx; popl %%ecx",                         \
+                     "%c[paravirt_sti_type]", "%c[paravirt_clobber]")
 
-#define STI_STRING paravirt_alt("pushl %%ecx; pushl %%edx;"            \
-                    "call *paravirt_ops+%c[irq_enable];"               \
-                    "popl %%edx; popl %%ecx",                          \
-                    PARAVIRT_IRQ_ENABLE, CLBR_EAX)
 #define CLI_STI_CLOBBERS , "%eax"
-#define CLI_STI_INPUT_ARGS \
+#define CLI_STI_INPUT_ARGS                                             \
        ,                                                               \
-       [irq_disable] "i" (offsetof(struct paravirt_ops, irq_disable)), \
-       [irq_enable] "i" (offsetof(struct paravirt_ops, irq_enable))
+       [paravirt_cli_type] "i" (PARAVIRT_PATCH(irq_disable)),          \
+       [paravirt_sti_type] "i" (PARAVIRT_PATCH(irq_enable)),           \
+       paravirt_clobber(CLBR_EAX)
+
+/* Make sure as little as possible of this mess escapes. */
+#undef PARAVIRT_CALL
+#undef __PVOP_CALL
+#undef __PVOP_VCALL
+#undef PVOP_VCALL0
+#undef PVOP_CALL0
+#undef PVOP_VCALL1
+#undef PVOP_CALL1
+#undef PVOP_VCALL2
+#undef PVOP_CALL2
+#undef PVOP_VCALL3
+#undef PVOP_CALL3
+#undef PVOP_VCALL4
+#undef PVOP_CALL4
 
 #else  /* __ASSEMBLY__ */
 
-#define PARA_PATCH(ptype, clobbers, ops)       \
+#define PARA_PATCH(off)        ((off) / 4)
+
+#define PARA_SITE(ptype, clobbers, ops)                \
 771:;                                          \
        ops;                                    \
 772:;                                          \
@@ -538,28 +1049,30 @@ static inline unsigned long __raw_local_irq_save(void)
         .short clobbers;                       \
        .popsection
 
-#define INTERRUPT_RETURN                               \
-       PARA_PATCH(PARAVIRT_INTERRUPT_RETURN, CLBR_ANY, \
-       jmp *%cs:paravirt_ops+PARAVIRT_iret)
+#define INTERRUPT_RETURN                                       \
+       PARA_SITE(PARA_PATCH(PARAVIRT_iret), CLBR_NONE,         \
+                 jmp *%cs:paravirt_ops+PARAVIRT_iret)
 
-#define DISABLE_INTERRUPTS(clobbers)                   \
-       PARA_PATCH(PARAVIRT_IRQ_DISABLE, clobbers,      \
-       pushl %ecx; pushl %edx;                         \
-       call *paravirt_ops+PARAVIRT_irq_disable;        \
-       popl %edx; popl %ecx)                           \
+#define DISABLE_INTERRUPTS(clobbers)                                   \
+       PARA_SITE(PARA_PATCH(PARAVIRT_irq_disable), clobbers,           \
+                 pushl %eax; pushl %ecx; pushl %edx;                   \
+                 call *%cs:paravirt_ops+PARAVIRT_irq_disable;          \
+                 popl %edx; popl %ecx; popl %eax)                      \
 
-#define ENABLE_INTERRUPTS(clobbers)                    \
-       PARA_PATCH(PARAVIRT_IRQ_ENABLE, clobbers,       \
-       pushl %ecx; pushl %edx;                         \
-       call *%cs:paravirt_ops+PARAVIRT_irq_enable;     \
-       popl %edx; popl %ecx)
+#define ENABLE_INTERRUPTS(clobbers)                                    \
+       PARA_SITE(PARA_PATCH(PARAVIRT_irq_enable), clobbers,            \
+                 pushl %eax; pushl %ecx; pushl %edx;                   \
+                 call *%cs:paravirt_ops+PARAVIRT_irq_enable;           \
+                 popl %edx; popl %ecx; popl %eax)
 
-#define ENABLE_INTERRUPTS_SYSEXIT                      \
-       PARA_PATCH(PARAVIRT_STI_SYSEXIT, CLBR_ANY,      \
-       jmp *%cs:paravirt_ops+PARAVIRT_irq_enable_sysexit)
+#define ENABLE_INTERRUPTS_SYSEXIT                                      \
+       PARA_SITE(PARA_PATCH(PARAVIRT_irq_enable_sysexit), CLBR_NONE,   \
+                 jmp *%cs:paravirt_ops+PARAVIRT_irq_enable_sysexit)
 
 #define GET_CR0_INTO_EAX                       \
-       call *paravirt_ops+PARAVIRT_read_cr0
+       push %ecx; push %edx;                   \
+       call *paravirt_ops+PARAVIRT_read_cr0;   \
+       pop %edx; pop %ecx
 
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_PARAVIRT */
diff --git a/include/asm-i386/pda.h b/include/asm-i386/pda.h
deleted file mode 100644 (file)
index b12d59a..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-   Per-processor Data Areas
-   Jeremy Fitzhardinge <jeremy@goop.org> 2006
-   Based on asm-x86_64/pda.h by Andi Kleen.
- */
-#ifndef _I386_PDA_H
-#define _I386_PDA_H
-
-#include <linux/stddef.h>
-#include <linux/types.h>
-
-struct i386_pda
-{
-       struct i386_pda *_pda;          /* pointer to self */
-
-       int cpu_number;
-       struct task_struct *pcurrent;   /* current process */
-       struct pt_regs *irq_regs;
-};
-
-extern struct i386_pda *_cpu_pda[];
-
-#define cpu_pda(i)     (_cpu_pda[i])
-
-#define pda_offset(field) offsetof(struct i386_pda, field)
-
-extern void __bad_pda_field(void);
-
-/* This variable is never instantiated.  It is only used as a stand-in
-   for the real per-cpu PDA memory, so that gcc can understand what
-   memory operations the inline asms() below are performing.  This
-   eliminates the need to make the asms volatile or have memory
-   clobbers, so gcc can readily analyse them. */
-extern struct i386_pda _proxy_pda;
-
-#define pda_to_op(op,field,val)                                                \
-       do {                                                            \
-               typedef typeof(_proxy_pda.field) T__;                   \
-               if (0) { T__ tmp__; tmp__ = (val); }                    \
-               switch (sizeof(_proxy_pda.field)) {                     \
-               case 1:                                                 \
-                       asm(op "b %1,%%fs:%c2"                          \
-                           : "+m" (_proxy_pda.field)                   \
-                           :"ri" ((T__)val),                           \
-                            "i"(pda_offset(field)));                   \
-                       break;                                          \
-               case 2:                                                 \
-                       asm(op "w %1,%%fs:%c2"                          \
-                           : "+m" (_proxy_pda.field)                   \
-                           :"ri" ((T__)val),                           \
-                            "i"(pda_offset(field)));                   \
-                       break;                                          \
-               case 4:                                                 \
-                       asm(op "l %1,%%fs:%c2"                          \
-                           : "+m" (_proxy_pda.field)                   \
-                           :"ri" ((T__)val),                           \
-                            "i"(pda_offset(field)));                   \
-                       break;                                          \
-               default: __bad_pda_field();                             \
-               }                                                       \
-       } while (0)
-
-#define pda_from_op(op,field)                                          \
-       ({                                                              \
-               typeof(_proxy_pda.field) ret__;                         \
-               switch (sizeof(_proxy_pda.field)) {                     \
-               case 1:                                                 \
-                       asm(op "b %%fs:%c1,%0"                          \
-                           : "=r" (ret__)                              \
-                           : "i" (pda_offset(field)),                  \
-                             "m" (_proxy_pda.field));                  \
-                       break;                                          \
-               case 2:                                                 \
-                       asm(op "w %%fs:%c1,%0"                          \
-                           : "=r" (ret__)                              \
-                           : "i" (pda_offset(field)),                  \
-                             "m" (_proxy_pda.field));                  \
-                       break;                                          \
-               case 4:                                                 \
-                       asm(op "l %%fs:%c1,%0"                          \
-                           : "=r" (ret__)                              \
-                           : "i" (pda_offset(field)),                  \
-                             "m" (_proxy_pda.field));                  \
-                       break;                                          \
-               default: __bad_pda_field();                             \
-               }                                                       \
-               ret__; })
-
-/* Return a pointer to a pda field */
-#define pda_addr(field)                                                        \
-       ((typeof(_proxy_pda.field) *)((unsigned char *)read_pda(_pda) + \
-                                     pda_offset(field)))
-
-#define read_pda(field) pda_from_op("mov",field)
-#define write_pda(field,val) pda_to_op("mov",field,val)
-#define add_pda(field,val) pda_to_op("add",field,val)
-#define sub_pda(field,val) pda_to_op("sub",field,val)
-#define or_pda(field,val) pda_to_op("or",field,val)
-
-#endif /* _I386_PDA_H */
index 510ae1d..f54830b 100644 (file)
@@ -1,9 +1,32 @@
 #ifndef __ARCH_I386_PERCPU__
 #define __ARCH_I386_PERCPU__
 
-#ifndef __ASSEMBLY__
-#include <asm-generic/percpu.h>
-#else
+#ifdef __ASSEMBLY__
+
+/*
+ * PER_CPU finds an address of a per-cpu variable.
+ *
+ * Args:
+ *    var - variable name
+ *    reg - 32bit register
+ *
+ * The resulting address is stored in the "reg" argument.
+ *
+ * Example:
+ *    PER_CPU(cpu_gdt_descr, %ebx)
+ */
+#ifdef CONFIG_SMP
+#define PER_CPU(var, reg)                              \
+       movl %fs:per_cpu__##this_cpu_off, reg;          \
+       lea per_cpu__##var(reg), reg
+#define PER_CPU_VAR(var)       %fs:per_cpu__##var
+#else /* ! SMP */
+#define PER_CPU(var, reg)                      \
+       movl $per_cpu__##var, reg
+#define PER_CPU_VAR(var)       per_cpu__##var
+#endif /* SMP */
+
+#else /* ...!ASSEMBLY */
 
 /*
  * PER_CPU finds an address of a per-cpu variable.
  *    PER_CPU(cpu_gdt_descr, %ebx)
  */
 #ifdef CONFIG_SMP
-#define PER_CPU(var, cpu) \
-       movl __per_cpu_offset(,cpu,4), cpu;     \
-       addl $per_cpu__/**/var, cpu;
-#else /* ! SMP */
-#define PER_CPU(var, cpu) \
-       movl $per_cpu__/**/var, cpu;
+/* Same as generic implementation except for optimized local access. */
+#define __GENERIC_PER_CPU
+
+/* This is used for other cpus to find our section. */
+extern unsigned long __per_cpu_offset[];
+
+#define per_cpu_offset(x) (__per_cpu_offset[x])
+
+/* Separate out the type, so (int[3], foo) works. */
+#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
+#define DEFINE_PER_CPU(type, name) \
+    __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
+
+/* We can use this directly for local CPU (faster). */
+DECLARE_PER_CPU(unsigned long, this_cpu_off);
+
+/* var is in discarded region: offset to particular copy we want */
+#define per_cpu(var, cpu) (*({                         \
+       extern int simple_indentifier_##var(void);      \
+       RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]); }))
+
+#define __raw_get_cpu_var(var) (*({                                    \
+       extern int simple_indentifier_##var(void);                      \
+       RELOC_HIDE(&per_cpu__##var, x86_read_percpu(this_cpu_off));     \
+}))
+
+#define __get_cpu_var(var) __raw_get_cpu_var(var)
+
+/* A macro to avoid #include hell... */
+#define percpu_modcopy(pcpudst, src, size)                     \
+do {                                                           \
+       unsigned int __i;                                       \
+       for_each_possible_cpu(__i)                              \
+               memcpy((pcpudst)+__per_cpu_offset[__i],         \
+                      (src), (size));                          \
+} while (0)
+
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
+
+/* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */
+#define __percpu_seg "%%fs:"
+#else  /* !SMP */
+#include <asm-generic/percpu.h>
+#define __percpu_seg ""
 #endif /* SMP */
 
+/* For arch-specific code, we can use direct single-insn ops (they
+ * don't give an lvalue though). */
+extern void __bad_percpu_size(void);
+
+#define percpu_to_op(op,var,val)                               \
+       do {                                                    \
+               typedef typeof(var) T__;                        \
+               if (0) { T__ tmp__; tmp__ = (val); }            \
+               switch (sizeof(var)) {                          \
+               case 1:                                         \
+                       asm(op "b %1,"__percpu_seg"%0"          \
+                           : "+m" (var)                        \
+                           :"ri" ((T__)val));                  \
+                       break;                                  \
+               case 2:                                         \
+                       asm(op "w %1,"__percpu_seg"%0"          \
+                           : "+m" (var)                        \
+                           :"ri" ((T__)val));                  \
+                       break;                                  \
+               case 4:                                         \
+                       asm(op "l %1,"__percpu_seg"%0"          \
+                           : "+m" (var)                        \
+                           :"ri" ((T__)val));                  \
+                       break;                                  \
+               default: __bad_percpu_size();                   \
+               }                                               \
+       } while (0)
+
+#define percpu_from_op(op,var)                                 \
+       ({                                                      \
+               typeof(var) ret__;                              \
+               switch (sizeof(var)) {                          \
+               case 1:                                         \
+                       asm(op "b "__percpu_seg"%1,%0"          \
+                           : "=r" (ret__)                      \
+                           : "m" (var));                       \
+                       break;                                  \
+               case 2:                                         \
+                       asm(op "w "__percpu_seg"%1,%0"          \
+                           : "=r" (ret__)                      \
+                           : "m" (var));                       \
+                       break;                                  \
+               case 4:                                         \
+                       asm(op "l "__percpu_seg"%1,%0"          \
+                           : "=r" (ret__)                      \
+                           : "m" (var));                       \
+                       break;                                  \
+               default: __bad_percpu_size();                   \
+               }                                               \
+               ret__; })
+
+#define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var)
+#define x86_write_percpu(var,val) percpu_to_op("mov", per_cpu__##var, val)
+#define x86_add_percpu(var,val) percpu_to_op("add", per_cpu__##var, val)
+#define x86_sub_percpu(var,val) percpu_to_op("sub", per_cpu__##var, val)
+#define x86_or_percpu(var,val) percpu_to_op("or", per_cpu__##var, val)
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ARCH_I386_PERCPU__ */
index c8dc2d0..4743017 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _I386_PGALLOC_H
 #define _I386_PGALLOC_H
 
-#include <asm/fixmap.h>
 #include <linux/threads.h>
 #include <linux/mm.h>          /* for struct page */
 
index 0251807..0f71c9f 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
 #define _I386_PGTABLE_2LEVEL_DEFS_H
 
+#define SHARED_KERNEL_PMD      0
+
 /*
  * traditional i386 two-level paging structure:
  */
index 38c3fcc..a50fd17 100644 (file)
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
  */
+static inline void native_set_pte(pte_t *ptep , pte_t pte)
+{
+       *ptep = pte;
+}
+static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
+                                    pte_t *ptep , pte_t pte)
+{
+       native_set_pte(ptep, pte);
+}
+static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+       *pmdp = pmd;
+}
 #ifndef CONFIG_PARAVIRT
-#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+#define set_pte(pteptr, pteval)                native_set_pte(pteptr, pteval)
+#define set_pte_at(mm,addr,ptep,pteval) native_set_pte_at(mm, addr, ptep, pteval)
+#define set_pmd(pmdptr, pmdval)                native_set_pmd(pmdptr, pmdval)
 #endif
 
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
 #define pte_clear(mm,addr,xp)  do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
 
-#define raw_ptep_get_and_clear(xp)     __pte(xchg(&(xp)->pte_low, 0))
+static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
+{
+       *xp = __pte(0);
+}
+
+#ifdef CONFIG_SMP
+static inline pte_t native_ptep_get_and_clear(pte_t *xp)
+{
+       return __pte(xchg(&xp->pte_low, 0));
+}
+#else
+#define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
+#endif
 
 #define pte_page(x)            pfn_to_page(pte_pfn(x))
 #define pte_none(x)            (!(x).pte_low)
-#define pte_pfn(x)             ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
+#define pte_pfn(x)             (pte_val(x) >> PAGE_SHIFT)
 #define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #define pfn_pmd(pfn, prot)     __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
@@ -66,6 +91,4 @@ static inline int pte_exec_kernel(pte_t pte)
 #define __pte_to_swp_entry(pte)                ((swp_entry_t) { (pte).pte_low })
 #define __swp_entry_to_pte(x)          ((pte_t) { (x).val })
 
-void vmalloc_sync_all(void);
-
 #endif /* _I386_PGTABLE_2LEVEL_H */
index eb3a1ea..c0df89f 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
 #define _I386_PGTABLE_3LEVEL_DEFS_H
 
+#ifdef CONFIG_PARAVIRT
+#define SHARED_KERNEL_PMD      (paravirt_ops.shared_kernel_pmd)
+#else
+#define SHARED_KERNEL_PMD      1
+#endif
+
 /*
  * PGDIR_SHIFT determines what a top-level page table entry can map
  */
index 7a2318f..eb0f1d7 100644 (file)
@@ -42,20 +42,23 @@ static inline int pte_exec_kernel(pte_t pte)
        return pte_x(pte);
 }
 
-#ifndef CONFIG_PARAVIRT
 /* Rules for using set_pte: the pte being assigned *must* be
  * either not present or in a state where the hardware will
  * not attempt to update the pte.  In places where this is
  * not possible, use pte_get_and_clear to obtain the old pte
  * value and then use set_pte to update it.  -ben
  */
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void native_set_pte(pte_t *ptep, pte_t pte)
 {
        ptep->pte_high = pte.pte_high;
        smp_wmb();
        ptep->pte_low = pte.pte_low;
 }
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
+                                    pte_t *ptep , pte_t pte)
+{
+       native_set_pte(ptep, pte);
+}
 
 /*
  * Since this is only called on user PTEs, and the page fault handler
@@ -63,7 +66,8 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
  * we are justified in merely clearing the PTE present bit, followed
  * by a set.  The ordering here is important.
  */
-static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr,
+                                         pte_t *ptep, pte_t pte)
 {
        ptep->pte_low = 0;
        smp_wmb();
@@ -72,32 +76,48 @@ static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, pte
        ptep->pte_low = pte.pte_low;
 }
 
-#define set_pte_atomic(pteptr,pteval) \
-               set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
-#define set_pmd(pmdptr,pmdval) \
-               set_64bit((unsigned long long *)(pmdptr),pmd_val(pmdval))
-#define set_pud(pudptr,pudval) \
-               (*(pudptr) = (pudval))
+static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+       set_64bit((unsigned long long *)(ptep),native_pte_val(pte));
+}
+static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+       set_64bit((unsigned long long *)(pmdp),native_pmd_val(pmd));
+}
+static inline void native_set_pud(pud_t *pudp, pud_t pud)
+{
+       *pudp = pud;
+}
 
 /*
  * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
  * entry, so clear the bottom half first and enforce ordering with a compiler
  * barrier.
  */
-static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        ptep->pte_low = 0;
        smp_wmb();
        ptep->pte_high = 0;
 }
 
-static inline void pmd_clear(pmd_t *pmd)
+static inline void native_pmd_clear(pmd_t *pmd)
 {
        u32 *tmp = (u32 *)pmd;
        *tmp = 0;
        smp_wmb();
        *(tmp + 1) = 0;
 }
+
+#ifndef CONFIG_PARAVIRT
+#define set_pte(ptep, pte)                     native_set_pte(ptep, pte)
+#define set_pte_at(mm, addr, ptep, pte)                native_set_pte_at(mm, addr, ptep, pte)
+#define set_pte_present(mm, addr, ptep, pte)   native_set_pte_present(mm, addr, ptep, pte)
+#define set_pte_atomic(ptep, pte)              native_set_pte_atomic(ptep, pte)
+#define set_pmd(pmdp, pmd)                     native_set_pmd(pmdp, pmd)
+#define set_pud(pudp, pud)                     native_set_pud(pudp, pud)
+#define pte_clear(mm, addr, ptep)              native_pte_clear(mm, addr, ptep)
+#define pmd_clear(pmd)                         native_pmd_clear(pmd)
 #endif
 
 /*
@@ -119,7 +139,8 @@ static inline void pud_clear (pud_t * pud) { }
 #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
                        pmd_index(address))
 
-static inline pte_t raw_ptep_get_and_clear(pte_t *ptep)
+#ifdef CONFIG_SMP
+static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
 {
        pte_t res;
 
@@ -130,6 +151,9 @@ static inline pte_t raw_ptep_get_and_clear(pte_t *ptep)
 
        return res;
 }
+#else
+#define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
+#endif
 
 #define __HAVE_ARCH_PTE_SAME
 static inline int pte_same(pte_t a, pte_t b)
@@ -146,28 +170,21 @@ static inline int pte_none(pte_t pte)
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-       return (pte.pte_low >> PAGE_SHIFT) |
-               (pte.pte_high << (32 - PAGE_SHIFT));
+       return pte_val(pte) >> PAGE_SHIFT;
 }
 
 extern unsigned long long __supported_pte_mask;
 
 static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
 {
-       pte_t pte;
-
-       pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) | \
-                                       (pgprot_val(pgprot) >> 32);
-       pte.pte_high &= (__supported_pte_mask >> 32);
-       pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & \
-                                                       __supported_pte_mask;
-       return pte;
+       return __pte((((unsigned long long)page_nr << PAGE_SHIFT) |
+                     pgprot_val(pgprot)) & __supported_pte_mask);
 }
 
 static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
 {
-       return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) | \
-                       pgprot_val(pgprot)) & __supported_pte_mask);
+       return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) |
+                     pgprot_val(pgprot)) & __supported_pte_mask);
 }
 
 /*
@@ -187,6 +204,4 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
 
 #define __pmd_free_tlb(tlb, x)         do { } while (0)
 
-#define vmalloc_sync_all() ((void)0)
-
 #endif /* _I386_PGTABLE_3LEVEL_H */
index c3b58d4..c6b8b94 100644 (file)
@@ -159,6 +159,7 @@ void paging_init(void);
 
 extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
 #define __PAGE_KERNEL_RO               (__PAGE_KERNEL & ~_PAGE_RW)
+#define __PAGE_KERNEL_RX               (__PAGE_KERNEL_EXEC & ~_PAGE_RW)
 #define __PAGE_KERNEL_NOCACHE          (__PAGE_KERNEL | _PAGE_PCD)
 #define __PAGE_KERNEL_LARGE            (__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC       (__PAGE_KERNEL_EXEC | _PAGE_PSE)
@@ -166,6 +167,7 @@ extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
 #define PAGE_KERNEL            __pgprot(__PAGE_KERNEL)
 #define PAGE_KERNEL_RO         __pgprot(__PAGE_KERNEL_RO)
 #define PAGE_KERNEL_EXEC       __pgprot(__PAGE_KERNEL_EXEC)
+#define PAGE_KERNEL_RX         __pgprot(__PAGE_KERNEL_RX)
 #define PAGE_KERNEL_NOCACHE    __pgprot(__PAGE_KERNEL_NOCACHE)
 #define PAGE_KERNEL_LARGE      __pgprot(__PAGE_KERNEL_LARGE)
 #define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC)
@@ -241,6 +243,8 @@ static inline pte_t pte_mkyoung(pte_t pte)  { (pte).pte_low |= _PAGE_ACCESSED; re
 static inline pte_t pte_mkwrite(pte_t pte)     { (pte).pte_low |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkhuge(pte_t pte)      { (pte).pte_low |= _PAGE_PSE; return pte; }
 
+extern void vmalloc_sync_all(void);
+
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
 #else
@@ -263,9 +267,18 @@ static inline pte_t pte_mkhuge(pte_t pte)  { (pte).pte_low |= _PAGE_PSE; return p
  */
 #define pte_update(mm, addr, ptep)             do { } while (0)
 #define pte_update_defer(mm, addr, ptep)       do { } while (0)
-#define paravirt_map_pt_hook(slot, va, pfn)    do { } while (0)
 #endif
 
+/* local pte updates need not use xchg for locking */
+static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
+{
+       pte_t res = *ptep;
+
+       /* Pure native function needs no input for mm, addr */
+       native_pte_clear(NULL, 0, ptep);
+       return res;
+}
+
 /*
  * We only update the dirty/accessed state if we set
  * the dirty bit by hand in the kernel, since the hardware
@@ -330,7 +343,7 @@ do {                                                                        \
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-       pte_t pte = raw_ptep_get_and_clear(ptep);
+       pte_t pte = native_ptep_get_and_clear(ptep);
        pte_update(mm, addr, ptep);
        return pte;
 }
@@ -340,8 +353,11 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 {
        pte_t pte;
        if (full) {
-               pte = *ptep;
-               pte_clear(mm, addr, ptep);
+               /*
+                * Full address destruction in progress; paravirt does not
+                * care about updates and native needs no locking
+                */
+               pte = native_local_ptep_get_and_clear(ptep);
        } else {
                pte = ptep_get_and_clear(mm, addr, ptep);
        }
@@ -470,24 +486,10 @@ extern pte_t *lookup_address(unsigned long address);
 #endif
 
 #if defined(CONFIG_HIGHPTE)
-#define pte_offset_map(dir, address)                           \
-({                                                             \
-       pte_t *__ptep;                                          \
-       unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;           \
-       __ptep = (pte_t *)kmap_atomic(pfn_to_page(pfn),KM_PTE0);\
-       paravirt_map_pt_hook(KM_PTE0,__ptep, pfn);              \
-       __ptep = __ptep + pte_index(address);                   \
-       __ptep;                                                 \
-})
-#define pte_offset_map_nested(dir, address)                    \
-({                                                             \
-       pte_t *__ptep;                                          \
-       unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;           \
-       __ptep = (pte_t *)kmap_atomic(pfn_to_page(pfn),KM_PTE1);\
-       paravirt_map_pt_hook(KM_PTE1,__ptep, pfn);              \
-       __ptep = __ptep + pte_index(address);                   \
-       __ptep;                                                 \
-})
+#define pte_offset_map(dir, address) \
+       ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+#define pte_offset_map_nested(dir, address) \
+       ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else
@@ -510,6 +512,22 @@ do {                                                                       \
  * tables contain all the necessary information.
  */
 #define update_mmu_cache(vma,address,pte) do { } while (0)
+
+void native_pagetable_setup_start(pgd_t *base);
+void native_pagetable_setup_done(pgd_t *base);
+
+#ifndef CONFIG_PARAVIRT
+static inline void paravirt_pagetable_setup_start(pgd_t *base)
+{
+       native_pagetable_setup_start(base);
+}
+
+static inline void paravirt_pagetable_setup_done(pgd_t *base)
+{
+       native_pagetable_setup_done(base);
+}
+#endif /* !CONFIG_PARAVIRT */
+
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_FLATMEM
diff --git a/include/asm-i386/processor-flags.h b/include/asm-i386/processor-flags.h
new file mode 100644 (file)
index 0000000..5404e90
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __ASM_I386_PROCESSOR_FLAGS_H
+#define __ASM_I386_PROCESSOR_FLAGS_H
+/* Various flags defined: can be included from assembler. */
+
+/*
+ * EFLAGS bits
+ */
+#define X86_EFLAGS_CF  0x00000001 /* Carry Flag */
+#define X86_EFLAGS_PF  0x00000004 /* Parity Flag */
+#define X86_EFLAGS_AF  0x00000010 /* Auxillary carry Flag */
+#define X86_EFLAGS_ZF  0x00000040 /* Zero Flag */
+#define X86_EFLAGS_SF  0x00000080 /* Sign Flag */
+#define X86_EFLAGS_TF  0x00000100 /* Trap Flag */
+#define X86_EFLAGS_IF  0x00000200 /* Interrupt Flag */
+#define X86_EFLAGS_DF  0x00000400 /* Direction Flag */
+#define X86_EFLAGS_OF  0x00000800 /* Overflow Flag */
+#define X86_EFLAGS_IOPL        0x00003000 /* IOPL mask */
+#define X86_EFLAGS_NT  0x00004000 /* Nested Task */
+#define X86_EFLAGS_RF  0x00010000 /* Resume Flag */
+#define X86_EFLAGS_VM  0x00020000 /* Virtual Mode */
+#define X86_EFLAGS_AC  0x00040000 /* Alignment Check */
+#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
+#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
+#define X86_EFLAGS_ID  0x00200000 /* CPUID detection flag */
+
+/*
+ * Basic CPU control in CR0
+ */
+#define X86_CR0_PE     0x00000001 /* Protection Enable */
+#define X86_CR0_MP     0x00000002 /* Monitor Coprocessor */
+#define X86_CR0_EM     0x00000004 /* Emulation */
+#define X86_CR0_TS     0x00000008 /* Task Switched */
+#define X86_CR0_ET     0x00000010 /* Extension Type */
+#define X86_CR0_NE     0x00000020 /* Numeric Error */
+#define X86_CR0_WP     0x00010000 /* Write Protect */
+#define X86_CR0_AM     0x00040000 /* Alignment Mask */
+#define X86_CR0_NW     0x20000000 /* Not Write-through */
+#define X86_CR0_CD     0x40000000 /* Cache Disable */
+#define X86_CR0_PG     0x80000000 /* Paging */
+
+/*
+ * Paging options in CR3
+ */
+#define X86_CR3_PWT    0x00000008 /* Page Write Through */
+#define X86_CR3_PCD    0x00000010 /* Page Cache Disable */
+
+/*
+ * Intel CPU features in CR4
+ */
+#define X86_CR4_VME    0x00000001 /* enable vm86 extensions */
+#define X86_CR4_PVI    0x00000002 /* virtual interrupts flag enable */
+#define X86_CR4_TSD    0x00000004 /* disable time stamp at ipl 3 */
+#define X86_CR4_DE     0x00000008 /* enable debugging extensions */
+#define X86_CR4_PSE    0x00000010 /* enable page size extensions */
+#define X86_CR4_PAE    0x00000020 /* enable physical address extensions */
+#define X86_CR4_MCE    0x00000040 /* Machine check enable */
+#define X86_CR4_PGE    0x00000080 /* enable global pages */
+#define X86_CR4_PCE    0x00000100 /* enable performance counters at ipl 3 */
+#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
+#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
+#define X86_CR4_VMXE   0x00002000 /* enable VMX virtualization */
+
+/*
+ * x86-64 Task Priority Register, CR8
+ */
+#define X86_CR8_TPR    0x00000007 /* task priority register */
+
+/*
+ * AMD and Transmeta use MSRs for configuration; see <asm/msr-index.h>
+ */
+
+/*
+ *      NSC/Cyrix CPU configuration register indexes
+ */
+#define CX86_PCR0      0x20
+#define CX86_GCR       0xb8
+#define CX86_CCR0      0xc0
+#define CX86_CCR1      0xc1
+#define CX86_CCR2      0xc2
+#define CX86_CCR3      0xc3
+#define CX86_CCR4      0xe8
+#define CX86_CCR5      0xe9
+#define CX86_CCR6      0xea
+#define CX86_CCR7      0xeb
+#define CX86_PCR1      0xf0
+#define CX86_DIR0      0xfe
+#define CX86_DIR1      0xff
+#define CX86_ARR_BASE  0xc4
+#define CX86_RCR_BASE  0xdc
+
+#endif /* __ASM_I386_PROCESSOR_FLAGS_H */
index 11bf899..70f3515 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/percpu.h>
 #include <linux/cpumask.h>
 #include <linux/init.h>
+#include <asm/processor-flags.h>
 
 /* flag for disabling the tsc */
 extern int tsc_disable;
@@ -115,7 +116,8 @@ extern char ignore_fpu_irq;
 
 void __init cpu_detect(struct cpuinfo_x86 *c);
 
-extern void identify_cpu(struct cpuinfo_x86 *);
+extern void identify_boot_cpu(void);
+extern void identify_secondary_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
@@ -126,28 +128,7 @@ extern void detect_ht(struct cpuinfo_x86 *c);
 static inline void detect_ht(struct cpuinfo_x86 *c) {}
 #endif
 
-/*
- * EFLAGS bits
- */
-#define X86_EFLAGS_CF  0x00000001 /* Carry Flag */
-#define X86_EFLAGS_PF  0x00000004 /* Parity Flag */
-#define X86_EFLAGS_AF  0x00000010 /* Auxillary carry Flag */
-#define X86_EFLAGS_ZF  0x00000040 /* Zero Flag */
-#define X86_EFLAGS_SF  0x00000080 /* Sign Flag */
-#define X86_EFLAGS_TF  0x00000100 /* Trap Flag */
-#define X86_EFLAGS_IF  0x00000200 /* Interrupt Flag */
-#define X86_EFLAGS_DF  0x00000400 /* Direction Flag */
-#define X86_EFLAGS_OF  0x00000800 /* Overflow Flag */
-#define X86_EFLAGS_IOPL        0x00003000 /* IOPL mask */
-#define X86_EFLAGS_NT  0x00004000 /* Nested Task */
-#define X86_EFLAGS_RF  0x00010000 /* Resume Flag */
-#define X86_EFLAGS_VM  0x00020000 /* Virtual Mode */
-#define X86_EFLAGS_AC  0x00040000 /* Alignment Check */
-#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
-#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
-#define X86_EFLAGS_ID  0x00200000 /* CPUID detection flag */
-
-static inline fastcall void native_cpuid(unsigned int *eax, unsigned int *ebx,
+static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
                                         unsigned int *ecx, unsigned int *edx)
 {
        /* ecx is often an input as well as an output. */
@@ -161,21 +142,6 @@ static inline fastcall void native_cpuid(unsigned int *eax, unsigned int *ebx,
 
 #define load_cr3(pgdir) write_cr3(__pa(pgdir))
 
-/*
- * Intel CPU features in CR4
- */
-#define X86_CR4_VME            0x0001  /* enable vm86 extensions */
-#define X86_CR4_PVI            0x0002  /* virtual interrupts flag enable */
-#define X86_CR4_TSD            0x0004  /* disable time stamp at ipl 3 */
-#define X86_CR4_DE             0x0008  /* enable debugging extensions */
-#define X86_CR4_PSE            0x0010  /* enable page size extensions */
-#define X86_CR4_PAE            0x0020  /* enable physical address extensions */
-#define X86_CR4_MCE            0x0040  /* Machine check enable */
-#define X86_CR4_PGE            0x0080  /* enable global pages */
-#define X86_CR4_PCE            0x0100  /* enable performance counters at ipl 3 */
-#define X86_CR4_OSFXSR         0x0200  /* enable fast FPU save and restore */
-#define X86_CR4_OSXMMEXCPT     0x0400  /* enable unmasked SSE exceptions */
-
 /*
  * Save the cr4 feature set we're using (ie
  * Pentium 4MB enable and PPro Global page
@@ -202,26 +168,6 @@ static inline void clear_in_cr4 (unsigned long mask)
        write_cr4(cr4);
 }
 
-/*
- *      NSC/Cyrix CPU configuration register indexes
- */
-
-#define CX86_PCR0 0x20
-#define CX86_GCR  0xb8
-#define CX86_CCR0 0xc0
-#define CX86_CCR1 0xc1
-#define CX86_CCR2 0xc2
-#define CX86_CCR3 0xc3
-#define CX86_CCR4 0xe8
-#define CX86_CCR5 0xe9
-#define CX86_CCR6 0xea
-#define CX86_CCR7 0xeb
-#define CX86_PCR1 0xf0
-#define CX86_DIR0 0xfe
-#define CX86_DIR1 0xff
-#define CX86_ARR_BASE 0xc4
-#define CX86_RCR_BASE 0xdc
-
 /*
  *      NSC/Cyrix CPU indexed register access macros
  */
@@ -345,7 +291,8 @@ typedef struct {
 
 struct thread_struct;
 
-struct tss_struct {
+/* This is the TSS defined by the hardware. */
+struct i386_hw_tss {
        unsigned short  back_link,__blh;
        unsigned long   esp0;
        unsigned short  ss0,__ss0h;
@@ -369,6 +316,11 @@ struct tss_struct {
        unsigned short  gs, __gsh;
        unsigned short  ldt, __ldth;
        unsigned short  trace, io_bitmap_base;
+} __attribute__((packed));
+
+struct tss_struct {
+       struct i386_hw_tss x86_tss;
+
        /*
         * The extra 1 is there because the CPU will access an
         * additional byte beyond the end of the IO permission
@@ -421,10 +373,11 @@ struct thread_struct {
 };
 
 #define INIT_THREAD  {                                                 \
+       .esp0 = sizeof(init_stack) + (long)&init_stack,                 \
        .vm86_info = NULL,                                              \
        .sysenter_cs = __KERNEL_CS,                                     \
        .io_bitmap_ptr = NULL,                                          \
-       .fs = __KERNEL_PDA,                                             \
+       .fs = __KERNEL_PERCPU,                                          \
 }
 
 /*
@@ -434,10 +387,12 @@ struct thread_struct {
  * be within the limit.
  */
 #define INIT_TSS  {                                                    \
-       .esp0           = sizeof(init_stack) + (long)&init_stack,       \
-       .ss0            = __KERNEL_DS,                                  \
-       .ss1            = __KERNEL_CS,                                  \
-       .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,                     \
+       .x86_tss = {                                                    \
+               .esp0           = sizeof(init_stack) + (long)&init_stack, \
+               .ss0            = __KERNEL_DS,                          \
+               .ss1            = __KERNEL_CS,                          \
+               .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,             \
+        },                                                             \
        .io_bitmap      = { [ 0 ... IO_BITMAP_LONGS] = ~0 },            \
 }
 
@@ -544,40 +499,70 @@ static inline void rep_nop(void)
 
 #define cpu_relax()    rep_nop()
 
-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#define paravirt_enabled() 0
-#define __cpuid native_cpuid
-
-static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread)
 {
-       tss->esp0 = thread->esp0;
+       tss->x86_tss.esp0 = thread->esp0;
        /* This can only happen when SEP is enabled, no need to test "SEP"arately */
-       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
-               tss->ss1 = thread->sysenter_cs;
+       if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
+               tss->x86_tss.ss1 = thread->sysenter_cs;
                wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
        }
 }
 
-/*
- * These special macros can be used to get or set a debugging register
- */
-#define get_debugreg(var, register)                            \
-               __asm__("movl %%db" #register ", %0"            \
-                       :"=r" (var))
-#define set_debugreg(value, register)                  \
-               __asm__("movl %0,%%db" #register                \
-                       : /* no output */                       \
-                       :"r" (value))
 
-#define set_iopl_mask native_set_iopl_mask
-#endif /* CONFIG_PARAVIRT */
+static inline unsigned long native_get_debugreg(int regno)
+{
+       unsigned long val = 0;  /* Damn you, gcc! */
+
+       switch (regno) {
+       case 0:
+               asm("movl %%db0, %0" :"=r" (val)); break;
+       case 1:
+               asm("movl %%db1, %0" :"=r" (val)); break;
+       case 2:
+               asm("movl %%db2, %0" :"=r" (val)); break;
+       case 3:
+               asm("movl %%db3, %0" :"=r" (val)); break;
+       case 6:
+               asm("movl %%db6, %0" :"=r" (val)); break;
+       case 7:
+               asm("movl %%db7, %0" :"=r" (val)); break;
+       default:
+               BUG();
+       }
+       return val;
+}
+
+static inline void native_set_debugreg(int regno, unsigned long value)
+{
+       switch (regno) {
+       case 0:
+               asm("movl %0,%%db0"     : /* no output */ :"r" (value));
+               break;
+       case 1:
+               asm("movl %0,%%db1"     : /* no output */ :"r" (value));
+               break;
+       case 2:
+               asm("movl %0,%%db2"     : /* no output */ :"r" (value));
+               break;
+       case 3:
+               asm("movl %0,%%db3"     : /* no output */ :"r" (value));
+               break;
+       case 6:
+               asm("movl %0,%%db6"     : /* no output */ :"r" (value));
+               break;
+       case 7:
+               asm("movl %0,%%db7"     : /* no output */ :"r" (value));
+               break;
+       default:
+               BUG();
+       }
+}
 
 /*
  * Set IOPL bits in EFLAGS from given mask
  */
-static fastcall inline void native_set_iopl_mask(unsigned mask)
+static inline void native_set_iopl_mask(unsigned mask)
 {
        unsigned int reg;
        __asm__ __volatile__ ("pushfl;"
@@ -590,6 +575,28 @@ static fastcall inline void native_set_iopl_mask(unsigned mask)
                                : "i" (~X86_EFLAGS_IOPL), "r" (mask));
 }
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define paravirt_enabled() 0
+#define __cpuid native_cpuid
+
+static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+{
+       native_load_esp0(tss, thread);
+}
+
+/*
+ * These special macros can be used to get or set a debugging register
+ */
+#define get_debugreg(var, register)                            \
+       (var) = native_get_debugreg(register)
+#define set_debugreg(value, register)                          \
+       native_set_debugreg(register, value)
+
+#define set_iopl_mask native_set_iopl_mask
+#endif /* CONFIG_PARAVIRT */
+
 /*
  * Generic CPUID function
  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
@@ -742,8 +749,10 @@ extern unsigned long boot_option_idle_override;
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
-extern int init_gdt(int cpu, struct task_struct *idle);
 extern void cpu_set_gdt(int);
-extern void secondary_cpu_init(void);
+extern void switch_to_new_gdt(void);
+extern void cpu_init(void);
+
+extern int force_mwait;
 
 #endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-i386/reboot.h b/include/asm-i386/reboot.h
new file mode 100644 (file)
index 0000000..e9e3ffc
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _ASM_REBOOT_H
+#define _ASM_REBOOT_H
+
+struct pt_regs;
+
+struct machine_ops
+{
+       void (*restart)(char *cmd);
+       void (*halt)(void);
+       void (*power_off)(void);
+       void (*shutdown)(void);
+       void (*crash_shutdown)(struct pt_regs *);
+       void (*emergency_restart)(void);
+};
+
+extern struct machine_ops machine_ops;
+
+void machine_real_restart(unsigned char *code, int length);
+
+#endif /* _ASM_REBOOT_H */
diff --git a/include/asm-i386/reboot_fixups.h b/include/asm-i386/reboot_fixups.h
new file mode 100644 (file)
index 0000000..0cb7d87
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _LINUX_REBOOT_FIXUPS_H
+#define _LINUX_REBOOT_FIXUPS_H
+
+extern void mach_reboot_fixups(void);
+
+#endif /* _LINUX_REBOOT_FIXUPS_H */
diff --git a/include/asm-i386/required-features.h b/include/asm-i386/required-features.h
new file mode 100644 (file)
index 0000000..9db866c
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _ASM_REQUIRED_FEATURES_H
+#define _ASM_REQUIRED_FEATURES_H 1
+
+/* Define minimum CPUID feature set for kernel These bits are checked
+   really early to actually display a visible error message before the
+   kernel dies.  Only add word 0 bits here
+
+   Some requirements that are not in CPUID yet are also in the
+   CONFIG_X86_MINIMUM_CPU mode which is checked too.
+
+   The real information is in arch/i386/Kconfig.cpu, this just converts
+   the CONFIGs into a bitmask */
+
+#ifdef CONFIG_X86_PAE
+#define NEED_PAE       (1<<X86_FEATURE_PAE)
+#else
+#define NEED_PAE       0
+#endif
+
+#ifdef CONFIG_X86_CMOV
+#define NEED_CMOV      (1<<X86_FEATURE_CMOV)
+#else
+#define NEED_CMOV      0
+#endif
+
+#ifdef CONFIG_X86_CMPXCHG64
+#define NEED_CMPXCHG64  (1<<X86_FEATURE_CX8)
+#else
+#define NEED_CMPXCHG64  0
+#endif
+
+#define REQUIRED_MASK1 (NEED_PAE|NEED_CMOV|NEED_CMPXCHG64)
+
+#endif
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 065f10b..597a47c 100644 (file)
@@ -39,7 +39,7 @@
  *  25 - APM BIOS support 
  *
  *  26 - ESPFIX small SS
- *  27 - PDA                           [ per-cpu private data area ]
+ *  27 - per-cpu                       [ offset to per-cpu data area ]
  *  28 - unused
  *  29 - unused
  *  30 - unused
 #define GDT_ENTRY_ESPFIX_SS            (GDT_ENTRY_KERNEL_BASE + 14)
 #define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
 
-#define GDT_ENTRY_PDA                  (GDT_ENTRY_KERNEL_BASE + 15)
-#define __KERNEL_PDA (GDT_ENTRY_PDA * 8)
+#define GDT_ENTRY_PERCPU                       (GDT_ENTRY_KERNEL_BASE + 15)
+#ifdef CONFIG_SMP
+#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
+#else
+#define __KERNEL_PERCPU 0
+#endif
 
 #define GDT_ENTRY_DOUBLEFAULT_TSS      31
 
index 6bf0033..090abc1 100644 (file)
@@ -8,19 +8,15 @@
 #include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
-#include <asm/pda.h>
 #endif
 
-#ifdef CONFIG_X86_LOCAL_APIC
-#ifndef __ASSEMBLY__
-#include <asm/fixmap.h>
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(__ASSEMBLY__)
 #include <asm/bitops.h>
 #include <asm/mpspec.h>
+#include <asm/apic.h>
 #ifdef CONFIG_X86_IO_APIC
 #include <asm/io_apic.h>
 #endif
-#include <asm/apic.h>
-#endif
 #endif
 
 #define BAD_APICID 0xFFu
@@ -52,6 +48,59 @@ extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);
 #endif
 
+struct smp_ops
+{
+       void (*smp_prepare_boot_cpu)(void);
+       void (*smp_prepare_cpus)(unsigned max_cpus);
+       int (*cpu_up)(unsigned cpu);
+       void (*smp_cpus_done)(unsigned max_cpus);
+
+       void (*smp_send_stop)(void);
+       void (*smp_send_reschedule)(int cpu);
+       int (*smp_call_function_mask)(cpumask_t mask,
+                                     void (*func)(void *info), void *info,
+                                     int wait);
+};
+
+extern struct smp_ops smp_ops;
+
+static inline void smp_prepare_boot_cpu(void)
+{
+       smp_ops.smp_prepare_boot_cpu();
+}
+static inline void smp_prepare_cpus(unsigned int max_cpus)
+{
+       smp_ops.smp_prepare_cpus(max_cpus);
+}
+static inline int __cpu_up(unsigned int cpu)
+{
+       return smp_ops.cpu_up(cpu);
+}
+static inline void smp_cpus_done(unsigned int max_cpus)
+{
+       smp_ops.smp_cpus_done(max_cpus);
+}
+
+static inline void smp_send_stop(void)
+{
+       smp_ops.smp_send_stop();
+}
+static inline void smp_send_reschedule(int cpu)
+{
+       smp_ops.smp_send_reschedule(cpu);
+}
+static inline int smp_call_function_mask(cpumask_t mask,
+                                        void (*func) (void *info), void *info,
+                                        int wait)
+{
+       return smp_ops.smp_call_function_mask(mask, func, info, wait);
+}
+
+void native_smp_prepare_boot_cpu(void);
+void native_smp_prepare_cpus(unsigned int max_cpus);
+int native_cpu_up(unsigned int cpunum);
+void native_smp_cpus_done(unsigned int max_cpus);
+
 #ifndef CONFIG_PARAVIRT
 #define startup_ipi_hook(phys_apicid, start_eip, start_esp)            \
 do { } while (0)
@@ -62,7 +111,8 @@ do { } while (0)
  * from the initial startup. We map APIC_BASE very early in page_setup(),
  * so this is correct in the x86 case.
  */
-#define raw_smp_processor_id() (read_pda(cpu_number))
+DECLARE_PER_CPU(int, cpu_number);
+#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
 
 extern cpumask_t cpu_callout_map;
 extern cpumask_t cpu_callin_map;
index a6d20d9..c3a58c0 100644 (file)
@@ -88,65 +88,96 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
 #define savesegment(seg, value) \
        asm volatile("mov %%" #seg ",%0":"=rm" (value))
 
+
+static inline void native_clts(void)
+{
+       asm volatile ("clts");
+}
+
+static inline unsigned long native_read_cr0(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static inline void native_write_cr0(unsigned long val)
+{
+       asm volatile("movl %0,%%cr0": :"r" (val));
+}
+
+static inline unsigned long native_read_cr2(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr2,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static inline void native_write_cr2(unsigned long val)
+{
+       asm volatile("movl %0,%%cr2": :"r" (val));
+}
+
+static inline unsigned long native_read_cr3(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static inline void native_write_cr3(unsigned long val)
+{
+       asm volatile("movl %0,%%cr3": :"r" (val));
+}
+
+static inline unsigned long native_read_cr4(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static inline unsigned long native_read_cr4_safe(void)
+{
+       unsigned long val;
+       /* This could fault if %cr4 does not exist */
+       asm("1: movl %%cr4, %0          \n"
+               "2:                             \n"
+               ".section __ex_table,\"a\"      \n"
+               ".long 1b,2b                    \n"
+               ".previous                      \n"
+               : "=r" (val): "0" (0));
+       return val;
+}
+
+static inline void native_write_cr4(unsigned long val)
+{
+       asm volatile("movl %0,%%cr4": :"r" (val));
+}
+
+static inline void native_wbinvd(void)
+{
+       asm volatile("wbinvd": : :"memory");
+}
+
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
-#define read_cr0() ({ \
-       unsigned int __dummy; \
-       __asm__ __volatile__( \
-               "movl %%cr0,%0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define write_cr0(x) \
-       __asm__ __volatile__("movl %0,%%cr0": :"r" (x))
-
-#define read_cr2() ({ \
-       unsigned int __dummy; \
-       __asm__ __volatile__( \
-               "movl %%cr2,%0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define write_cr2(x) \
-       __asm__ __volatile__("movl %0,%%cr2": :"r" (x))
-
-#define read_cr3() ({ \
-       unsigned int __dummy; \
-       __asm__ ( \
-               "movl %%cr3,%0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define write_cr3(x) \
-       __asm__ __volatile__("movl %0,%%cr3": :"r" (x))
-
-#define read_cr4() ({ \
-       unsigned int __dummy; \
-       __asm__( \
-               "movl %%cr4,%0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define read_cr4_safe() ({                           \
-       unsigned int __dummy;                         \
-       /* This could fault if %cr4 does not exist */ \
-       __asm__("1: movl %%cr4, %0              \n"   \
-               "2:                             \n"   \
-               ".section __ex_table,\"a\"      \n"   \
-               ".long 1b,2b                    \n"   \
-               ".previous                      \n"   \
-               : "=r" (__dummy): "0" (0));           \
-       __dummy;                                      \
-})
-#define write_cr4(x) \
-       __asm__ __volatile__("movl %0,%%cr4": :"r" (x))
-
-#define wbinvd() \
-       __asm__ __volatile__ ("wbinvd": : :"memory")
+#define read_cr0()     (native_read_cr0())
+#define write_cr0(x)   (native_write_cr0(x))
+#define read_cr2()     (native_read_cr2())
+#define write_cr2(x)   (native_write_cr2(x))
+#define read_cr3()     (native_read_cr3())
+#define write_cr3(x)   (native_write_cr3(x))
+#define read_cr4()     (native_read_cr4())
+#define read_cr4_safe()        (native_read_cr4_safe())
+#define write_cr4(x)   (native_write_cr4(x))
+#define wbinvd()       (native_wbinvd())
 
 /* Clear the 'TS' bit */
-#define clts() __asm__ __volatile__ ("clts")
+#define clts()         (native_clts())
+
 #endif/* CONFIG_PARAVIRT */
 
 /* Set the 'TS' bit */
index 12dd67b..153770e 100644 (file)
@@ -9,8 +9,6 @@ void setup_pit_timer(void);
 unsigned long long native_sched_clock(void);
 unsigned long native_calculate_cpu_khz(void);
 
-/* Modifiers for buggy PIT handling */
-extern int pit_latch_buggy;
 extern int timer_ack;
 extern int no_timer_check;
 extern int no_sync_cmos_clock;
index 4dd8284..db7f77e 100644 (file)
  *  - flush_tlb_range(vma, start, end) flushes a range of pages
  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
  *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ *  - flush_tlb_others(cpumask, mm, va) flushes a TLBs on other cpus
  *
  * ..but the i386 has somewhat limited tlb flushing capabilities,
  * and page-granular flushes are available only on i486 and up.
  */
 
+#define TLB_FLUSH_ALL  0xffffffff
+
+
 #ifndef CONFIG_SMP
 
 #define flush_tlb() __flush_tlb()
@@ -110,7 +114,12 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
                __flush_tlb();
 }
 
-#else
+static inline void native_flush_tlb_others(const cpumask_t *cpumask,
+                                          struct mm_struct *mm, unsigned long va)
+{
+}
+
+#else  /* SMP */
 
 #include <asm/smp.h>
 
@@ -129,6 +138,9 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st
        flush_tlb_mm(vma->vm_mm);
 }
 
+void native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm,
+                            unsigned long va);
+
 #define TLBSTATE_OK    1
 #define TLBSTATE_LAZY  2
 
@@ -139,8 +151,11 @@ struct tlb_state
        char __cacheline_padding[L1_CACHE_BYTES-8];
 };
 DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
+#endif /* SMP */
 
-
+#ifndef CONFIG_PARAVIRT
+#define flush_tlb_others(mask, mm, va)         \
+       native_flush_tlb_others(&mask, mm, va)
 #endif
 
 #define flush_tlb_kernel_range(start, end) flush_tlb_all()
index 84016ff..3f3c1fa 100644 (file)
@@ -35,25 +35,30 @@ static inline cycles_t get_cycles(void)
 static __always_inline cycles_t get_cycles_sync(void)
 {
        unsigned long long ret;
-#ifdef X86_FEATURE_SYNC_RDTSC
        unsigned eax;
 
+       /*
+        * Use RDTSCP if possible; it is guaranteed to be synchronous
+        * and doesn't cause a VMEXIT on Hypervisors
+        */
+       alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP,
+                                "=A" (ret), "0" (0ULL) : "ecx", "memory");
+       if (ret)
+               return ret;
+
        /*
         * Don't do an additional sync on CPUs where we know
         * RDTSC is already synchronous:
         */
        alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
                          "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
-#else
-       sync_core();
-#endif
        rdtscll(ret);
 
        return ret;
 }
 
 extern void tsc_init(void);
-extern void mark_tsc_unstable(void);
+extern void mark_tsc_unstable(char *reason);
 extern int unsynchronized_tsc(void);
 extern void init_tsc_clocksource(void);
 
index 70829ae..e2aa5e0 100644 (file)
@@ -397,7 +397,19 @@ unsigned long __must_check __copy_from_user_ll_nocache(void *to,
 unsigned long __must_check __copy_from_user_ll_nocache_nozero(void *to,
                                const void __user *from, unsigned long n);
 
-/*
+/**
+ * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ * The caller should also make sure he pins the user space address
+ * so that the we don't result in page fault and sleep.
+ *
  * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
  * we return the initial request size (1, 2 or 4), as copy_*_user should do.
  * If a store crosses a page boundary and gets a fault, the x86 will not write
index c3a1fcf..213930b 100644 (file)
@@ -53,22 +53,8 @@ extern unsigned long long vmi_get_sched_cycles(void);
 extern unsigned long vmi_cpu_khz(void);
 
 #ifdef CONFIG_X86_LOCAL_APIC
-extern void __init vmi_timer_setup_boot_alarm(void);
-extern void __devinit vmi_timer_setup_secondary_alarm(void);
-extern void apic_vmi_timer_interrupt(void);
-#endif
-
-#ifdef CONFIG_NO_IDLE_HZ
-extern int vmi_stop_hz_timer(void);
-extern void vmi_account_time_restart_hz_timer(void);
-#else
-static inline int vmi_stop_hz_timer(void)
-{
-       return 0;
-}
-static inline void vmi_account_time_restart_hz_timer(void)
-{
-}
+extern void __devinit vmi_time_bsp_init(void);
+extern void __devinit vmi_time_ap_init(void);
 #endif
 
 /*
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 b5c6508..cef2400 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/processor.h>
+#include <asm-generic/mm_hooks.h>
 
 struct ia64_ctx {
        spinlock_t lock;
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 1f40d4a..91909e5 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/pgalloc.h>
 #include <asm/mmu.h>
 #include <asm/tlbflush.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * Cache of MMU context last used.
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 231d11b..894dacb 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __M68K_MMU_CONTEXT_H
 #define __M68K_MMU_CONTEXT_H
 
+#include <asm-generic/mm_hooks.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
index 6c077d3..9ccee42 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm-generic/mm_hooks.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
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 fe065d6..65024ff 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/smtc.h>
 #endif /* SMTC */
+#include <asm-generic/mm_hooks.h>
 
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
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 9c05836..bad6902 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
+#include <asm-generic/mm_hooks.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
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 083ac91..c0d7795 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mm.h>  
 #include <asm/mmu.h>   
 #include <asm/cputable.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * Copyright (C) 2001 PPC 64 Team, IBM Corp
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 2bc8589..a6441a0 100644 (file)
@@ -6,6 +6,7 @@
 #include <asm/bitops.h>
 #include <asm/mmu.h>
 #include <asm/cputable.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
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 1d21da2..501cb9b 100644 (file)
@@ -10,6 +10,8 @@
 #define __S390_MMU_CONTEXT_H
 
 #include <asm/pgalloc.h>
+#include <asm-generic/mm_hooks.h>
+
 /*
  * get a new mmu context.. S390 don't know about contexts.
  */
index 3420244..01acaaa 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * The MMU "context" consists of two things:
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 8c860da..507bf72 100644 (file)
@@ -27,7 +27,7 @@
 extern unsigned long mmu_context_cache;
 
 #include <asm/page.h>
-
+#include <asm-generic/mm_hooks.h>
 
 /* Current mm's pgd */
 extern pgd_t *mmu_pdtp_cache;
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 ed1e01d..671a997 100644 (file)
@@ -5,6 +5,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm-generic/mm_hooks.h>
+
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
index 2337eb4..8d12903 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
+#include <asm-generic/mm_hooks.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
index 0d3df76..ced8cbd 100644 (file)
@@ -5,16 +5,6 @@
 
 #ifdef CONFIG_SMP
 
-#ifdef CONFIG_MODULES
-# define PERCPU_MODULE_RESERVE 8192
-#else
-# define PERCPU_MODULE_RESERVE 0
-#endif
-
-#define PERCPU_ENOUGH_ROOM \
-       (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
-        PERCPU_MODULE_RESERVE)
-
 extern void setup_per_cpu_areas(void);
 
 extern unsigned long __per_cpu_base;
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 f709c78..9aa4b44 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __UM_MMU_CONTEXT_H
 #define __UM_MMU_CONTEXT_H
 
+#include <asm-generic/mm_hooks.h>
+
 #include "linux/sched.h"
 #include "choose-mode.h"
 #include "um_mmu.h"
index f521c80..01daacd 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __V850_MMU_CONTEXT_H__
 #define __V850_MMU_CONTEXT_H__
 
+#include <asm-generic/mm_hooks.h>
+
 #define destroy_context(mm)            ((void)0)
 #define init_new_context(tsk,mm)       0
 #define switch_mm(prev,next,tsk)       ((void)0)
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 ebd7117..89ad1fc 100644 (file)
@@ -8,7 +8,7 @@ header-y += boot.h
 header-y += bootsetup.h
 header-y += debugreg.h
 header-y += ldt.h
-header-y += msr.h
+header-y += msr-index.h
 header-y += prctl.h
 header-y += ptrace-abi.h
 header-y += sigcontext32.h
@@ -16,5 +16,7 @@ header-y += ucontext.h
 header-y += vsyscall32.h
 
 unifdef-y += mce.h
+unifdef-y += msr.h
 unifdef-y += mtrr.h
 unifdef-y += vsyscall.h
+unifdef-y += const.h
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 a6657b4..a09fe85 100644 (file)
@@ -16,6 +16,7 @@ struct alt_instr {
        u8  pad[5];
 };
 
+extern void alternative_instructions(void);
 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
 
 struct module;
@@ -141,8 +142,8 @@ void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
 static inline void
 apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
 {}
-#define __start_parainstructions NULL
-#define __stop_parainstructions NULL
+#define __parainstructions NULL
+#define __parainstructions_end NULL
 #endif
 
 #endif /* _X86_64_ALTERNATIVE_H */
index 7cfb39c..45e9fca 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_APIC_H
 
 #include <linux/pm.h>
+#include <linux/delay.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/system.h>
@@ -47,11 +48,8 @@ static __inline unsigned int apic_read(unsigned long reg)
        return *((volatile unsigned int *)(APIC_BASE+reg));
 }
 
-static __inline__ void apic_wait_icr_idle(void)
-{
-       while (apic_read( APIC_ICR ) & APIC_ICR_BUSY)
-               cpu_relax();
-}
+extern void apic_wait_icr_idle(void);
+extern unsigned int safe_apic_wait_icr_idle(void);
 
 static inline void ack_APIC_irq(void)
 {
@@ -83,7 +81,7 @@ extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
-extern void clustered_apic_check(void);
+extern void setup_apic_routing(void);
 
 extern void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
                                   unsigned char msg_type, unsigned char mask);
index d86c5dd..b33dc04 100644 (file)
@@ -1,28 +1,6 @@
-/*
- *  include/asm-x86_64/bugs.h
- *
- *  Copyright (C) 1994  Linus Torvalds
- *  Copyright (C) 2000  SuSE
- *
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- *     void check_bugs(void);
- */
+#ifndef _ASM_X86_64_BUGS_H
+#define _ASM_X86_64_BUGS_H
 
-#include <asm/processor.h>
-#include <asm/i387.h>
-#include <asm/msr.h>
-#include <asm/pda.h>
+void check_bugs(void);
 
-extern void alternative_instructions(void);
-
-static void __init check_bugs(void)
-{
-       identify_cpu(&boot_cpu_data);
-#if !defined(CONFIG_SMP)
-       printk("CPU: ");
-       print_cpu_info(&boot_cpu_data);
-#endif
-       alternative_instructions(); 
-}
+#endif /* _ASM_X86_64_BUGS_H */
diff --git a/include/asm-x86_64/const.h b/include/asm-x86_64/const.h
new file mode 100644 (file)
index 0000000..54fb08f
--- /dev/null
@@ -0,0 +1,20 @@
+/* const.h: Macros for dealing with constants.  */
+
+#ifndef _X86_64_CONST_H
+#define _X86_64_CONST_H
+
+/* Some constant macros are used in both assembler and
+ * C code.  Therefore we cannot annotate them always with
+ * 'UL' and other type specificers unilaterally.  We
+ * use the following macros to deal with this.
+ */
+
+#ifdef __ASSEMBLY__
+#define _AC(X,Y)       X
+#else
+#define __AC(X,Y)      (X##Y)
+#define _AC(X,Y)       __AC(X,Y)
+#endif
+
+
+#endif /* !(_X86_64_CONST_H) */
index 913d6ac..ac991b5 100644 (file)
@@ -107,16 +107,6 @@ static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
                              DESC_LDT, size * 8 - 1);
 }
 
-static inline void set_seg_base(unsigned cpu, int entry, void *base)
-{ 
-       struct desc_struct *d = &cpu_gdt(cpu)[entry];
-       u32 addr = (u32)(u64)base;
-       BUG_ON((u64)base >> 32); 
-       d->base0 = addr & 0xffff;
-       d->base1 = (addr >> 16) & 0xff;
-       d->base2 = (addr >> 24) & 0xff;
-} 
-
 #define LDT_entry_a(info) \
        ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
 /* Don't allow setting of the lm bit. It is useless anyways because 
@@ -145,16 +135,13 @@ static inline void set_seg_base(unsigned cpu, int entry, void *base)
        (info)->useable         == 0    && \
        (info)->lm              == 0)
 
-#if TLS_SIZE != 24
-# error update this code.
-#endif
-
 static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 {
+       unsigned int i;
        u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
-       gdt[0] = t->tls_array[0];
-       gdt[1] = t->tls_array[1];
-       gdt[2] = t->tls_array[2];
+
+       for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+               gdt[i] = t->tls_array[i];
 } 
 
 /*
index d2af227..6897e2a 100644 (file)
@@ -52,7 +52,7 @@ struct dma_mapping_ops {
 };
 
 extern dma_addr_t bad_dma_address;
-extern struct dma_mapping_ops* dma_ops;
+extern const struct dma_mapping_ops* dma_ops;
 extern int iommu_merge;
 
 static inline int dma_mapping_error(dma_addr_t dma_addr)
index 1b620db..e90e167 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/apicdef.h>
 #include <asm/page.h>
 #include <asm/vsyscall.h>
-#include <asm/vsyscall32.h>
 
 /*
  * Here we define all the compile-time 'special' virtual
index b80f4bb..d7e516c 100644 (file)
@@ -29,7 +29,9 @@ struct genapic {
        unsigned int (*phys_pkg_id)(int index_msb);
 };
 
+extern struct genapic *genapic;
 
-extern struct genapic *genapic, *genapic_force, apic_flat;
+extern struct genapic apic_flat;
+extern struct genapic apic_physflat;
 
 #endif
index 2a5c162..a7c75ea 100644 (file)
  * Subject to the GNU Public License, v.2
  */
 
-#include <asm/fixmap.h>
 #include <asm/hw_irq.h>
-#include <asm/apicdef.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
 
 /*
  * the following functions deal with sending IPIs between CPUs.
@@ -76,10 +74,42 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsign
        apic_write(APIC_ICR, cfg);
 }
 
+/*
+ * This is used to send an IPI with no shorthand notation (the destination is
+ * specified in bits 56 to 63 of the ICR).
+ */
+static inline void __send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
+{
+       unsigned long cfg;
+
+       /*
+        * Wait for idle.
+        */
+       if (unlikely(vector == NMI_VECTOR))
+               safe_apic_wait_icr_idle();
+       else
+               apic_wait_icr_idle();
+
+       /*
+        * prepare target chip field
+        */
+       cfg = __prepare_ICR2(mask);
+       apic_write(APIC_ICR2, cfg);
+
+       /*
+        * program the ICR
+        */
+       cfg = __prepare_ICR(0, vector, dest);
+
+       /*
+        * Send the IPI. The write to APIC_ICR fires this off.
+        */
+       apic_write(APIC_ICR, cfg);
+}
 
 static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
 {
-       unsigned long cfg, flags;
+       unsigned long flags;
        unsigned long query_cpu;
 
        /*
@@ -88,28 +118,9 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
         * - mbligh
         */
        local_irq_save(flags);
-
        for_each_cpu_mask(query_cpu, mask) {
-               /*
-                * Wait for idle.
-                */
-               apic_wait_icr_idle();
-
-               /*
-                * prepare target chip field
-                */
-               cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
-               apic_write(APIC_ICR2, cfg);
-
-               /*
-                * program the ICR
-                */
-               cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL);
-
-               /*
-                * Send the IPI. The write to APIC_ICR fires this off.
-                */
-               apic_write(APIC_ICR, cfg);
+               __send_IPI_dest_field(x86_cpu_to_apicid[query_cpu],
+                                     vector, APIC_DEST_PHYSICAL);
        }
        local_irq_restore(flags);
 }
index cce6937..86e70fe 100644 (file)
@@ -9,6 +9,7 @@
  */
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
+#include <asm/processor-flags.h>
 
 #ifndef __ASSEMBLY__
 /*
@@ -53,19 +54,19 @@ static inline void raw_local_irq_disable(void)
 {
        unsigned long flags = __raw_local_save_flags();
 
-       raw_local_irq_restore((flags & ~(1 << 9)) | (1 << 18));
+       raw_local_irq_restore((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
 }
 
 static inline void raw_local_irq_enable(void)
 {
        unsigned long flags = __raw_local_save_flags();
 
-       raw_local_irq_restore((flags | (1 << 9)) & ~(1 << 18));
+       raw_local_irq_restore((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
 }
 
 static inline int raw_irqs_disabled_flags(unsigned long flags)
 {
-       return !(flags & (1<<9)) || (flags & (1 << 18));
+       return !(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC);
 }
 
 #else /* CONFIG_X86_VSMP */
@@ -82,7 +83,7 @@ static inline void raw_local_irq_enable(void)
 
 static inline int raw_irqs_disabled_flags(unsigned long flags)
 {
-       return !(flags & (1 << 9));
+       return !(flags & X86_EFLAGS_IF);
 }
 
 #endif
index af03b9f..0cce83a 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/pda.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
+#include <asm-generic/mm_hooks.h>
 
 /*
  * possibly do the LDT unload here?
index fb558fb..19a8937 100644 (file)
@@ -49,7 +49,7 @@ extern int pfn_valid(unsigned long pfn);
 
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE     (64*1024*1024)
-#define FAKE_NODE_MIN_HASH_MASK        (~(FAKE_NODE_MIN_SIZE - 1ul))
+#define FAKE_NODE_MIN_HASH_MASK        (~(FAKE_NODE_MIN_SIZE - 1uL))
 #endif
 
 #endif
diff --git a/include/asm-x86_64/msr-index.h b/include/asm-x86_64/msr-index.h
new file mode 100644 (file)
index 0000000..d77a63f
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-i386/msr-index.h>
index 902f9a5..a524f03 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef X86_64_MSR_H
 #define X86_64_MSR_H 1
 
+#include <asm/msr-index.h>
+
 #ifndef __ASSEMBLY__
 /*
  * Access to machine-specific registers (available on 586 and better only)
@@ -157,9 +159,6 @@ static inline unsigned int cpuid_edx(unsigned int op)
        return edx;
 }
 
-#define MSR_IA32_UCODE_WRITE           0x79
-#define MSR_IA32_UCODE_REV             0x8b
-
 #ifdef CONFIG_SMP
 void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
@@ -172,269 +171,6 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        wrmsr(msr_no, l, h);
 }
-#endif  /*  CONFIG_SMP  */
-
-#endif
-
-/* AMD/K8 specific MSRs */ 
-#define MSR_EFER 0xc0000080            /* extended feature register */
-#define MSR_STAR 0xc0000081            /* legacy mode SYSCALL target */
-#define MSR_LSTAR 0xc0000082           /* long mode SYSCALL target */
-#define MSR_CSTAR 0xc0000083           /* compatibility mode SYSCALL target */
-#define MSR_SYSCALL_MASK 0xc0000084    /* EFLAGS mask for syscall */
-#define MSR_FS_BASE 0xc0000100         /* 64bit FS base */
-#define MSR_GS_BASE 0xc0000101         /* 64bit GS base */
-#define MSR_KERNEL_GS_BASE  0xc0000102 /* SwapGS GS shadow (or USER_GS from kernel) */ 
-/* EFER bits: */ 
-#define _EFER_SCE 0  /* SYSCALL/SYSRET */
-#define _EFER_LME 8  /* Long mode enable */
-#define _EFER_LMA 10 /* Long mode active (read-only) */
-#define _EFER_NX 11  /* No execute enable */
-
-#define EFER_SCE (1<<_EFER_SCE)
-#define EFER_LME (1<<_EFER_LME)
-#define EFER_LMA (1<<_EFER_LMA)
-#define EFER_NX (1<<_EFER_NX)
-
-/* Intel MSRs. Some also available on other CPUs */
-#define MSR_IA32_TSC           0x10
-#define MSR_IA32_PLATFORM_ID   0x17
-
-#define MSR_IA32_PERFCTR0      0xc1
-#define MSR_IA32_PERFCTR1      0xc2
-#define MSR_FSB_FREQ           0xcd
-
-#define MSR_MTRRcap            0x0fe
-#define MSR_IA32_BBL_CR_CTL        0x119
-
-#define MSR_IA32_SYSENTER_CS   0x174
-#define MSR_IA32_SYSENTER_ESP  0x175
-#define MSR_IA32_SYSENTER_EIP  0x176
-
-#define MSR_IA32_MCG_CAP       0x179
-#define MSR_IA32_MCG_STATUS        0x17a
-#define MSR_IA32_MCG_CTL       0x17b
-
-#define MSR_IA32_EVNTSEL0      0x186
-#define MSR_IA32_EVNTSEL1      0x187
-
-#define MSR_IA32_DEBUGCTLMSR       0x1d9
-#define MSR_IA32_LASTBRANCHFROMIP  0x1db
-#define MSR_IA32_LASTBRANCHTOIP        0x1dc
-#define MSR_IA32_LASTINTFROMIP     0x1dd
-#define MSR_IA32_LASTINTTOIP       0x1de
-
-#define MSR_IA32_PEBS_ENABLE           0x3f1
-#define MSR_IA32_DS_AREA               0x600
-#define MSR_IA32_PERF_CAPABILITIES     0x345
-
-#define MSR_MTRRfix64K_00000   0x250
-#define MSR_MTRRfix16K_80000   0x258
-#define MSR_MTRRfix16K_A0000   0x259
-#define MSR_MTRRfix4K_C0000    0x268
-#define MSR_MTRRfix4K_C8000    0x269
-#define MSR_MTRRfix4K_D0000    0x26a
-#define MSR_MTRRfix4K_D8000    0x26b
-#define MSR_MTRRfix4K_E0000    0x26c
-#define MSR_MTRRfix4K_E8000    0x26d
-#define MSR_MTRRfix4K_F0000    0x26e
-#define MSR_MTRRfix4K_F8000    0x26f
-#define MSR_MTRRdefType                0x2ff
-
-#define MSR_IA32_MC0_CTL       0x400
-#define MSR_IA32_MC0_STATUS        0x401
-#define MSR_IA32_MC0_ADDR      0x402
-#define MSR_IA32_MC0_MISC      0x403
-
-#define MSR_P6_PERFCTR0                        0xc1
-#define MSR_P6_PERFCTR1                        0xc2
-#define MSR_P6_EVNTSEL0                        0x186
-#define MSR_P6_EVNTSEL1                        0x187
-
-/* K7/K8 MSRs. Not complete. See the architecture manual for a more complete list. */
-#define MSR_K7_EVNTSEL0            0xC0010000
-#define MSR_K7_PERFCTR0            0xC0010004
-#define MSR_K7_EVNTSEL1            0xC0010001
-#define MSR_K7_PERFCTR1            0xC0010005
-#define MSR_K7_EVNTSEL2            0xC0010002
-#define MSR_K7_PERFCTR2            0xC0010006
-#define MSR_K7_EVNTSEL3            0xC0010003
-#define MSR_K7_PERFCTR3            0xC0010007
-#define MSR_K8_TOP_MEM1                   0xC001001A
-#define MSR_K8_TOP_MEM2                   0xC001001D
-#define MSR_K8_SYSCFG             0xC0010010
-#define MSR_K8_HWCR               0xC0010015
-
-/* K6 MSRs */
-#define MSR_K6_EFER                    0xC0000080
-#define MSR_K6_STAR                    0xC0000081
-#define MSR_K6_WHCR                    0xC0000082
-#define MSR_K6_UWCCR                   0xC0000085
-#define MSR_K6_PSOR                    0xC0000087
-#define MSR_K6_PFIR                    0xC0000088
-
-/* Centaur-Hauls/IDT defined MSRs. */
-#define MSR_IDT_FCR1                   0x107
-#define MSR_IDT_FCR2                   0x108
-#define MSR_IDT_FCR3                   0x109
-#define MSR_IDT_FCR4                   0x10a
-
-#define MSR_IDT_MCR0                   0x110
-#define MSR_IDT_MCR1                   0x111
-#define MSR_IDT_MCR2                   0x112
-#define MSR_IDT_MCR3                   0x113
-#define MSR_IDT_MCR4                   0x114
-#define MSR_IDT_MCR5                   0x115
-#define MSR_IDT_MCR6                   0x116
-#define MSR_IDT_MCR7                   0x117
-#define MSR_IDT_MCR_CTRL               0x120
-
-/* VIA Cyrix defined MSRs*/
-#define MSR_VIA_FCR                    0x1107
-#define MSR_VIA_LONGHAUL               0x110a
-#define MSR_VIA_RNG                    0x110b
-#define MSR_VIA_BCR2                   0x1147
-
-/* Intel defined MSRs. */
-#define MSR_IA32_P5_MC_ADDR            0
-#define MSR_IA32_P5_MC_TYPE            1
-#define MSR_IA32_PLATFORM_ID           0x17
-#define MSR_IA32_EBL_CR_POWERON                0x2a
-
-#define MSR_IA32_APICBASE               0x1b
-#define MSR_IA32_APICBASE_BSP           (1<<8)
-#define MSR_IA32_APICBASE_ENABLE        (1<<11)
-#define MSR_IA32_APICBASE_BASE          (0xfffff<<12)
-
-/* P4/Xeon+ specific */
-#define MSR_IA32_MCG_EAX               0x180
-#define MSR_IA32_MCG_EBX               0x181
-#define MSR_IA32_MCG_ECX               0x182
-#define MSR_IA32_MCG_EDX               0x183
-#define MSR_IA32_MCG_ESI               0x184
-#define MSR_IA32_MCG_EDI               0x185
-#define MSR_IA32_MCG_EBP               0x186
-#define MSR_IA32_MCG_ESP               0x187
-#define MSR_IA32_MCG_EFLAGS            0x188
-#define MSR_IA32_MCG_EIP               0x189
-#define MSR_IA32_MCG_RESERVED          0x18A
-
-#define MSR_P6_EVNTSEL0                        0x186
-#define MSR_P6_EVNTSEL1                        0x187
-
-#define MSR_IA32_PERF_STATUS           0x198
-#define MSR_IA32_PERF_CTL              0x199
-
-#define MSR_IA32_MPERF                 0xE7
-#define MSR_IA32_APERF                 0xE8
-
-#define MSR_IA32_THERM_CONTROL         0x19a
-#define MSR_IA32_THERM_INTERRUPT       0x19b
-#define MSR_IA32_THERM_STATUS          0x19c
-#define MSR_IA32_MISC_ENABLE           0x1a0
-
-#define MSR_IA32_DEBUGCTLMSR           0x1d9
-#define MSR_IA32_LASTBRANCHFROMIP      0x1db
-#define MSR_IA32_LASTBRANCHTOIP                0x1dc
-#define MSR_IA32_LASTINTFROMIP         0x1dd
-#define MSR_IA32_LASTINTTOIP           0x1de
-
-#define MSR_IA32_MC0_CTL               0x400
-#define MSR_IA32_MC0_STATUS            0x401
-#define MSR_IA32_MC0_ADDR              0x402
-#define MSR_IA32_MC0_MISC              0x403
-
-/* Pentium IV performance counter MSRs */
-#define MSR_P4_BPU_PERFCTR0            0x300
-#define MSR_P4_BPU_PERFCTR1            0x301
-#define MSR_P4_BPU_PERFCTR2            0x302
-#define MSR_P4_BPU_PERFCTR3            0x303
-#define MSR_P4_MS_PERFCTR0             0x304
-#define MSR_P4_MS_PERFCTR1             0x305
-#define MSR_P4_MS_PERFCTR2             0x306
-#define MSR_P4_MS_PERFCTR3             0x307
-#define MSR_P4_FLAME_PERFCTR0          0x308
-#define MSR_P4_FLAME_PERFCTR1          0x309
-#define MSR_P4_FLAME_PERFCTR2          0x30a
-#define MSR_P4_FLAME_PERFCTR3          0x30b
-#define MSR_P4_IQ_PERFCTR0             0x30c
-#define MSR_P4_IQ_PERFCTR1             0x30d
-#define MSR_P4_IQ_PERFCTR2             0x30e
-#define MSR_P4_IQ_PERFCTR3             0x30f
-#define MSR_P4_IQ_PERFCTR4             0x310
-#define MSR_P4_IQ_PERFCTR5             0x311
-#define MSR_P4_BPU_CCCR0               0x360
-#define MSR_P4_BPU_CCCR1               0x361
-#define MSR_P4_BPU_CCCR2               0x362
-#define MSR_P4_BPU_CCCR3               0x363
-#define MSR_P4_MS_CCCR0                0x364
-#define MSR_P4_MS_CCCR1                0x365
-#define MSR_P4_MS_CCCR2                0x366
-#define MSR_P4_MS_CCCR3                0x367
-#define MSR_P4_FLAME_CCCR0             0x368
-#define MSR_P4_FLAME_CCCR1             0x369
-#define MSR_P4_FLAME_CCCR2             0x36a
-#define MSR_P4_FLAME_CCCR3             0x36b
-#define MSR_P4_IQ_CCCR0                0x36c
-#define MSR_P4_IQ_CCCR1                0x36d
-#define MSR_P4_IQ_CCCR2                0x36e
-#define MSR_P4_IQ_CCCR3                0x36f
-#define MSR_P4_IQ_CCCR4                0x370
-#define MSR_P4_IQ_CCCR5                0x371
-#define MSR_P4_ALF_ESCR0               0x3ca
-#define MSR_P4_ALF_ESCR1               0x3cb
-#define MSR_P4_BPU_ESCR0               0x3b2
-#define MSR_P4_BPU_ESCR1               0x3b3
-#define MSR_P4_BSU_ESCR0               0x3a0
-#define MSR_P4_BSU_ESCR1               0x3a1
-#define MSR_P4_CRU_ESCR0               0x3b8
-#define MSR_P4_CRU_ESCR1               0x3b9
-#define MSR_P4_CRU_ESCR2               0x3cc
-#define MSR_P4_CRU_ESCR3               0x3cd
-#define MSR_P4_CRU_ESCR4               0x3e0
-#define MSR_P4_CRU_ESCR5               0x3e1
-#define MSR_P4_DAC_ESCR0               0x3a8
-#define MSR_P4_DAC_ESCR1               0x3a9
-#define MSR_P4_FIRM_ESCR0              0x3a4
-#define MSR_P4_FIRM_ESCR1              0x3a5
-#define MSR_P4_FLAME_ESCR0             0x3a6
-#define MSR_P4_FLAME_ESCR1             0x3a7
-#define MSR_P4_FSB_ESCR0               0x3a2
-#define MSR_P4_FSB_ESCR1               0x3a3
-#define MSR_P4_IQ_ESCR0                0x3ba
-#define MSR_P4_IQ_ESCR1                0x3bb
-#define MSR_P4_IS_ESCR0                0x3b4
-#define MSR_P4_IS_ESCR1                0x3b5
-#define MSR_P4_ITLB_ESCR0              0x3b6
-#define MSR_P4_ITLB_ESCR1              0x3b7
-#define MSR_P4_IX_ESCR0                0x3c8
-#define MSR_P4_IX_ESCR1                0x3c9
-#define MSR_P4_MOB_ESCR0               0x3aa
-#define MSR_P4_MOB_ESCR1               0x3ab
-#define MSR_P4_MS_ESCR0                0x3c0
-#define MSR_P4_MS_ESCR1                0x3c1
-#define MSR_P4_PMH_ESCR0               0x3ac
-#define MSR_P4_PMH_ESCR1               0x3ad
-#define MSR_P4_RAT_ESCR0               0x3bc
-#define MSR_P4_RAT_ESCR1               0x3bd
-#define MSR_P4_SAAT_ESCR0              0x3ae
-#define MSR_P4_SAAT_ESCR1              0x3af
-#define MSR_P4_SSU_ESCR0               0x3be
-#define MSR_P4_SSU_ESCR1               0x3bf    /* guess: not defined in manual */
-#define MSR_P4_TBPU_ESCR0              0x3c2
-#define MSR_P4_TBPU_ESCR1              0x3c3
-#define MSR_P4_TC_ESCR0                0x3c4
-#define MSR_P4_TC_ESCR1                0x3c5
-#define MSR_P4_U2L_ESCR0               0x3b0
-#define MSR_P4_U2L_ESCR1               0x3b1
-
-/* Intel Core-based CPU performance counters */
-#define MSR_CORE_PERF_FIXED_CTR0       0x309
-#define MSR_CORE_PERF_FIXED_CTR1       0x30a
-#define MSR_CORE_PERF_FIXED_CTR2       0x30b
-#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x38d
-#define MSR_CORE_PERF_GLOBAL_STATUS    0x38e
-#define MSR_CORE_PERF_GLOBAL_CTRL      0x38f
-#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x390
-
-#endif
+#endif  /* CONFIG_SMP */
+#endif /* __ASSEMBLY__ */
+#endif /* X86_64_MSR_H */
index d6135b2..b557c48 100644 (file)
@@ -135,6 +135,18 @@ struct mtrr_gentry32
 
 #endif /* CONFIG_COMPAT */
 
+#ifdef CONFIG_MTRR
+extern void mtrr_ap_init(void);
+extern void mtrr_bp_init(void);
+extern void mtrr_save_fixed_ranges(void *);
+extern void mtrr_save_state(void);
+#else
+#define mtrr_ap_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
+#define mtrr_save_fixed_ranges(arg) do {} while (0)
+#define mtrr_save_state() do {} while (0)
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif  /*  _LINUX_MTRR_H  */
index 72375e7..d0a7f53 100644 (file)
@@ -80,4 +80,13 @@ extern int unknown_nmi_panic;
 void __trigger_all_cpu_backtrace(void);
 #define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
 
+
+void lapic_watchdog_stop(void);
+int lapic_watchdog_init(unsigned nmi_hz);
+int lapic_wd_event(unsigned nmi_hz);
+unsigned lapic_adjust_nmi_hz(unsigned hz);
+int lapic_watchdog_ok(void);
+void disable_lapic_nmi_watchdog(void);
+void enable_lapic_nmi_watchdog(void);
+
 #endif /* ASM_NMI_H */
index 10f3461..b17fc16 100644 (file)
@@ -1,14 +1,11 @@
 #ifndef _X86_64_PAGE_H
 #define _X86_64_PAGE_H
 
+#include <asm/const.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE      (0x1 << PAGE_SHIFT)
-#else
-#define PAGE_SIZE      (1UL << PAGE_SHIFT)
-#endif
+#define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 #define PHYSICAL_PAGE_MASK     (~(PAGE_SIZE-1) & __PHYSICAL_MASK)
 
 #define N_EXCEPTION_STACKS 5  /* hw limit: 7 */
 
 #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
-#define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
+#define LARGE_PAGE_SIZE (_AC(1,UL) << PMD_SHIFT)
 
 #define HPAGE_SHIFT PMD_SHIFT
-#define HPAGE_SIZE     ((1UL) << HPAGE_SHIFT)
+#define HPAGE_SIZE     (_AC(1,UL) << HPAGE_SHIFT)
 #define HPAGE_MASK     (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
 
@@ -64,6 +61,8 @@ typedef struct { unsigned long pgd; } pgd_t;
 
 typedef struct { unsigned long pgprot; } pgprot_t;
 
+extern unsigned long phys_base;
+
 #define pte_val(x)     ((x).pte)
 #define pmd_val(x)     ((x).pmd)
 #define pud_val(x)     ((x).pud)
@@ -76,29 +75,25 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
-#define __PHYSICAL_START       ((unsigned long)CONFIG_PHYSICAL_START)
-#define __START_KERNEL         (__START_KERNEL_map + __PHYSICAL_START)
-#define __START_KERNEL_map     0xffffffff80000000UL
-#define __PAGE_OFFSET           0xffff810000000000UL
+#endif /* !__ASSEMBLY__ */
 
-#else
 #define __PHYSICAL_START       CONFIG_PHYSICAL_START
+#define __KERNEL_ALIGN         0x200000
 #define __START_KERNEL         (__START_KERNEL_map + __PHYSICAL_START)
 #define __START_KERNEL_map     0xffffffff80000000
 #define __PAGE_OFFSET           0xffff810000000000
-#endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
 /* See Documentation/x86_64/mm.txt for a description of the memory map. */
 #define __PHYSICAL_MASK_SHIFT  46
-#define __PHYSICAL_MASK                ((1UL << __PHYSICAL_MASK_SHIFT) - 1)
+#define __PHYSICAL_MASK                ((_AC(1,UL) << __PHYSICAL_MASK_SHIFT) - 1)
 #define __VIRTUAL_MASK_SHIFT   48
-#define __VIRTUAL_MASK         ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
+#define __VIRTUAL_MASK         ((_AC(1,UL) << __VIRTUAL_MASK_SHIFT) - 1)
 
-#define KERNEL_TEXT_SIZE  (40UL*1024*1024)
-#define KERNEL_TEXT_START 0xffffffff80000000UL 
+#define KERNEL_TEXT_SIZE  (40*1024*1024)
+#define KERNEL_TEXT_START 0xffffffff80000000
 
 #ifndef __ASSEMBLY__
 
@@ -106,21 +101,19 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #endif /* __ASSEMBLY__ */
 
-#define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
+#define PAGE_OFFSET            __PAGE_OFFSET
 
 /* Note: __pa(&symbol_visible_to_c) should be always replaced with __pa_symbol.
-   Otherwise you risk miscompilation. */ 
-#define __pa(x)                        (((unsigned long)(x)>=__START_KERNEL_map)?(unsigned long)(x) - (unsigned long)__START_KERNEL_map:(unsigned long)(x) - PAGE_OFFSET)
+   Otherwise you risk miscompilation. */
+#define __pa(x)                        ((unsigned long)(x) - PAGE_OFFSET)
 /* __pa_symbol should be used for C visible symbols.
    This seems to be the official gcc blessed way to do such arithmetic. */ 
 #define __pa_symbol(x)         \
        ({unsigned long v;  \
          asm("" : "=r" (v) : "0" (x)); \
-         __pa(v); })
+         ((v - __START_KERNEL_map) + phys_base); })
 
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
-#define __boot_va(x)           __va(x)
-#define __boot_pa(x)           __pa(x)
 #ifdef CONFIG_FLATMEM
 #define pfn_valid(pfn)         ((pfn) < end_pfn)
 #endif
index 5ed0ef3..c6fbb67 100644 (file)
 
 #include <asm/pda.h>
 
-#ifdef CONFIG_MODULES
-# define PERCPU_MODULE_RESERVE 8192
-#else
-# define PERCPU_MODULE_RESERVE 0
-#endif
-
-#define PERCPU_ENOUGH_ROOM \
-       (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
-        PERCPU_MODULE_RESERVE)
-
 #define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset)
 #define __my_cpu_offset() read_pda(data_offset)
 
index 4e28b60..8bb5646 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _X86_64_PGALLOC_H
 #define _X86_64_PGALLOC_H
 
-#include <asm/fixmap.h>
 #include <asm/pda.h>
 #include <linux/threads.h>
 #include <linux/mm.h>
@@ -45,24 +44,16 @@ static inline void pgd_list_add(pgd_t *pgd)
        struct page *page = virt_to_page(pgd);
 
        spin_lock(&pgd_lock);
-       page->index = (pgoff_t)pgd_list;
-       if (pgd_list)
-               pgd_list->private = (unsigned long)&page->index;
-       pgd_list = page;
-       page->private = (unsigned long)&pgd_list;
+       list_add(&page->lru, &pgd_list);
        spin_unlock(&pgd_lock);
 }
 
 static inline void pgd_list_del(pgd_t *pgd)
 {
-       struct page *next, **pprev, *page = virt_to_page(pgd);
+       struct page *page = virt_to_page(pgd);
 
        spin_lock(&pgd_lock);
-       next = (struct page *)page->index;
-       pprev = (struct page **)page->private;
-       *pprev = next;
-       if (next)
-               next->private = (unsigned long)pprev;
+       list_del(&page->lru);
        spin_unlock(&pgd_lock);
 }
 
index 730bd60..599993f 100644 (file)
@@ -1,25 +1,25 @@
 #ifndef _X86_64_PGTABLE_H
 #define _X86_64_PGTABLE_H
 
+#include <asm/const.h>
+#ifndef __ASSEMBLY__
+
 /*
  * This file contains the functions and defines necessary to modify and use
  * the x86-64 page table tree.
  */
 #include <asm/processor.h>
-#include <asm/fixmap.h>
 #include <asm/bitops.h>
 #include <linux/threads.h>
 #include <asm/pda.h>
 
 extern pud_t level3_kernel_pgt[512];
-extern pud_t level3_physmem_pgt[512];
 extern pud_t level3_ident_pgt[512];
 extern pmd_t level2_kernel_pgt[512];
 extern pgd_t init_level4_pgt[];
-extern pgd_t boot_level4_pgt[];
 extern unsigned long __supported_pte_mask;
 
-#define swapper_pg_dir init_level4_pgt
+#define swapper_pg_dir ((pgd_t *)NULL)
 
 extern void paging_init(void);
 extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
@@ -29,7 +29,9 @@ extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
  * for zero-mapped memory areas etc..
  */
 extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+#define ZERO_PAGE(vaddr) (pfn_to_page(__pa_symbol(&empty_zero_page) >> PAGE_SHIFT))
+
+#endif /* !__ASSEMBLY__ */
 
 /*
  * PGDIR_SHIFT determines what a top-level page table entry can map
@@ -55,6 +57,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
  */
 #define PTRS_PER_PTE   512
 
+#ifndef __ASSEMBLY__
+
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %p(%016lx).\n", __FILE__, __LINE__, &(e), pte_val(e))
 #define pmd_ERROR(e) \
@@ -118,22 +122,23 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 
 #define pte_pgprot(a)  (__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
 
-#define PMD_SIZE       (1UL << PMD_SHIFT)
+#endif /* !__ASSEMBLY__ */
+
+#define PMD_SIZE       (_AC(1,UL) << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
-#define PUD_SIZE       (1UL << PUD_SHIFT)
+#define PUD_SIZE       (_AC(1,UL) << PUD_SHIFT)
 #define PUD_MASK       (~(PUD_SIZE-1))
-#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_SIZE     (_AC(1,UL) << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
 #define USER_PTRS_PER_PGD      ((TASK_SIZE-1)/PGDIR_SIZE+1)
 #define FIRST_USER_ADDRESS     0
 
-#ifndef __ASSEMBLY__
-#define MAXMEM          0x3fffffffffffUL
-#define VMALLOC_START    0xffffc20000000000UL
-#define VMALLOC_END      0xffffe1ffffffffffUL
-#define MODULES_VADDR    0xffffffff88000000UL
-#define MODULES_END      0xfffffffffff00000UL
+#define MAXMEM          0x3fffffffffff
+#define VMALLOC_START    0xffffc20000000000
+#define VMALLOC_END      0xffffe1ffffffffff
+#define MODULES_VADDR    0xffffffff88000000
+#define MODULES_END      0xfffffffffff00000
 #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
 
 #define _PAGE_BIT_PRESENT      0
@@ -159,7 +164,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 #define _PAGE_GLOBAL   0x100   /* Global TLB entry */
 
 #define _PAGE_PROTNONE 0x080   /* If not present */
-#define _PAGE_NX        (1UL<<_PAGE_BIT_NX)
+#define _PAGE_NX        (_AC(1,UL)<<_PAGE_BIT_NX)
 
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE  (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
@@ -221,6 +226,8 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 #define __S110 PAGE_SHARED_EXEC
 #define __S111 PAGE_SHARED_EXEC
 
+#ifndef __ASSEMBLY__
+
 static inline unsigned long pgd_bad(pgd_t pgd)
 {
        return pgd_val(pgd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
@@ -403,11 +410,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define __swp_entry_to_pte(x)          ((pte_t) { (x).val })
 
 extern spinlock_t pgd_lock;
-extern struct page *pgd_list;
+extern struct list_head pgd_list;
 void vmalloc_sync_all(void);
 
-#endif /* !__ASSEMBLY__ */
-
 extern int kern_addr_valid(unsigned long addr); 
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
@@ -437,5 +442,6 @@ extern int kern_addr_valid(unsigned long addr);
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
+#endif /* !__ASSEMBLY__ */
 
 #endif /* _X86_64_PGTABLE_H */
diff --git a/include/asm-x86_64/processor-flags.h b/include/asm-x86_64/processor-flags.h
new file mode 100644 (file)
index 0000000..ec99a57
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-i386/processor-flags.h>
index 76552d7..461ffe4 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/percpu.h>
 #include <linux/personality.h>
 #include <linux/cpumask.h>
+#include <asm/processor-flags.h>
 
 #define TF_MASK                0x00000100
 #define IF_MASK                0x00000200
@@ -102,42 +103,6 @@ extern void print_cpu_info(struct cpuinfo_x86 *);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
 
-/*
- * EFLAGS bits
- */
-#define X86_EFLAGS_CF  0x00000001 /* Carry Flag */
-#define X86_EFLAGS_PF  0x00000004 /* Parity Flag */
-#define X86_EFLAGS_AF  0x00000010 /* Auxillary carry Flag */
-#define X86_EFLAGS_ZF  0x00000040 /* Zero Flag */
-#define X86_EFLAGS_SF  0x00000080 /* Sign Flag */
-#define X86_EFLAGS_TF  0x00000100 /* Trap Flag */
-#define X86_EFLAGS_IF  0x00000200 /* Interrupt Flag */
-#define X86_EFLAGS_DF  0x00000400 /* Direction Flag */
-#define X86_EFLAGS_OF  0x00000800 /* Overflow Flag */
-#define X86_EFLAGS_IOPL        0x00003000 /* IOPL mask */
-#define X86_EFLAGS_NT  0x00004000 /* Nested Task */
-#define X86_EFLAGS_RF  0x00010000 /* Resume Flag */
-#define X86_EFLAGS_VM  0x00020000 /* Virtual Mode */
-#define X86_EFLAGS_AC  0x00040000 /* Alignment Check */
-#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
-#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
-#define X86_EFLAGS_ID  0x00200000 /* CPUID detection flag */
-
-/*
- * Intel CPU features in CR4
- */
-#define X86_CR4_VME            0x0001  /* enable vm86 extensions */
-#define X86_CR4_PVI            0x0002  /* virtual interrupts flag enable */
-#define X86_CR4_TSD            0x0004  /* disable time stamp at ipl 3 */
-#define X86_CR4_DE             0x0008  /* enable debugging extensions */
-#define X86_CR4_PSE            0x0010  /* enable page size extensions */
-#define X86_CR4_PAE            0x0020  /* enable physical address extensions */
-#define X86_CR4_MCE            0x0040  /* Machine check enable */
-#define X86_CR4_PGE            0x0080  /* enable global pages */
-#define X86_CR4_PCE            0x0100  /* enable performance counters at ipl 3 */
-#define X86_CR4_OSFXSR         0x0200  /* enable fast FPU save and restore */
-#define X86_CR4_OSXMMEXCPT     0x0400  /* enable unmasked SSE exceptions */
-
 /*
  * Save the cr4 feature set we're using (ie
  * Pentium 4MB enable and PPro Global page
@@ -201,7 +166,7 @@ struct i387_fxsave_struct {
        u32     mxcsr;
        u32     mxcsr_mask;
        u32     st_space[32];   /* 8*16 bytes for each FP-reg = 128 bytes */
-       u32     xmm_space[64];  /* 16*16 bytes for each XMM-reg = 128 bytes */
+       u32     xmm_space[64];  /* 16*16 bytes for each XMM-reg = 256 bytes */
        u32     padding[24];
 } __attribute__ ((aligned (16)));
 
@@ -426,22 +391,6 @@ static inline void prefetchw(void *x)
 
 #define cpu_relax()   rep_nop()
 
-/*
- *      NSC/Cyrix CPU configuration register indexes
- */
-#define CX86_CCR0 0xc0
-#define CX86_CCR1 0xc1
-#define CX86_CCR2 0xc2
-#define CX86_CCR3 0xc3
-#define CX86_CCR4 0xe8
-#define CX86_CCR5 0xe9
-#define CX86_CCR6 0xea
-#define CX86_CCR7 0xeb
-#define CX86_DIR0 0xfe
-#define CX86_DIR1 0xff
-#define CX86_ARR_BASE 0xc4
-#define CX86_RCR_BASE 0xdc
-
 /*
  *      NSC/Cyrix CPU indexed register access macros
  */
index b6e65a6..85255db 100644 (file)
@@ -11,18 +11,9 @@ struct pt_regs;
 extern void start_kernel(void);
 extern void pda_init(int); 
 
-extern void zap_low_mappings(int cpu);
-
 extern void early_idt_handler(void);
 
 extern void mcheck_init(struct cpuinfo_x86 *c);
-#ifdef CONFIG_MTRR
-extern void mtrr_ap_init(void);
-extern void mtrr_bp_init(void);
-#else
-#define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
-#endif
 extern void init_memory_mapping(unsigned long start, unsigned long end);
 
 extern void system_call(void); 
@@ -82,7 +73,6 @@ extern void syscall32_cpu_init(void);
 extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end);
 
 extern void early_quirks(void);
-extern void quirk_intel_irqbalance(void);
 extern void check_efer(void);
 
 extern int unhandled_signal(struct task_struct *tsk, int sig);
@@ -93,6 +83,7 @@ extern unsigned long table_start, table_end;
 
 extern int exception_trace;
 extern unsigned cpu_khz;
+extern unsigned tsc_khz;
 
 extern void no_iommu_init(void);
 extern int force_iommu, no_iommu;
@@ -121,8 +112,12 @@ extern int gsi_irq_sharing(int gsi);
 
 extern void smp_local_timer_interrupt(void);
 
+extern int force_mwait;
+
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
+void i8254_timer_resume(void);
+
 #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
 #define round_down(x,y) ((x) & ~((y)-1))
 
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 334ddcd..adf2bf1 100644 (file)
@@ -6,7 +6,7 @@
 #define __KERNEL_CS    0x10
 #define __KERNEL_DS    0x18
 
-#define __KERNEL32_CS   0x38
+#define __KERNEL32_CS   0x08
 
 /* 
  * we cannot use the same code segment descriptor for user and kernel
index de592a4..d570442 100644 (file)
 #include <linux/init.h>
 extern int disable_apic;
 
-#include <asm/fixmap.h>
 #include <asm/mpspec.h>
-#include <asm/io_apic.h>
 #include <asm/apic.h>
+#include <asm/io_apic.h>
 #include <asm/thread_info.h>
 
 #ifdef CONFIG_SMP
@@ -38,7 +37,6 @@ extern void lock_ipi_call_lock(void);
 extern void unlock_ipi_call_lock(void);
 extern int smp_num_siblings;
 extern void smp_send_reschedule(int cpu);
-void smp_stop_cpu(void);
 
 extern cpumask_t cpu_sibling_map[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
index bc7f817..9c3f8de 100644 (file)
@@ -17,6 +17,7 @@ struct saved_context {
        u16 ds, es, fs, gs, ss;
        unsigned long gs_base, gs_kernel_base, fs_base;
        unsigned long cr0, cr2, cr3, cr4, cr8;
+       unsigned long efer;
        u16 gdt_pad;
        u16 gdt_limit;
        unsigned long gdt_base;
@@ -44,12 +45,12 @@ extern unsigned long saved_context_eflags;
 extern void fix_processor_context(void);
 
 #ifdef CONFIG_ACPI_SLEEP
-extern unsigned long saved_eip;
-extern unsigned long saved_esp;
-extern unsigned long saved_ebp;
-extern unsigned long saved_ebx;
-extern unsigned long saved_esi;
-extern unsigned long saved_edi;
+extern unsigned long saved_rip;
+extern unsigned long saved_rsp;
+extern unsigned long saved_rbp;
+extern unsigned long saved_rbx;
+extern unsigned long saved_rsi;
+extern unsigned long saved_rdi;
 
 /* routines for saving/restoring kernel state */
 extern int acpi_save_state_mem(void);
index bd376bc..213b7fe 100644 (file)
@@ -89,6 +89,11 @@ static inline unsigned long read_cr3(void)
        return cr3;
 } 
 
+static inline void write_cr3(unsigned long val)
+{
+       asm volatile("movq %0,%%cr3" :: "r" (val) : "memory");
+}
+
 static inline unsigned long read_cr4(void)
 { 
        unsigned long cr4;
@@ -98,7 +103,7 @@ static inline unsigned long read_cr4(void)
 
 static inline void write_cr4(unsigned long val)
 { 
-       asm volatile("movq %0,%%cr4" :: "r" (val));
+       asm volatile("movq %0,%%cr4" :: "r" (val) : "memory");
 } 
 
 #define stts() write_cr0(8 | read_cr0())
index 8c6808a..f6527e1 100644 (file)
@@ -27,6 +27,6 @@ extern int read_current_timer(unsigned long *timer_value);
 #define NS_SCALE        10 /* 2^10, carefully chosen */
 #define US_SCALE        32 /* 2^32, arbitralrily chosen */
 
-extern void mark_tsc_unstable(void);
+extern void mark_tsc_unstable(char *msg);
 extern void set_cyc2ns_scale(unsigned long khz);
 #endif
index 983bd29..512401b 100644 (file)
@@ -3,41 +3,18 @@
 
 #include <linux/mm.h>
 #include <asm/processor.h>
-
-static inline unsigned long get_cr3(void)
-{
-       unsigned long cr3;
-       asm volatile("mov %%cr3,%0" : "=r" (cr3));
-       return cr3;
-}
-
-static inline void set_cr3(unsigned long cr3)
-{
-       asm volatile("mov %0,%%cr3" :: "r" (cr3) : "memory");
-}
+#include <asm/system.h>
 
 static inline void __flush_tlb(void)
 {
-       set_cr3(get_cr3());
-}
-
-static inline unsigned long get_cr4(void)
-{
-       unsigned long cr4;
-       asm volatile("mov %%cr4,%0" : "=r" (cr4));
-       return cr4;
-}
-
-static inline void set_cr4(unsigned long cr4)
-{
-       asm volatile("mov %0,%%cr4" :: "r" (cr4) : "memory");
+       write_cr3(read_cr3());
 }
 
 static inline void __flush_tlb_all(void)
 {
-       unsigned long cr4 = get_cr4();
-       set_cr4(cr4 & ~X86_CR4_PGE);    /* clear PGE */
-       set_cr4(cr4);                   /* write old PGE again and flush TLBs */
+       unsigned long cr4 = read_cr4();
+       write_cr4(cr4 & ~X86_CR4_PGE);  /* clear PGE */
+       write_cr4(cr4);                 /* write old PGE again and flush TLBs */
 }
 
 #define __flush_tlb_one(addr) \
index c5f596e..26e23e0 100644 (file)
@@ -620,8 +620,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice)
 #define __NR_move_pages                279
 __SYSCALL(__NR_move_pages, sys_move_pages)
 
-#define __NR_syscall_max __NR_move_pages
-
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -655,7 +653,6 @@ __SYSCALL(__NR_move_pages, sys_move_pages)
 #include <asm/ptrace.h>
 
 asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
-asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
                                const struct sigaction __user *act,
index f14851f..92f9483 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <asm-generic/mm_hooks.h>
 
 #define XCHAL_MMU_ASID_BITS    8
 
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 4ff0f57..9f05279 100644 (file)
@@ -96,6 +96,7 @@ header-y += iso_fs.h
 header-y += ixjuser.h
 header-y += jffs2.h
 header-y += keyctl.h
+header-y += kvm.h
 header-y += limits.h
 header-y += lock_dlm_plock.h
 header-y += magic.h
index 81c07cd..0365ec9 100644 (file)
@@ -122,9 +122,9 @@ extern void *alloc_large_system_hash(const char *tablename,
 #define HASH_EARLY     0x00000001      /* Allocating during early boot? */
 
 /* Only NUMA needs hash distribution.
- * IA64 is known to have sufficient vmalloc space.
+ * IA64 and x86_64 have sufficient vmalloc space.
  */
-#if defined(CONFIG_NUMA) && defined(CONFIG_IA64)
+#if defined(CONFIG_NUMA) && (defined(CONFIG_IA64) || defined(CONFIG_X86_64))
 #define HASHDIST_DEFAULT 1
 #else
 #define HASHDIST_DEFAULT 0
index 0899e2c..963051a 100644 (file)
  *                     CPUFREQ NOTIFIER INTERFACE                    *
  *********************************************************************/
 
+#ifdef CONFIG_CPU_FREQ
 int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
+#else
+static inline int cpufreq_register_notifier(struct notifier_block *nb,
+                                               unsigned int list)
+{
+       return 0;
+}
+#endif
 int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
 
 #define CPUFREQ_TRANSITION_NOTIFIER    (0)
@@ -257,21 +265,25 @@ 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);
 
-/* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
-unsigned int cpufreq_get(unsigned int cpu);
 
-/* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
+/*
+ * query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it
+ */
 #ifdef CONFIG_CPU_FREQ
 unsigned int cpufreq_quick_get(unsigned int cpu);
+unsigned int cpufreq_get(unsigned int cpu);
 #else
 static inline unsigned int cpufreq_quick_get(unsigned int cpu)
 {
        return 0;
 }
+static inline unsigned int cpufreq_get(unsigned int cpu)
+{
+       return 0;
+}
 #endif
 
 
index 3250365..22c7ac5 100644 (file)
@@ -14,5 +14,13 @@ extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
 extern const struct file_operations proc_vmcore_operations;
 extern struct proc_dir_entry *proc_vmcore;
 
+/* Architecture code defines this if there are other possible ELF
+ * machine types, e.g. on bi-arch capable hardware. */
+#ifndef vmcore_elf_check_arch_cross
+#define vmcore_elf_check_arch_cross(x) 0
+#endif
+
+#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+
 #endif /* CONFIG_CRASH_DUMP */
 #endif /* LINUX_CRASHDUMP_H */
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 60713e6..8b17ffe 100644 (file)
@@ -83,6 +83,23 @@ typedef __s64        Elf64_Sxword;
 #define DT_DEBUG       21
 #define DT_TEXTREL     22
 #define DT_JMPREL      23
+#define DT_ENCODING    32
+#define OLD_DT_LOOS    0x60000000
+#define DT_LOOS                0x6000000d
+#define DT_HIOS                0x6ffff000
+#define DT_VALRNGLO    0x6ffffd00
+#define DT_VALRNGHI    0x6ffffdff
+#define DT_ADDRRNGLO   0x6ffffe00
+#define DT_ADDRRNGHI   0x6ffffeff
+#define DT_VERSYM      0x6ffffff0
+#define DT_RELACOUNT   0x6ffffff9
+#define DT_RELCOUNT    0x6ffffffa
+#define DT_FLAGS_1     0x6ffffffb
+#define DT_VERDEF      0x6ffffffc
+#define        DT_VERDEFNUM    0x6ffffffd
+#define DT_VERNEED     0x6ffffffe
+#define        DT_VERNEEDNUM   0x6fffffff
+#define OLD_DT_HIOS     0x6fffffff
 #define DT_LOPROC      0x70000000
 #define DT_HIPROC      0x7fffffff
 
index 67396db..9a1e067 100644 (file)
  *      ELFNOTE(XYZCo, 12, .long, 0xdeadbeef)
  */
 #define ELFNOTE(name, type, desctype, descdata)        \
-.pushsection .note.name                        ;       \
+.pushsection .note.name, "",@note      ;       \
   .align 4                             ;       \
   .long 2f - 1f                /* namesz */    ;       \
   .long 4f - 3f                /* descsz */    ;       \
   .long type                           ;       \
-1:.asciz "name"                                ;       \
+1:.asciz #name                         ;       \
 2:.align 4                             ;       \
 3:desctype descdata                    ;       \
 4:.align 4                             ;       \
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 645d440..a515eb0 100644 (file)
@@ -27,6 +27,8 @@ static inline void flush_kernel_dcache_page(struct page *page)
 unsigned int nr_free_highpages(void);
 extern unsigned long totalhigh_pages;
 
+void kmap_flush_unused(void);
+
 #else /* CONFIG_HIGHMEM */
 
 static inline unsigned int nr_free_highpages(void) { return 0; }
@@ -42,11 +44,20 @@ 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)
 #define kmap_atomic_pfn(pfn, idx)      kmap_atomic(pfn_to_page(pfn), (idx))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
+
+#define kmap_flush_unused()    do {} while(0)
 #endif
 
 #endif /* CONFIG_HIGHMEM */
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 */
index e290a01..9abf120 100644 (file)
 #endif
 
 /* For assembly routines */
+#ifdef CONFIG_HOTPLUG_CPU
+#define __INIT         .section        ".text","ax"
+#define __INITDATA     .section        ".data","aw"
+#else
 #define __INIT         .section        ".init.text","ax"
-#define __FINIT                .previous
 #define __INITDATA     .section        ".init.data","aw"
+#endif
+#define __FINIT                .previous
 
 #ifndef __ASSEMBLY__
 /*
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 13d510c..be2bf3a 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;
@@ -1078,7 +1058,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);
 
@@ -1108,7 +1088,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)
 
@@ -1125,12 +1105,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 *);
 
@@ -1172,6 +1165,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 275354f..e6edca8 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/types.h>
 #include <linux/ioctl.h>
 
-#define KVM_API_VERSION 4
+#define KVM_API_VERSION 12
 
 /*
  * Architectural interrupt line count, and the size of the bitmap needed
@@ -33,37 +33,39 @@ struct kvm_memory_region {
 /* for kvm_memory_region::flags */
 #define KVM_MEM_LOG_DIRTY_PAGES  1UL
 
-
-#define KVM_EXIT_TYPE_FAIL_ENTRY 1
-#define KVM_EXIT_TYPE_VM_EXIT    2
+struct kvm_memory_alias {
+       __u32 slot;  /* this has a different namespace than memory slots */
+       __u32 flags;
+       __u64 guest_phys_addr;
+       __u64 memory_size;
+       __u64 target_phys_addr;
+};
 
 enum kvm_exit_reason {
        KVM_EXIT_UNKNOWN          = 0,
        KVM_EXIT_EXCEPTION        = 1,
        KVM_EXIT_IO               = 2,
-       KVM_EXIT_CPUID            = 3,
+       KVM_EXIT_HYPERCALL        = 3,
        KVM_EXIT_DEBUG            = 4,
        KVM_EXIT_HLT              = 5,
        KVM_EXIT_MMIO             = 6,
        KVM_EXIT_IRQ_WINDOW_OPEN  = 7,
        KVM_EXIT_SHUTDOWN         = 8,
+       KVM_EXIT_FAIL_ENTRY       = 9,
+       KVM_EXIT_INTR             = 10,
 };
 
-/* for KVM_RUN */
+/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
        /* in */
-       __u32 emulated;  /* skip current instruction */
-       __u32 mmio_completed; /* mmio request completed */
        __u8 request_interrupt_window;
        __u8 padding1[7];
 
        /* out */
-       __u32 exit_type;
        __u32 exit_reason;
-       __u32 instruction_length;
        __u8 ready_for_interrupt_injection;
        __u8 if_flag;
-       __u16 padding2;
+       __u8 padding2[2];
 
        /* in (pre_kvm_run), out (post_kvm_run) */
        __u64 cr8;
@@ -72,29 +74,26 @@ struct kvm_run {
        union {
                /* KVM_EXIT_UNKNOWN */
                struct {
-                       __u32 hardware_exit_reason;
+                       __u64 hardware_exit_reason;
                } hw;
+               /* KVM_EXIT_FAIL_ENTRY */
+               struct {
+                       __u64 hardware_entry_failure_reason;
+               } fail_entry;
                /* KVM_EXIT_EXCEPTION */
                struct {
                        __u32 exception;
                        __u32 error_code;
                } ex;
                /* KVM_EXIT_IO */
-               struct {
+               struct kvm_io {
 #define KVM_EXIT_IO_IN  0
 #define KVM_EXIT_IO_OUT 1
                        __u8 direction;
                        __u8 size; /* bytes */
-                       __u8 string;
-                       __u8 string_down;
-                       __u8 rep;
-                       __u8 pad;
                        __u16 port;
-                       __u64 count;
-                       union {
-                               __u64 address;
-                               __u32 value;
-                       };
+                       __u32 count;
+                       __u64 data_offset; /* relative to kvm_run start */
                } io;
                struct {
                } debug;
@@ -105,6 +104,13 @@ struct kvm_run {
                        __u32 len;
                        __u8  is_write;
                } mmio;
+               /* KVM_EXIT_HYPERCALL */
+               struct {
+                       __u64 args[6];
+                       __u64 ret;
+                       __u32 longmode;
+                       __u32 pad;
+               } hypercall;
        };
 };
 
@@ -118,6 +124,21 @@ struct kvm_regs {
        __u64 rip, rflags;
 };
 
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u8  fpr[8][16];
+       __u16 fcw;
+       __u16 fsw;
+       __u8  ftwx;  /* in fxsave format */
+       __u8  pad1;
+       __u16 last_opcode;
+       __u64 last_ip;
+       __u64 last_dp;
+       __u8  xmm[16][16];
+       __u32 mxcsr;
+       __u32 pad2;
+};
+
 struct kvm_segment {
        __u64 base;
        __u32 limit;
@@ -210,38 +231,74 @@ struct kvm_dirty_log {
        };
 };
 
+struct kvm_cpuid_entry {
+       __u32 function;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding;
+};
+
+/* for KVM_SET_CPUID */
+struct kvm_cpuid {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry entries[0];
+};
+
+/* for KVM_SET_SIGNAL_MASK */
+struct kvm_signal_mask {
+       __u32 len;
+       __u8  sigset[0];
+};
+
 #define KVMIO 0xAE
 
 /*
  * ioctls for /dev/kvm fds:
  */
-#define KVM_GET_API_VERSION       _IO(KVMIO, 1)
-#define KVM_CREATE_VM             _IO(KVMIO, 2) /* returns a VM fd */
-#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 15, struct kvm_msr_list)
+#define KVM_GET_API_VERSION       _IO(KVMIO,   0x00)
+#define KVM_CREATE_VM             _IO(KVMIO,   0x01) /* returns a VM fd */
+#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 0x02, struct kvm_msr_list)
+/*
+ * Check if a kvm extension is available.  Argument is extension number,
+ * return is 1 (yes) or 0 (no, sorry).
+ */
+#define KVM_CHECK_EXTENSION       _IO(KVMIO,   0x03)
+/*
+ * Get size for mmap(vcpu_fd)
+ */
+#define KVM_GET_VCPU_MMAP_SIZE    _IO(KVMIO,   0x04) /* in bytes */
 
 /*
  * ioctls for VM fds
  */
-#define KVM_SET_MEMORY_REGION     _IOW(KVMIO, 10, struct kvm_memory_region)
+#define KVM_SET_MEMORY_REGION     _IOW(KVMIO, 0x40, struct kvm_memory_region)
 /*
  * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
  * a vcpu fd.
  */
-#define KVM_CREATE_VCPU           _IOW(KVMIO, 11, int)
-#define KVM_GET_DIRTY_LOG         _IOW(KVMIO, 12, struct kvm_dirty_log)
+#define KVM_CREATE_VCPU           _IO(KVMIO,  0x41)
+#define KVM_GET_DIRTY_LOG         _IOW(KVMIO, 0x42, struct kvm_dirty_log)
+#define KVM_SET_MEMORY_ALIAS      _IOW(KVMIO, 0x43, struct kvm_memory_alias)
 
 /*
  * ioctls for vcpu fds
  */
-#define KVM_RUN                   _IOWR(KVMIO, 2, struct kvm_run)
-#define KVM_GET_REGS              _IOR(KVMIO, 3, struct kvm_regs)
-#define KVM_SET_REGS              _IOW(KVMIO, 4, struct kvm_regs)
-#define KVM_GET_SREGS             _IOR(KVMIO, 5, struct kvm_sregs)
-#define KVM_SET_SREGS             _IOW(KVMIO, 6, struct kvm_sregs)
-#define KVM_TRANSLATE             _IOWR(KVMIO, 7, struct kvm_translation)
-#define KVM_INTERRUPT             _IOW(KVMIO, 8, struct kvm_interrupt)
-#define KVM_DEBUG_GUEST           _IOW(KVMIO, 9, struct kvm_debug_guest)
-#define KVM_GET_MSRS              _IOWR(KVMIO, 13, struct kvm_msrs)
-#define KVM_SET_MSRS              _IOW(KVMIO, 14, struct kvm_msrs)
+#define KVM_RUN                   _IO(KVMIO,   0x80)
+#define KVM_GET_REGS              _IOR(KVMIO,  0x81, struct kvm_regs)
+#define KVM_SET_REGS              _IOW(KVMIO,  0x82, struct kvm_regs)
+#define KVM_GET_SREGS             _IOR(KVMIO,  0x83, struct kvm_sregs)
+#define KVM_SET_SREGS             _IOW(KVMIO,  0x84, struct kvm_sregs)
+#define KVM_TRANSLATE             _IOWR(KVMIO, 0x85, struct kvm_translation)
+#define KVM_INTERRUPT             _IOW(KVMIO,  0x86, struct kvm_interrupt)
+#define KVM_DEBUG_GUEST           _IOW(KVMIO,  0x87, struct kvm_debug_guest)
+#define KVM_GET_MSRS              _IOWR(KVMIO, 0x88, struct kvm_msrs)
+#define KVM_SET_MSRS              _IOW(KVMIO,  0x89, struct kvm_msrs)
+#define KVM_SET_CPUID             _IOW(KVMIO,  0x8a, struct kvm_cpuid)
+#define KVM_SET_SIGNAL_MASK       _IOW(KVMIO,  0x8b, struct kvm_signal_mask)
+#define KVM_GET_FPU               _IOR(KVMIO,  0x8c, struct kvm_fpu)
+#define KVM_SET_FPU               _IOW(KVMIO,  0x8d, struct kvm_fpu)
 
 #endif
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 326da7d..dff9ea3 100644 (file)
@@ -29,6 +29,7 @@
 
 #define TUN_MINOR           200
 #define        HPET_MINOR           228
+#define KVM_MINOR            232
 
 struct device;
 
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 600e3d3..b72be2f 100644 (file)
 
 /* Enough to cover all DEFINE_PER_CPUs in kernel, including modules. */
 #ifndef PERCPU_ENOUGH_ROOM
-#define PERCPU_ENOUGH_ROOM 32768
+#ifdef CONFIG_MODULES
+#define PERCPU_MODULE_RESERVE  8192
+#else
+#define PERCPU_MODULE_RESERVE  0
 #endif
 
+#define PERCPU_ENOUGH_ROOM                                             \
+       (__per_cpu_end - __per_cpu_start + PERCPU_MODULE_RESERVE)
+#endif /* PERCPU_ENOUGH_ROOM */
+
 /*
  * Must be an lvalue. Since @var must be a simple identifier,
  * we force a syntax error here if it isn't.
index 3e628f9..89580b7 100644 (file)
@@ -26,9 +26,6 @@
 /********** arch/$ARCH/mm/init.c **********/
 #define POISON_FREE_INITMEM    0xcc
 
-/********** arch/x86_64/mm/init.c **********/
-#define        POISON_FREE_INITDATA    0xba
-
 /********** arch/ia64/hp/common/sba_iommu.c **********/
 /*
  * arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a
diff --git a/include/linux/reboot_fixups.h b/include/linux/reboot_fixups.h
deleted file mode 100644 (file)
index 480ea2d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _LINUX_REBOOT_FIXUPS_H
-#define _LINUX_REBOOT_FIXUPS_H
-
-#ifdef CONFIG_X86_REBOOTFIXUPS
-extern void mach_reboot_fixups(void);
-#else
-#define mach_reboot_fixups() ((void)(0))
-#endif
-
-#endif /* _LINUX_REBOOT_FIXUPS_H */
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);
@@ -334,6 +325,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
         */
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 7a92b4c..df982ff 100644 (file)
@@ -369,12 +369,8 @@ static void __init setup_per_cpu_areas(void)
        unsigned long nr_possible_cpus = num_possible_cpus();
 
        /* Copy section for each CPU (we discard the original) */
-       size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
-#ifdef CONFIG_MODULES
-       if (size < PERCPU_ENOUGH_ROOM)
-               size = PERCPU_ENOUGH_ROOM;
-#endif
-       ptr = alloc_bootmem(size * nr_possible_cpus);
+       size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
+       ptr = alloc_bootmem_pages(size * nr_possible_cpus);
 
        for_each_possible_cpu(i) {
                __per_cpu_offset[i] = ptr - __per_cpu_start;
index 6af959c..ffccefb 100644 (file)
@@ -286,6 +286,8 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                if (retval)
                        goto out;
        }
+       /* a new mm has just been created */
+       arch_dup_mmap(oldmm, mm);
        retval = 0;
 out:
        up_write(&mm->mmap_sem);
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 9da5af6..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
@@ -346,10 +348,10 @@ static void *percpu_modalloc(unsigned long size, unsigned long align,
        unsigned int i;
        void *ptr;
 
-       if (align > SMP_CACHE_BYTES) {
-               printk(KERN_WARNING "%s: per-cpu alignment %li > %i\n",
-                      name, align, SMP_CACHE_BYTES);
-               align = SMP_CACHE_BYTES;
+       if (align > PAGE_SIZE) {
+               printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
+                      name, align, PAGE_SIZE);
+               align = PAGE_SIZE;
        }
 
        ptr = __per_cpu_start;
@@ -430,7 +432,7 @@ static int percpu_modinit(void)
        pcpu_size = kmalloc(sizeof(pcpu_size[0]) * pcpu_num_allocated,
                            GFP_KERNEL);
        /* Static in-kernel percpu data (used). */
-       pcpu_size[0] = -ALIGN(__per_cpu_end-__per_cpu_start, SMP_CACHE_BYTES);
+       pcpu_size[0] = -(__per_cpu_end-__per_cpu_start);
        /* Free room. */
        pcpu_size[1] = PERCPU_ENOUGH_ROOM + pcpu_size[0];
        if (pcpu_size[1] < 0) {
@@ -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 eb461b8..33bd94c 100644 (file)
@@ -23,6 +23,8 @@ static inline int pm_suspend_disk(void)
 }
 #endif
 
+extern int pfn_is_nosave(unsigned long);
+
 extern struct mutex pm_mutex;
 
 #define power_attr(_name) \
@@ -35,10 +37,7 @@ static struct subsys_attribute _name##_attr = {      \
        .store  = _name##_store,                \
 }
 
-extern struct subsystem power_subsys;
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
+extern struct kset power_subsys;
 
 /* Preferred image size in bytes (default 500 MB) */
 extern unsigned long image_size;
index fc53ad0..704c25a 100644 (file)
@@ -650,17 +650,6 @@ static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; }
 static inline unsigned int count_highmem_pages(void) { return 0; }
 #endif /* CONFIG_HIGHMEM */
 
-/**
- *     pfn_is_nosave - check if given pfn is in the 'nosave' section
- */
-
-static inline int pfn_is_nosave(unsigned long pfn)
-{
-       unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
-       unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
-       return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
-}
-
 /**
  *     saveable - Determine whether a non-highmem page should be included in
  *     the suspend image.
index 3581f8f..b18c155 100644 (file)
@@ -33,12 +33,14 @@ extern char resume_file[];
 
 #define SWSUSP_SIG     "S1SUSPEND"
 
-static struct swsusp_header {
+struct swsusp_header {
        char reserved[PAGE_SIZE - 20 - sizeof(sector_t)];
        sector_t image;
        char    orig_sig[10];
        char    sig[10];
-} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
+} __attribute__((packed));
+
+static struct swsusp_header *swsusp_header;
 
 /*
  * General things
@@ -141,14 +143,14 @@ static int mark_swapfiles(sector_t start)
 {
        int error;
 
-       bio_read_page(swsusp_resume_block, &swsusp_header, NULL);
-       if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
-           !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
-               memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
-               memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
-               swsusp_header.image = start;
+       bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+       if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
+           !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
+               memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
+               memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
+               swsusp_header->image = start;
                error = bio_write_page(swsusp_resume_block,
-                                       &swsusp_header, NULL);
+                                       swsusp_header, NULL);
        } else {
                printk(KERN_ERR "swsusp: Swap header not found!\n");
                error = -ENODEV;
@@ -564,7 +566,7 @@ int swsusp_read(void)
        if (error < PAGE_SIZE)
                return error < 0 ? error : -EFAULT;
        header = (struct swsusp_info *)data_of(snapshot);
-       error = get_swap_reader(&handle, swsusp_header.image);
+       error = get_swap_reader(&handle, swsusp_header->image);
        if (!error)
                error = swap_read_page(&handle, header, NULL);
        if (!error)
@@ -591,17 +593,17 @@ int swsusp_check(void)
        resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
        if (!IS_ERR(resume_bdev)) {
                set_blocksize(resume_bdev, PAGE_SIZE);
-               memset(&swsusp_header, 0, sizeof(swsusp_header));
+               memset(swsusp_header, 0, sizeof(PAGE_SIZE));
                error = bio_read_page(swsusp_resume_block,
-                                       &swsusp_header, NULL);
+                                       swsusp_header, NULL);
                if (error)
                        return error;
 
-               if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
-                       memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
+               if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
+                       memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
                        /* Reset swap signature now */
                        error = bio_write_page(swsusp_resume_block,
-                                               &swsusp_header, NULL);
+                                               swsusp_header, NULL);
                } else {
                        return -EINVAL;
                }
@@ -632,3 +634,13 @@ void swsusp_close(void)
 
        blkdev_put(resume_bdev);
 }
+
+static int swsusp_header_init(void)
+{
+       swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL);
+       if (!swsusp_header)
+               panic("Could not allocate memory for swsusp_header\n");
+       return 0;
+}
+
+core_initcall(swsusp_header_init);
index 6db6e98..845f91d 100644 (file)
@@ -292,7 +292,6 @@ STATIC int INIT huft_build(
    oversubscribed set of lengths), and three if not enough memory. */
 {
   unsigned a;                   /* counter for codes of length k */
-  unsigned c[BMAX+1];           /* bit length count table */
   unsigned f;                   /* i repeats in table every f entries */
   int g;                        /* maximum code length */
   int h;                        /* table level */
@@ -303,18 +302,33 @@ STATIC int INIT huft_build(
   register unsigned *p;         /* pointer into c[], b[], or v[] */
   register struct huft *q;      /* points to current table */
   struct huft r;                /* table entry for structure assignment */
-  struct huft *u[BMAX];         /* table stack */
-  unsigned v[N_MAX];            /* values in order of bit length */
   register int w;               /* bits before this table == (l * h) */
-  unsigned x[BMAX+1];           /* bit offsets, then code stack */
   unsigned *xp;                 /* pointer into x */
   int y;                        /* number of dummy codes added */
   unsigned z;                   /* number of entries in current table */
+  struct {
+    unsigned c[BMAX+1];           /* bit length count table */
+    struct huft *u[BMAX];         /* table stack */
+    unsigned v[N_MAX];            /* values in order of bit length */
+    unsigned x[BMAX+1];           /* bit offsets, then code stack */
+  } *stk;
+  unsigned *c, *v, *x;
+  struct huft **u;
+  int ret;
 
 DEBG("huft1 ");
 
+  stk = malloc(sizeof(*stk));
+  if (stk == NULL)
+    return 3;                  /* out of memory */
+
+  c = stk->c;
+  v = stk->v;
+  x = stk->x;
+  u = stk->u;
+
   /* Generate counts for each bit length */
-  memzero(c, sizeof(c));
+  memzero(stk->c, sizeof(stk->c));
   p = b;  i = n;
   do {
     Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), 
@@ -326,7 +340,8 @@ DEBG("huft1 ");
   {
     *t = (struct huft *)NULL;
     *m = 0;
-    return 2;
+    ret = 2;
+    goto out;
   }
 
 DEBG("huft2 ");
@@ -351,10 +366,14 @@ DEBG("huft3 ");
 
   /* Adjust last length count to fill out codes, if needed */
   for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return 2;                 /* bad input: more codes than bits */
-  if ((y -= c[i]) < 0)
-    return 2;
+    if ((y -= c[j]) < 0) {
+      ret = 2;                 /* bad input: more codes than bits */
+      goto out;
+    }
+  if ((y -= c[i]) < 0) {
+    ret = 2;
+    goto out;
+  }
   c[i] += y;
 
 DEBG("huft4 ");
@@ -428,7 +447,8 @@ DEBG1("3 ");
         {
           if (h)
             huft_free(u[0]);
-          return 3;             /* not enough memory */
+          ret = 3;             /* not enough memory */
+         goto out;
         }
 DEBG1("4 ");
         hufts += z + 1;         /* track memory usage */
@@ -492,7 +512,11 @@ DEBG("h6f ");
 DEBG("huft7 ");
 
   /* Return true (1) if we were given an incomplete table */
-  return y != 0 && g != 1;
+  ret = y != 0 && g != 1;
+
+  out:
+  free(stk);
+  return ret;
 }
 
 
@@ -705,10 +729,14 @@ STATIC int noinline INIT inflate_fixed(void)
   struct huft *td;      /* distance code table */
   int bl;               /* lookup bits for tl */
   int bd;               /* lookup bits for td */
-  unsigned l[288];      /* length list for huft_build */
+  unsigned *l;          /* length list for huft_build */
 
 DEBG("<fix");
 
+  l = malloc(sizeof(*l) * 288);
+  if (l == NULL)
+    return 3;                  /* out of memory */
+
   /* set up literal table */
   for (i = 0; i < 144; i++)
     l[i] = 8;
@@ -719,9 +747,10 @@ DEBG("<fix");
   for (; i < 288; i++)          /* make a complete, but wrong code set */
     l[i] = 8;
   bl = 7;
-  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) {
+    free(l);
     return i;
-
+  }
 
   /* set up distance table */
   for (i = 0; i < 30; i++)      /* make an incomplete code set */
@@ -730,6 +759,7 @@ DEBG("<fix");
   if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
   {
     huft_free(tl);
+    free(l);
 
     DEBG(">");
     return i;
@@ -737,11 +767,13 @@ DEBG("<fix");
 
 
   /* decompress until an end-of-block code */
-  if (inflate_codes(tl, td, bl, bd))
+  if (inflate_codes(tl, td, bl, bd)) {
+    free(l);
     return 1;
-
+  }
 
   /* free the decoding tables, return */
+  free(l);
   huft_free(tl);
   huft_free(td);
   return 0;
@@ -766,16 +798,19 @@ STATIC int noinline INIT inflate_dynamic(void)
   unsigned nb;          /* number of bit length codes */
   unsigned nl;          /* number of literal/length codes */
   unsigned nd;          /* number of distance codes */
-#ifdef PKZIP_BUG_WORKAROUND
-  unsigned ll[288+32];  /* literal/length and distance code lengths */
-#else
-  unsigned ll[286+30];  /* literal/length and distance code lengths */
-#endif
+  unsigned *ll;         /* literal/length and distance code lengths */
   register ulg b;       /* bit buffer */
   register unsigned k;  /* number of bits in bit buffer */
+  int ret;
 
 DEBG("<dyn");
 
+#ifdef PKZIP_BUG_WORKAROUND
+  ll = malloc(sizeof(*ll) * (288+32));  /* literal/length and distance code lengths */
+#else
+  ll = malloc(sizeof(*ll) * (286+30));  /* literal/length and distance code lengths */
+#endif
+
   /* make local bit buffer */
   b = bb;
   k = bk;
@@ -796,7 +831,10 @@ DEBG("<dyn");
 #else
   if (nl > 286 || nd > 30)
 #endif
-    return 1;                   /* bad lengths */
+  {
+    ret = 1;             /* bad lengths */
+    goto out;
+  }
 
 DEBG("dyn1 ");
 
@@ -818,7 +856,8 @@ DEBG("dyn2 ");
   {
     if (i == 1)
       huft_free(tl);
-    return i;                   /* incomplete code set */
+    ret = i;                   /* incomplete code set */
+    goto out;
   }
 
 DEBG("dyn3 ");
@@ -840,8 +879,10 @@ DEBG("dyn3 ");
       NEEDBITS(2)
       j = 3 + ((unsigned)b & 3);
       DUMPBITS(2)
-      if ((unsigned)i + j > n)
-        return 1;
+      if ((unsigned)i + j > n) {
+        ret = 1;
+       goto out;
+      }
       while (j--)
         ll[i++] = l;
     }
@@ -850,8 +891,10 @@ DEBG("dyn3 ");
       NEEDBITS(3)
       j = 3 + ((unsigned)b & 7);
       DUMPBITS(3)
-      if ((unsigned)i + j > n)
-        return 1;
+      if ((unsigned)i + j > n) {
+        ret = 1;
+       goto out;
+      }
       while (j--)
         ll[i++] = 0;
       l = 0;
@@ -861,8 +904,10 @@ DEBG("dyn3 ");
       NEEDBITS(7)
       j = 11 + ((unsigned)b & 0x7f);
       DUMPBITS(7)
-      if ((unsigned)i + j > n)
-        return 1;
+      if ((unsigned)i + j > n) {
+        ret = 1;
+       goto out;
+      }
       while (j--)
         ll[i++] = 0;
       l = 0;
@@ -891,7 +936,8 @@ DEBG("dyn5b ");
       error("incomplete literal tree");
       huft_free(tl);
     }
-    return i;                   /* incomplete code set */
+    ret = i;                   /* incomplete code set */
+    goto out;
   }
 DEBG("dyn5c ");
   bd = dbits;
@@ -907,15 +953,18 @@ DEBG("dyn5d ");
       huft_free(td);
     }
     huft_free(tl);
-    return i;                   /* incomplete code set */
+    ret = i;                   /* incomplete code set */
+    goto out;
 #endif
   }
 
 DEBG("dyn6 ");
 
   /* decompress until an end-of-block code */
-  if (inflate_codes(tl, td, bl, bd))
-    return 1;
+  if (inflate_codes(tl, td, bl, bd)) {
+    ret = 1;
+    goto out;
+  }
 
 DEBG("dyn7 ");
 
@@ -924,10 +973,14 @@ DEBG("dyn7 ");
   huft_free(td);
 
   DEBG(">");
-  return 0;
-
- underrun:
-  return 4;                    /* Input underrun */
+  ret = 0;
+out:
+  free(ll);
+  return ret;
+
+underrun:
+  ret = 4;                     /* Input underrun */
+  goto out;
 }
 
 
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 51e1c19..be8f8d3 100644 (file)
@@ -99,6 +99,15 @@ static void flush_all_zero_pkmaps(void)
        flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP));
 }
 
+/* Flush all unused kmap mappings in order to remove stray
+   mappings. */
+void kmap_flush_unused(void)
+{
+       spin_lock(&kmap_lock);
+       flush_all_zero_pkmaps();
+       spin_unlock(&kmap_lock);
+}
+
 static inline unsigned long map_new_virtual(struct page *page)
 {
        unsigned long vaddr;
index 84f997d..88da687 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -29,6 +29,7 @@
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
+#include <asm/mmu_context.h>
 
 #ifndef arch_mmap_check
 #define arch_mmap_check(addr, len, flags)      (0)
@@ -1979,6 +1980,9 @@ void exit_mmap(struct mm_struct *mm)
        unsigned long nr_accounted = 0;
        unsigned long end;
 
+       /* mm's last user has gone, and its about to be pulled down */
+       arch_exit_mmap(mm);
+
        lru_add_drain();
        flush_cache_mm(mm);
        tlb = tlb_gather_mmu(mm, 1);
index 4cbac24..168bfe9 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1146,7 +1146,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
         * Make sure we are not freeing a object from another node to the array
         * cache on this cpu.
         */
-       if (likely(slabp->nodeid == node) || unlikely(!use_alien_caches))
+       if (likely(slabp->nodeid == node))
                return 0;
 
        l3 = cachep->nodelists[node];
@@ -1394,6 +1394,9 @@ void __init kmem_cache_init(void)
        int order;
        int node;
 
+       if (num_possible_nodes() == 1)
+               use_alien_caches = 0;
+
        for (i = 0; i < NUM_INIT_LISTS; i++) {
                kmem_list3_init(&initkmem_list3[i]);
                if (i < MAX_NUMNODES)
@@ -3563,7 +3566,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
        check_irq_off();
        objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
-       if (cache_free_alien(cachep, objp))
+       if (use_alien_caches && cache_free_alien(cachep, objp))
                return;
 
        if (likely(ac->avail < ac->limit)) {
index 9eef486..cb5aabd 100644 (file)
@@ -431,7 +431,7 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
                area->flags |= VM_VPAGES;
        } else {
                pages = kmalloc_node(array_size,
-                               (gfp_mask & ~(__GFP_HIGHMEM | __GFP_ZERO)),
+                               (gfp_mask & GFP_LEVEL_MASK),
                                node);
        }
        area->pages = pages;
@@ -577,6 +577,14 @@ void *vmalloc_exec(unsigned long size)
        return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
 }
 
+#if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32)
+#define GFP_VMALLOC32 GFP_DMA32
+#elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA)
+#define GFP_VMALLOC32 GFP_DMA
+#else
+#define GFP_VMALLOC32 GFP_KERNEL
+#endif
+
 /**
  *     vmalloc_32  -  allocate virtually contiguous memory (32bit addressable)
  *     @size:          allocation size
@@ -586,7 +594,7 @@ void *vmalloc_exec(unsigned long size)
  */
 void *vmalloc_32(unsigned long size)
 {
-       return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL);
+       return __vmalloc(size, GFP_VMALLOC32, PAGE_KERNEL);
 }
 EXPORT_SYMBOL(vmalloc_32);
 
@@ -602,7 +610,7 @@ void *vmalloc_32_user(unsigned long size)
        struct vm_struct *area;
        void *ret;
 
-       ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+       ret = __vmalloc(size, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL);
        if (ret) {
                write_lock(&vmlist_lock);
                area = __find_vm_area(ret);
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)
@@ -542,6 +542,38 @@ static void rxrpc_zap_tx_window(struct rxrpc_call *call)
        kfree(acks_window);
 }
 
+/*
+ * 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
  */
@@ -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);
@@ -27,6 +28,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
  */
@@ -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 628f393..4ab36de 100644 (file)
@@ -657,6 +657,7 @@ static int secref_whitelist(const char *modname, const char *tosec,
                "_probe",
                "_probe_one",
                "_console",
+               "apic_es7000",
                NULL
        };
 
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 28db4be..19c65a8 100644 (file)
@@ -260,7 +260,7 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
        if (platform_ops && platform_ops->suspend)
                platform_ops->suspend(platform_ops->priv);
        GCR |= GCR_ACLINK_OFF;
-       pxa_set_cken(CKEN2_AC97, 0);
+       pxa_set_cken(CKEN_AC97, 0);
 
        return 0;
 }
@@ -269,7 +269,7 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card)
 {
        pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
 
-       pxa_set_cken(CKEN2_AC97, 1);
+       pxa_set_cken(CKEN_AC97, 1);
        if (platform_ops && platform_ops->resume)
                platform_ops->resume(platform_ops->priv);
        snd_ac97_resume(pxa2xx_ac97_ac97);
@@ -337,7 +337,7 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
        /* Use GPIO 113 as AC97 Reset on Bulverde */
        pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 #endif
-       pxa_set_cken(CKEN2_AC97, 1);
+       pxa_set_cken(CKEN_AC97, 1);
 
        ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
        if (ret)
@@ -361,10 +361,10 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
  err:
        if (card)
                snd_card_free(card);
-       if (CKEN & CKEN2_AC97) {
+       if (CKEN & CKEN_AC97) {
                GCR |= GCR_ACLINK_OFF;
                free_irq(IRQ_AC97, NULL);
-               pxa_set_cken(CKEN2_AC97, 0);
+               pxa_set_cken(CKEN_AC97, 0);
        }
        return ret;
 }
@@ -378,7 +378,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
                platform_set_drvdata(dev, NULL);
                GCR |= GCR_ACLINK_OFF;
                free_irq(IRQ_AC97, NULL);
-               pxa_set_cken(CKEN2_AC97, 0);
+               pxa_set_cken(CKEN_AC97, 0);
        }
 
        return 0;
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"
index 1bbbeff..b222755 100644 (file)
@@ -256,7 +256,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *pdev,
        struct snd_soc_cpu_dai *dai)
 {
        GCR |= GCR_ACLINK_OFF;
-       pxa_set_cken(CKEN2_AC97, 0);
+       pxa_set_cken(CKEN_AC97, 0);
        return 0;
 }
 
@@ -271,7 +271,7 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
        /* Use GPIO 113 as AC97 Reset on Bulverde */
        pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 #endif
-       pxa_set_cken(CKEN2_AC97, 1);
+       pxa_set_cken(CKEN_AC97, 1);
        return 0;
 }
 
@@ -296,14 +296,14 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
        /* Use GPIO 113 as AC97 Reset on Bulverde */
        pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 #endif
-       pxa_set_cken(CKEN2_AC97, 1);
+       pxa_set_cken(CKEN_AC97, 1);
        return 0;
 
  err:
-       if (CKEN & CKEN2_AC97) {
+       if (CKEN & CKEN_AC97) {
                GCR |= GCR_ACLINK_OFF;
                free_irq(IRQ_AC97, NULL);
-               pxa_set_cken(CKEN2_AC97, 0);
+               pxa_set_cken(CKEN_AC97, 0);
        }
        return ret;
 }
@@ -312,7 +312,7 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev)
 {
        GCR |= GCR_ACLINK_OFF;
        free_irq(IRQ_AC97, NULL);
-       pxa_set_cken(CKEN2_AC97, 0);
+       pxa_set_cken(CKEN_AC97, 0);
 }
 
 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
index 575a613..50c5c83 100644 (file)
@@ -149,7 +149,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
-       pxa_set_cken(CKEN8_I2S, 1);
+       pxa_set_cken(CKEN_I2S, 1);
        pxa_i2s_wait();
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -234,7 +234,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
        if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
                SACR0 &= ~SACR0_ENB;
                pxa_i2s_wait();
-               pxa_set_cken(CKEN8_I2S, 0);
+               pxa_set_cken(CKEN_I2S, 0);
        }
 }