Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
authorDmitry Torokhov <dtor@insightbb.com>
Tue, 8 May 2007 05:31:11 +0000 (01:31 -0400)
committerDmitry Torokhov <dtor@insightbb.com>
Tue, 8 May 2007 05:31:11 +0000 (01:31 -0400)
2189 files changed:
CREDITS
Documentation/DocBook/Makefile
Documentation/DocBook/man/Makefile [deleted file]
Documentation/blackfin/00-INDEX [new file with mode: 0644]
Documentation/blackfin/Filesystems [new file with mode: 0644]
Documentation/blackfin/cache-lock.txt [new file with mode: 0644]
Documentation/blackfin/cachefeatures.txt [new file with mode: 0644]
Documentation/dontdiff
Documentation/driver-model/devres.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/proc.txt
Documentation/i2c/busses/i2c-nforce2
Documentation/i2c/porting-clients
Documentation/i2c/summary
Documentation/i2c/writing-clients
Documentation/i386/boot.txt
Documentation/ia64/aliasing-test.c [new file with mode: 0644]
Documentation/ia64/aliasing.txt
Documentation/ia64/err_inject.txt [new file with mode: 0644]
Documentation/kbuild/modules.txt
Documentation/kernel-parameters.txt
Documentation/pci.txt
Documentation/pcmcia/driver.txt [new file with mode: 0644]
Documentation/power/interface.txt
Documentation/power/pci.txt
Documentation/scsi/aacraid.txt
Documentation/scsi/ncr53c8xx.txt
Documentation/sh/clk.txt [new file with mode: 0644]
Documentation/spi/pxa2xx
Documentation/sysctl/vm.txt
Documentation/sysrq.txt
Documentation/usb/usb-serial.txt
Documentation/vm/slabinfo.c [new file with mode: 0644]
Documentation/vm/slub.txt [new file with mode: 0644]
Documentation/x86_64/boot-options.txt
Documentation/x86_64/fake-numa-for-cpusets [new file with mode: 0644]
Documentation/x86_64/machinecheck
Kbuild
MAINTAINERS
Makefile
arch/alpha/boot/bootpz.c
arch/alpha/boot/misc.c
arch/alpha/boot/tools/objstrip.c
arch/alpha/kernel/err_common.c
arch/alpha/kernel/err_ev6.c
arch/alpha/kernel/err_ev7.c
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/srmcons.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/mmap.c
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/Kconfig
arch/arm26/boot/compressed/misc.c
arch/blackfin/Kconfig [new file with mode: 0644]
arch/blackfin/Makefile [new file with mode: 0644]
arch/blackfin/boot/Makefile [new file with mode: 0644]
arch/blackfin/defconfig [new file with mode: 0644]
arch/blackfin/kernel/Makefile [new file with mode: 0644]
arch/blackfin/kernel/asm-offsets.c [new file with mode: 0644]
arch/blackfin/kernel/bfin_dma_5xx.c [new file with mode: 0644]
arch/blackfin/kernel/bfin_gpio.c [new file with mode: 0644]
arch/blackfin/kernel/bfin_ksyms.c [new file with mode: 0644]
arch/blackfin/kernel/dma-mapping.c [new file with mode: 0644]
arch/blackfin/kernel/dualcore_test.c [new file with mode: 0644]
arch/blackfin/kernel/entry.S [new file with mode: 0644]
arch/blackfin/kernel/flat.c [new file with mode: 0644]
arch/blackfin/kernel/init_task.c [new file with mode: 0644]
arch/blackfin/kernel/irqchip.c [new file with mode: 0644]
arch/blackfin/kernel/module.c [new file with mode: 0644]
arch/blackfin/kernel/process.c [new file with mode: 0644]
arch/blackfin/kernel/ptrace.c [new file with mode: 0644]
arch/blackfin/kernel/setup.c [new file with mode: 0644]
arch/blackfin/kernel/signal.c [new file with mode: 0644]
arch/blackfin/kernel/sys_bfin.c [new file with mode: 0644]
arch/blackfin/kernel/time.c [new file with mode: 0644]
arch/blackfin/kernel/traps.c [new file with mode: 0644]
arch/blackfin/kernel/vmlinux.lds.S [new file with mode: 0644]
arch/blackfin/lib/Makefile [new file with mode: 0644]
arch/blackfin/lib/ashldi3.c [new file with mode: 0644]
arch/blackfin/lib/ashrdi3.c [new file with mode: 0644]
arch/blackfin/lib/checksum.c [new file with mode: 0644]
arch/blackfin/lib/divsi3.S [new file with mode: 0644]
arch/blackfin/lib/gcclib.h [new file with mode: 0644]
arch/blackfin/lib/ins.S [new file with mode: 0644]
arch/blackfin/lib/lshrdi3.c [new file with mode: 0644]
arch/blackfin/lib/memchr.S [new file with mode: 0644]
arch/blackfin/lib/memcmp.S [new file with mode: 0644]
arch/blackfin/lib/memcpy.S [new file with mode: 0644]
arch/blackfin/lib/memmove.S [new file with mode: 0644]
arch/blackfin/lib/memset.S [new file with mode: 0644]
arch/blackfin/lib/modsi3.S [new file with mode: 0644]
arch/blackfin/lib/muldi3.c [new file with mode: 0644]
arch/blackfin/lib/outs.S [new file with mode: 0644]
arch/blackfin/lib/smulsi3_highpart.S [new file with mode: 0644]
arch/blackfin/lib/strcmp.c [new file with mode: 0644]
arch/blackfin/lib/strcpy.c [new file with mode: 0644]
arch/blackfin/lib/strncmp.c [new file with mode: 0644]
arch/blackfin/lib/strncpy.c [new file with mode: 0644]
arch/blackfin/lib/udivsi3.S [new file with mode: 0644]
arch/blackfin/lib/umodsi3.S [new file with mode: 0644]
arch/blackfin/lib/umulsi3_highpart.S [new file with mode: 0644]
arch/blackfin/mach-bf533/Kconfig [new file with mode: 0644]
arch/blackfin/mach-bf533/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/cm_bf533.c [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/ezkit.c [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/generic_board.c [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/stamp.c [new file with mode: 0644]
arch/blackfin/mach-bf533/cpu.c [new file with mode: 0644]
arch/blackfin/mach-bf533/head.S [new file with mode: 0644]
arch/blackfin/mach-bf533/ints-priority.c [new file with mode: 0644]
arch/blackfin/mach-bf537/Kconfig [new file with mode: 0644]
arch/blackfin/mach-bf537/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/cm_bf537.c [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/eth_mac.c [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/generic_board.c [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/led.S [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/pnav10.c [new file with mode: 0644]
arch/blackfin/mach-bf537/boards/stamp.c [new file with mode: 0644]
arch/blackfin/mach-bf537/cpu.c [new file with mode: 0644]
arch/blackfin/mach-bf537/head.S [new file with mode: 0644]
arch/blackfin/mach-bf537/ints-priority.c [new file with mode: 0644]
arch/blackfin/mach-bf561/Kconfig [new file with mode: 0644]
arch/blackfin/mach-bf561/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf561/boards/Makefile [new file with mode: 0644]
arch/blackfin/mach-bf561/boards/cm_bf561.c [new file with mode: 0644]
arch/blackfin/mach-bf561/boards/ezkit.c [new file with mode: 0644]
arch/blackfin/mach-bf561/boards/generic_board.c [new file with mode: 0644]
arch/blackfin/mach-bf561/coreb.c [new file with mode: 0644]
arch/blackfin/mach-bf561/head.S [new file with mode: 0644]
arch/blackfin/mach-bf561/ints-priority.c [new file with mode: 0644]
arch/blackfin/mach-common/Makefile [new file with mode: 0644]
arch/blackfin/mach-common/cache.S [new file with mode: 0644]
arch/blackfin/mach-common/cacheinit.S [new file with mode: 0644]
arch/blackfin/mach-common/cplbhdlr.S [new file with mode: 0644]
arch/blackfin/mach-common/cplbinfo.c [new file with mode: 0644]
arch/blackfin/mach-common/cplbmgr.S [new file with mode: 0644]
arch/blackfin/mach-common/dpmc.S [new file with mode: 0644]
arch/blackfin/mach-common/entry.S [new file with mode: 0644]
arch/blackfin/mach-common/interrupt.S [new file with mode: 0644]
arch/blackfin/mach-common/ints-priority-dc.c [new file with mode: 0644]
arch/blackfin/mach-common/ints-priority-sc.c [new file with mode: 0644]
arch/blackfin/mach-common/irqpanic.c [new file with mode: 0644]
arch/blackfin/mach-common/lock.S [new file with mode: 0644]
arch/blackfin/mach-common/pm.c [new file with mode: 0644]
arch/blackfin/mm/Makefile [new file with mode: 0644]
arch/blackfin/mm/blackfin_sram.c [new file with mode: 0644]
arch/blackfin/mm/blackfin_sram.h [new file with mode: 0644]
arch/blackfin/mm/init.c [new file with mode: 0644]
arch/blackfin/oprofile/Kconfig [new file with mode: 0644]
arch/blackfin/oprofile/Makefile [new file with mode: 0644]
arch/blackfin/oprofile/common.c [new file with mode: 0644]
arch/blackfin/oprofile/op_blackfin.h [new file with mode: 0644]
arch/blackfin/oprofile/op_model_bf533.c [new file with mode: 0644]
arch/blackfin/oprofile/timer_int.c [new file with mode: 0644]
arch/cris/arch-v32/kernel/fasttimer.c
arch/cris/arch-v32/vmlinux.lds.S
arch/cris/kernel/profile.c
arch/frv/Kconfig
arch/frv/kernel/vmlinux.lds.S
arch/frv/mm/elf-fdpic.c
arch/h8300/Kconfig
arch/h8300/Makefile
arch/h8300/boot/Makefile
arch/h8300/boot/compressed/Makefile [new file with mode: 0644]
arch/h8300/boot/compressed/head.S [new file with mode: 0644]
arch/h8300/boot/compressed/misc.c [new file with mode: 0644]
arch/h8300/kernel/Makefile
arch/h8300/kernel/irq.c [new file with mode: 0644]
arch/h8300/kernel/setup.c
arch/h8300/kernel/time.c
arch/h8300/mm/kmap.c
arch/h8300/platform/h8300h/Makefile
arch/h8300/platform/h8300h/entry.S
arch/h8300/platform/h8300h/generic/Makefile
arch/h8300/platform/h8300h/ints_h8300h.c [deleted file]
arch/h8300/platform/h8s/entry.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/hugetlbpage.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/defconfig
arch/ia64/kernel/Makefile
arch/ia64/kernel/efi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/err_inject.c [new file with mode: 0644]
arch/ia64/kernel/ivt.S
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/patch.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/sys_ia64.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/mm/hugetlbpage.c
arch/ia64/mm/init.c
arch/ia64/mm/ioremap.c
arch/ia64/pci/pci.c
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/amiints.c
arch/m68k/amiga/cia.c
arch/m68k/amiga/config.c
arch/m68k/apollo/dn_ints.c
arch/m68k/atari/Makefile
arch/m68k/atari/ataints.c
arch/m68k/atari/atakeyb.c [new file with mode: 0644]
arch/m68k/atari/atasound.h [deleted file]
arch/m68k/atari/config.c
arch/m68k/atari/debug.c
arch/m68k/kernel/entry.S
arch/m68k/kernel/head.S
arch/m68k/kernel/ints.c
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/macints.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/q40/config.c
arch/m68k/q40/q40ints.c
arch/m68k/sun3/sun3ints.c
arch/m68k/sun3x/prom.c
arch/m68knommu/kernel/dma.c
arch/mips/Kconfig
arch/mips/kernel/vmlinux.lds.S
arch/mips/lib/iomap.c
arch/mips/pmc-sierra/msp71xx/msp_serial.c [new file with mode: 0644]
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/vmlinux.lds.S
arch/powerpc/Kconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/legacy_serial.c
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/mm/hugetlbpage.c
arch/powerpc/mm/init_64.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/powermac/cpufreq_32.c
arch/powerpc/platforms/pseries/power.c
arch/powerpc/platforms/pseries/ras.c
arch/ppc/8260_io/enet.c
arch/ppc/8260_io/fcc_enet.c
arch/ppc/8xx_io/enet.c
arch/ppc/kernel/vmlinux.lds.S
arch/ppc/syslib/ppc4xx_sgdma.c
arch/s390/Kconfig
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/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/hp6xx/Makefile
arch/sh/boards/hp6xx/setup.c
arch/sh/boards/landisk/Makefile
arch/sh/boards/landisk/gio.c [new file with mode: 0644]
arch/sh/boards/landisk/io.c [deleted file]
arch/sh/boards/landisk/irq.c
arch/sh/boards/landisk/landisk_pwb.c [deleted file]
arch/sh/boards/landisk/psw.c [new file with mode: 0644]
arch/sh/boards/landisk/rtc.c [deleted file]
arch/sh/boards/landisk/setup.c
arch/sh/boards/lboxre2/Makefile [new file with mode: 0644]
arch/sh/boards/lboxre2/irq.c [new file with mode: 0644]
arch/sh/boards/lboxre2/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/Kconfig
arch/sh/boards/renesas/r7780rp/Makefile
arch/sh/boards/renesas/r7780rp/irq-r7780rp.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/irq-r7785rp.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/irq.c
arch/sh/boards/renesas/r7780rp/setup.c
arch/sh/boards/se/770x/io.c
arch/sh/boards/se/770x/irq.c
arch/sh/boards/se/770x/setup.c
arch/sh/boards/se/7722/Makefile [new file with mode: 0644]
arch/sh/boards/se/7722/irq.c [new file with mode: 0644]
arch/sh/boards/se/7722/setup.c [new file with mode: 0644]
arch/sh/boards/se/7751/setup.c
arch/sh/boards/se/7780/Makefile [new file with mode: 0644]
arch/sh/boards/se/7780/irq.c [new file with mode: 0644]
arch/sh/boards/se/7780/setup.c [new file with mode: 0644]
arch/sh/configs/lboxre2_defconfig [new file with mode: 0644]
arch/sh/configs/r7780rp_defconfig
arch/sh/configs/r7785rp_defconfig [new file with mode: 0644]
arch/sh/configs/se7705_defconfig
arch/sh/configs/se7712_defconfig [new file with mode: 0644]
arch/sh/configs/se7722_defconfig [new file with mode: 0644]
arch/sh/configs/se7780_defconfig [new file with mode: 0644]
arch/sh/drivers/Kconfig
arch/sh/drivers/heartbeat.c
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/fixups-lboxre2.c [new file with mode: 0644]
arch/sh/drivers/pci/fixups-se7780.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-landisk.c
arch/sh/drivers/pci/ops-lboxre2.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-r7780rp.c
arch/sh/drivers/pci/ops-se7780.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-sh4.c
arch/sh/drivers/pci/pci-sh4.h
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7780.c
arch/sh/drivers/pci/pci-sh7780.h
arch/sh/kernel/Makefile
arch/sh/kernel/cf-enabler.c
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/Makefile
arch/sh/kernel/cpu/irq/intc2.c
arch/sh/kernel/cpu/irq/pint.c
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/probe.c
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh7709.c
arch/sh/kernel/cpu/sh3/setup-sh7710.c
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7722.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/clock-sh7785.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7785.c [new file with mode: 0644]
arch/sh/kernel/crash_dump.c [new file with mode: 0644]
arch/sh/kernel/irq.c
arch/sh/kernel/kgdb_stub.c
arch/sh/kernel/machine_kexec.c
arch/sh/kernel/process.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps.c
arch/sh/kernel/vmlinux.lds.S
arch/sh/lib/Makefile
arch/sh/lib/udivdi3.c [deleted file]
arch/sh/mm/Kconfig
arch/sh/mm/fault.c
arch/sh/mm/init.c
arch/sh/tools/mach-types
arch/sh64/kernel/vmlinux.lds.S
arch/sh64/mach-cayman/iomap.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc64/Kconfig
arch/sparc64/defconfig
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/central.c
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_fire.c [new file with mode: 0644]
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/prom.c
arch/sparc64/kernel/smp.c
arch/sparc64/mm/hugetlbpage.c
arch/sparc64/mm/init.c
arch/sparc64/mm/tsb.c
arch/sparc64/solaris/ioctl.c
arch/um/defconfig
arch/um/drivers/chan_kern.c
arch/um/drivers/chan_user.c
arch/um/drivers/cow_sys.h
arch/um/drivers/daemon_user.c
arch/um/drivers/fd.c
arch/um/drivers/harddog_user.c
arch/um/drivers/line.c
arch/um/drivers/mcast_user.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_user.c
arch/um/drivers/mmapper_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/net_user.c
arch/um/drivers/pcap_user.c
arch/um/drivers/port_user.c
arch/um/drivers/pty.c
arch/um/drivers/slip_user.c
arch/um/drivers/slirp_user.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/drivers/tty.c
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_user.c
arch/um/drivers/xterm.c
arch/um/include/arch.h [new file with mode: 0644]
arch/um/include/as-layout.h [new file with mode: 0644]
arch/um/include/common-offsets.h
arch/um/include/kern_util.h
arch/um/include/net_kern.h
arch/um/include/net_user.h
arch/um/include/os.h
arch/um/include/skas/mode_kern_skas.h
arch/um/include/tlb.h
arch/um/include/tt/uaccess-tt.h
arch/um/include/um_malloc.h
arch/um/include/user.h
arch/um/include/user_util.h [deleted file]
arch/um/kernel/exec.c
arch/um/kernel/init_task.c
arch/um/kernel/initrd.c
arch/um/kernel/irq.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/physmem.c
arch/um/kernel/process.c
arch/um/kernel/reboot.c
arch/um/kernel/signal.c
arch/um/kernel/skas/exec.c
arch/um/kernel/skas/process.c
arch/um/kernel/skas/tlb.c
arch/um/kernel/smp.c
arch/um/kernel/syscall.c
arch/um/kernel/sysrq.c
arch/um/kernel/time.c
arch/um/kernel/tlb.c
arch/um/kernel/trap.c
arch/um/kernel/tt/exec_kern.c
arch/um/kernel/tt/exec_user.c
arch/um/kernel/tt/gdb.c
arch/um/kernel/tt/include/mode_kern-tt.h [deleted file]
arch/um/kernel/tt/mem.c
arch/um/kernel/tt/mem_user.c
arch/um/kernel/tt/process_kern.c
arch/um/kernel/tt/ptproxy/proxy.c
arch/um/kernel/tt/ptproxy/ptrace.c
arch/um/kernel/tt/ptproxy/sysdep.c
arch/um/kernel/tt/ptproxy/wait.c
arch/um/kernel/tt/syscall_user.c
arch/um/kernel/tt/tlb.c
arch/um/kernel/tt/tracer.c
arch/um/kernel/tt/trap_user.c
arch/um/kernel/tt/uaccess_user.c
arch/um/kernel/um_arch.c
arch/um/os-Linux/aio.c
arch/um/os-Linux/drivers/ethertap_user.c
arch/um/os-Linux/drivers/tuntap_user.c
arch/um/os-Linux/file.c
arch/um/os-Linux/helper.c
arch/um/os-Linux/irq.c
arch/um/os-Linux/main.c
arch/um/os-Linux/mem.c
arch/um/os-Linux/process.c
arch/um/os-Linux/sigio.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/skas/mem.c
arch/um/os-Linux/skas/process.c
arch/um/os-Linux/skas/trap.c
arch/um/os-Linux/start_up.c
arch/um/os-Linux/sys-i386/tls.c
arch/um/os-Linux/time.c
arch/um/os-Linux/trap.c
arch/um/os-Linux/tt.c
arch/um/os-Linux/tty_log.c
arch/um/os-Linux/util.c
arch/um/sys-i386/bugs.c
arch/um/sys-i386/fault.c
arch/um/sys-i386/ptrace_user.c
arch/um/sys-i386/signal.c
arch/um/sys-i386/tls.c
arch/um/sys-i386/user-offsets.c
arch/um/sys-ppc/sigcontext.c
arch/um/sys-x86_64/bugs.c
arch/um/sys-x86_64/fault.c
arch/um/sys-x86_64/signal.c
arch/um/sys-x86_64/user-offsets.c
arch/v850/Kconfig
arch/v850/kernel/time.c
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/sys_x86_64.c
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/ioremap.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/network.c
arch/xtensa/platform-iss/setup.c
block/cfq-iosched.c
block/genhd.c
block/ioctl.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/acpi/sleep/proc.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/pata_icside.c [new file with mode: 0644]
drivers/atm/adummy.c
drivers/base/Makefile
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/amiflop.c
drivers/block/aoe/aoecmd.c
drivers/block/loop.c
drivers/block/rd.c
drivers/bluetooth/hci_usb.c
drivers/cdrom/cdrom.c
drivers/char/Kconfig
drivers/char/Makefile
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/drm/README.drm
drivers/char/drm/drm.h
drivers/char/drm/drmP.h
drivers/char/drm/drm_bufs.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_fops.c
drivers/char/drm/drm_hashtab.c
drivers/char/drm/drm_hashtab.h
drivers/char/drm/drm_irq.c
drivers/char/drm/drm_lock.c
drivers/char/drm/drm_mm.c
drivers/char/drm/drm_pciids.h
drivers/char/drm/drm_proc.c
drivers/char/drm/drm_stub.c
drivers/char/drm/drm_vm.c
drivers/char/drm/i915_dma.c
drivers/char/drm/radeon_cp.c
drivers/char/drm/sis_drv.c
drivers/char/drm/via_drv.c
drivers/char/drm/via_mm.h [deleted file]
drivers/char/hw_random/via-rng.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/tpm/tpm.h
drivers/char/tty_io.c
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/chips/tps65010.c
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/fmr_pool.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/mad.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/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/amso1100/c2.h
drivers/infiniband/hw/amso1100/c2_cq.c
drivers/infiniband/hw/amso1100/c2_provider.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_cm.h
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_iverbs.h
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/infiniband/hw/ehca/ipz_pt_fn.h
drivers/infiniband/hw/ipath/ipath_cq.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/ipath/ipath_layer.c
drivers/infiniband/hw/ipath/ipath_mmap.c
drivers/infiniband/hw/ipath/ipath_qp.c
drivers/infiniband/hw/ipath/ipath_rc.c
drivers/infiniband/hw/ipath/ipath_srq.c
drivers/infiniband/hw/ipath/ipath_stats.c
drivers/infiniband/hw/ipath/ipath_sysfs.c
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/ipath/ipath_verbs.h
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/input/evdev.c
drivers/input/joydev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/atakbd.c [new file with mode: 0644]
drivers/input/keyboard/hilkbd.c
drivers/input/mouse/Kconfig
drivers/input/mouse/Makefile
drivers/input/mouse/atarimouse.c [new file with mode: 0644]
drivers/input/mousedev.c
drivers/input/touchscreen/hp680_ts_input.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/md/md.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-alsa.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-video.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/Kconfig
drivers/mtd/devices/block2mtd.c
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/mtd/ubi/eba.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/cxgb3/version.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/smc91x.h
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/Kconfig
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/at91_cf.c
drivers/pcmcia/cs.c
drivers/pcmcia/ds.c
drivers/pcmcia/socket_sysfs.c
drivers/ps3/ps3av.c
drivers/ps3/ps3av_cmd.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-bfin.c [new file with mode: 0644]
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/esp_scsi.c
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/sun_esp.c
drivers/scsi/tmscsim.c
drivers/serial/8250.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/amba-pl010.c
drivers/serial/atmel_serial.c
drivers/serial/atmel_serial.h
drivers/serial/bfin_5xx.c [new file with mode: 0644]
drivers/serial/crisv10.h [deleted file]
drivers/serial/imx.c
drivers/serial/mpsc.c
drivers/serial/of_serial.c
drivers/serial/pxa.c
drivers/serial/serial_core.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/serial/sunsu.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi_bfin5xx.c [new file with mode: 0644]
drivers/spi/spi_s3c24xx.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ohci-ps3.c
drivers/usb/host/ohci-pxa27x.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/sunxvr2500.c [new file with mode: 0644]
drivers/video/sunxvr500.c [new file with mode: 0644]
drivers/video/valkyriefb.c
drivers/zorro/proc.c
drivers/zorro/zorro-sysfs.c
drivers/zorro/zorro.c
fs/Kconfig
fs/Kconfig.binfmt
fs/adfs/super.c
fs/affs/super.c
fs/afs/Makefile
fs/afs/callback.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/fsclient.c
fs/afs/internal.h
fs/afs/main.c
fs/afs/mntpt.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/aio.c
fs/befs/linuxvfs.c
fs/bfs/inode.c
fs/bio.c
fs/block_dev.c
fs/buffer.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/coda/inode.c
fs/compat.c
fs/compat_ioctl.c
fs/configfs/mount.c
fs/cramfs/inode.c
fs/dcache.c
fs/debugfs/inode.c
fs/dlm/Kconfig
fs/dlm/Makefile
fs/dlm/ast.c
fs/dlm/config.c
fs/dlm/config.h
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lock.h
fs/dlm/lockspace.c
fs/dlm/lowcomms-sctp.c [deleted file]
fs/dlm/lowcomms-tcp.c [deleted file]
fs/dlm/lowcomms.c [new file with mode: 0644]
fs/dlm/user.c
fs/dquot.c
fs/ecryptfs/main.c
fs/ecryptfs/mmap.c
fs/efs/super.c
fs/ext2/dir.c
fs/ext2/super.c
fs/ext3/super.c
fs/ext4/super.c
fs/fat/cache.c
fs/fat/inode.c
fs/freevxfs/vxfs_subr.c
fs/fuse/file.c
fs/fuse/inode.c
fs/gfs2/dir.c
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/incore.h
fs/gfs2/locking/dlm/lock.c
fs/gfs2/locking/dlm/lock_dlm.h
fs/gfs2/locking/dlm/plock.c
fs/gfs2/locking/dlm/sysfs.c
fs/gfs2/locking/nolock/main.c
fs/gfs2/lops.c
fs/gfs2/main.c
fs/gfs2/mount.c
fs/gfs2/ops_address.c
fs/gfs2/ops_file.c
fs/gfs2/ops_fstype.c
fs/gfs2/ops_super.c
fs/gfs2/rgrp.c
fs/gfs2/sys.c
fs/hfs/super.c
fs/hfsplus/super.c
fs/hpfs/super.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/isofs/inode.c
fs/jffs2/super.c
fs/jfs/jfs_metapage.c
fs/jfs/super.c
fs/lockd/mon.c
fs/lockd/svc4proc.c
fs/lockd/svclock.c
fs/lockd/svcproc.c
fs/lockd/svcsubs.c
fs/lockd/xdr.c
fs/lockd/xdr4.c
fs/locks.c
fs/minix/dir.c
fs/minix/inode.c
fs/namei.c
fs/ncpfs/inode.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.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/symlink.c
fs/nfs/write.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
fs/ntfs/aops.h
fs/ntfs/attrib.c
fs/ntfs/file.c
fs/ntfs/super.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/dlmfs.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/ocfs2/symlink.c
fs/openpromfs/inode.c
fs/partitions/acorn.c
fs/partitions/check.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/proc_misc.c
fs/proc/task_mmu.c
fs/proc/vmcore.c
fs/qnx4/inode.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/romfs/inode.c
fs/smbfs/inode.c
fs/sysfs/bin.c
fs/sysfs/file.c
fs/sysv/dir.c
fs/sysv/inode.c
fs/udf/super.c
fs/ufs/dir.c
fs/ufs/super.c
fs/ufs/util.c
fs/xfs/linux-2.6/xfs_super.c
include/acpi/acpi_bus.h
include/asm-alpha/mmu_context.h
include/asm-alpha/percpu.h
include/asm-alpha/scatterlist.h
include/asm-alpha/thread_info.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-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-blackfin/Kbuild [new file with mode: 0644]
include/asm-blackfin/a.out.h [new file with mode: 0644]
include/asm-blackfin/atomic.h [new file with mode: 0644]
include/asm-blackfin/auxvec.h [new file with mode: 0644]
include/asm-blackfin/bf5xx_timers.h [new file with mode: 0644]
include/asm-blackfin/bfin-global.h [new file with mode: 0644]
include/asm-blackfin/bfin5xx_spi.h [new file with mode: 0644]
include/asm-blackfin/bfin_simple_timer.h [new file with mode: 0644]
include/asm-blackfin/bfin_sport.h [new file with mode: 0644]
include/asm-blackfin/bitops.h [new file with mode: 0644]
include/asm-blackfin/blackfin.h [new file with mode: 0644]
include/asm-blackfin/bug.h [new file with mode: 0644]
include/asm-blackfin/bugs.h [new file with mode: 0644]
include/asm-blackfin/byteorder.h [new file with mode: 0644]
include/asm-blackfin/cache.h [new file with mode: 0644]
include/asm-blackfin/cacheflush.h [new file with mode: 0644]
include/asm-blackfin/checksum.h [new file with mode: 0644]
include/asm-blackfin/cplb.h [new file with mode: 0644]
include/asm-blackfin/cplbinit.h [new file with mode: 0644]
include/asm-blackfin/cpumask.h [new file with mode: 0644]
include/asm-blackfin/cputime.h [new file with mode: 0644]
include/asm-blackfin/current.h [new file with mode: 0644]
include/asm-blackfin/delay.h [new file with mode: 0644]
include/asm-blackfin/device.h [new file with mode: 0644]
include/asm-blackfin/div64.h [new file with mode: 0644]
include/asm-blackfin/dma-mapping.h [new file with mode: 0644]
include/asm-blackfin/dma.h [new file with mode: 0644]
include/asm-blackfin/dpmc.h [new file with mode: 0644]
include/asm-blackfin/elf.h [new file with mode: 0644]
include/asm-blackfin/emergency-restart.h [new file with mode: 0644]
include/asm-blackfin/entry.h [new file with mode: 0644]
include/asm-blackfin/errno.h [new file with mode: 0644]
include/asm-blackfin/fcntl.h [new file with mode: 0644]
include/asm-blackfin/flat.h [new file with mode: 0644]
include/asm-blackfin/futex.h [new file with mode: 0644]
include/asm-blackfin/gpio.h [new file with mode: 0644]
include/asm-blackfin/hardirq.h [new file with mode: 0644]
include/asm-blackfin/hw_irq.h [new file with mode: 0644]
include/asm-blackfin/ide.h [new file with mode: 0644]
include/asm-blackfin/io.h [new file with mode: 0644]
include/asm-blackfin/ioctl.h [new file with mode: 0644]
include/asm-blackfin/ioctls.h [new file with mode: 0644]
include/asm-blackfin/ipc.h [new file with mode: 0644]
include/asm-blackfin/ipcbuf.h [new file with mode: 0644]
include/asm-blackfin/irq.h [new file with mode: 0644]
include/asm-blackfin/irq_handler.h [new file with mode: 0644]
include/asm-blackfin/irq_regs.h [new file with mode: 0644]
include/asm-blackfin/kdebug.h [new file with mode: 0644]
include/asm-blackfin/kmap_types.h [new file with mode: 0644]
include/asm-blackfin/l1layout.h [new file with mode: 0644]
include/asm-blackfin/linkage.h [new file with mode: 0644]
include/asm-blackfin/local.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/anomaly.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/bf533.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/bfin_serial_5xx.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/blackfin.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/cdefBF532.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/defBF532.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/dma.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/irq.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/mem_init.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/mem_map.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/anomaly.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/bf537.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/bfin_serial_5xx.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/blackfin.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/cdefBF534.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/cdefBF537.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/defBF534.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/defBF537.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/dma.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/irq.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/mem_init.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/mem_map.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/anomaly.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/bf561.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/bfin_serial_5xx.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/blackfin.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/cdefBF561.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/defBF561.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/dma.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/irq.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/mem_init.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/mem_map.h [new file with mode: 0644]
include/asm-blackfin/mach-common/cdef_LPBlackfin.h [new file with mode: 0644]
include/asm-blackfin/mach-common/context.S [new file with mode: 0644]
include/asm-blackfin/mach-common/def_LPBlackfin.h [new file with mode: 0644]
include/asm-blackfin/macros.h [new file with mode: 0644]
include/asm-blackfin/mem_map.h [new file with mode: 0644]
include/asm-blackfin/mman.h [new file with mode: 0644]
include/asm-blackfin/mmu.h [new file with mode: 0644]
include/asm-blackfin/mmu_context.h [new file with mode: 0644]
include/asm-blackfin/module.h [new file with mode: 0644]
include/asm-blackfin/msgbuf.h [new file with mode: 0644]
include/asm-blackfin/mutex.h [new file with mode: 0644]
include/asm-blackfin/namei.h [new file with mode: 0644]
include/asm-blackfin/page.h [new file with mode: 0644]
include/asm-blackfin/page_offset.h [new file with mode: 0644]
include/asm-blackfin/param.h [new file with mode: 0644]
include/asm-blackfin/pci.h [new file with mode: 0644]
include/asm-blackfin/percpu.h [new file with mode: 0644]
include/asm-blackfin/pgalloc.h [new file with mode: 0644]
include/asm-blackfin/pgtable.h [new file with mode: 0644]
include/asm-blackfin/poll.h [new file with mode: 0644]
include/asm-blackfin/posix_types.h [new file with mode: 0644]
include/asm-blackfin/processor.h [new file with mode: 0644]
include/asm-blackfin/ptrace.h [new file with mode: 0644]
include/asm-blackfin/resource.h [new file with mode: 0644]
include/asm-blackfin/scatterlist.h [new file with mode: 0644]
include/asm-blackfin/sections.h [new file with mode: 0644]
include/asm-blackfin/segment.h [new file with mode: 0644]
include/asm-blackfin/semaphore-helper.h [new file with mode: 0644]
include/asm-blackfin/semaphore.h [new file with mode: 0644]
include/asm-blackfin/sembuf.h [new file with mode: 0644]
include/asm-blackfin/setup.h [new file with mode: 0644]
include/asm-blackfin/shmbuf.h [new file with mode: 0644]
include/asm-blackfin/shmparam.h [new file with mode: 0644]
include/asm-blackfin/sigcontext.h [new file with mode: 0644]
include/asm-blackfin/siginfo.h [new file with mode: 0644]
include/asm-blackfin/signal.h [new file with mode: 0644]
include/asm-blackfin/socket.h [new file with mode: 0644]
include/asm-blackfin/sockios.h [new file with mode: 0644]
include/asm-blackfin/spinlock.h [new file with mode: 0644]
include/asm-blackfin/stat.h [new file with mode: 0644]
include/asm-blackfin/statfs.h [new file with mode: 0644]
include/asm-blackfin/string.h [new file with mode: 0644]
include/asm-blackfin/system.h [new file with mode: 0644]
include/asm-blackfin/termbits.h [new file with mode: 0644]
include/asm-blackfin/termios.h [new file with mode: 0644]
include/asm-blackfin/thread_info.h [new file with mode: 0644]
include/asm-blackfin/timex.h [new file with mode: 0644]
include/asm-blackfin/tlb.h [new file with mode: 0644]
include/asm-blackfin/tlbflush.h [new file with mode: 0644]
include/asm-blackfin/topology.h [new file with mode: 0644]
include/asm-blackfin/traps.h [new file with mode: 0644]
include/asm-blackfin/types.h [new file with mode: 0644]
include/asm-blackfin/uaccess.h [new file with mode: 0644]
include/asm-blackfin/ucontext.h [new file with mode: 0644]
include/asm-blackfin/unaligned.h [new file with mode: 0644]
include/asm-blackfin/unistd.h [new file with mode: 0644]
include/asm-blackfin/user.h [new file with mode: 0644]
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/irq.h
include/asm-h8300/irq_regs.h [new file with mode: 0644]
include/asm-h8300/mmu_context.h
include/asm-h8300/pgtable.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/thread_info.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/asmmacro.h
include/asm-ia64/io.h
include/asm-ia64/kregs.h
include/asm-ia64/mmu_context.h
include/asm-ia64/pal.h
include/asm-ia64/patch.h
include/asm-ia64/processor.h
include/asm-ia64/scatterlist.h
include/asm-ia64/sections.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/dma-mapping.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/bug.h
include/asm-sh/clock.h
include/asm-sh/cpu-sh3/mmu_context.h
include/asm-sh/cpu-sh4/freq.h
include/asm-sh/irq.h
include/asm-sh/kdebug.h [new file with mode: 0644]
include/asm-sh/kexec.h
include/asm-sh/kgdb.h
include/asm-sh/lboxre2.h [new file with mode: 0644]
include/asm-sh/mmu_context.h
include/asm-sh/page.h
include/asm-sh/param.h
include/asm-sh/pci.h
include/asm-sh/processor.h
include/asm-sh/r7780rp.h
include/asm-sh/scatterlist.h
include/asm-sh/se.h
include/asm-sh/se7722.h [new file with mode: 0644]
include/asm-sh/se7751.h
include/asm-sh/se7780.h [new file with mode: 0644]
include/asm-sh/stat.h
include/asm-sh/system.h
include/asm-sh64/mmu_context.h
include/asm-sh64/scatterlist.h
include/asm-sparc/mmu_context.h
include/asm-sparc64/iommu.h
include/asm-sparc64/mmu_context.h
include/asm-sparc64/percpu.h
include/asm-sparc64/pgalloc.h
include/asm-sparc64/scatterlist.h
include/asm-um/mmu_context.h
include/asm-um/page.h
include/asm-um/tlbflush.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/buffer_head.h
include/linux/compiler-gcc.h
include/linux/compiler-gcc3.h
include/linux/compiler-gcc4.h
include/linux/compiler-intel.h
include/linux/cpufreq.h
include/linux/crash_dump.h
include/linux/crypto.h
include/linux/device.h
include/linux/dlm_device.h
include/linux/elf-em.h
include/linux/elf.h
include/linux/elfnote.h
include/linux/etherdevice.h
include/linux/ethtool.h
include/linux/fcntl.h
include/linux/fs.h
include/linux/gfp.h
include/linux/highmem.h
include/linux/hugetlb.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.h
include/linux/interrupt.h
include/linux/kernel.h
include/linux/kobject.h
include/linux/kvm.h
include/linux/lockd/lockd.h
include/linux/migrate.h
include/linux/miscdevice.h
include/linux/mm.h
include/linux/mm_types.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/mmzone.h
include/linux/mod_devicetable.h
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/page-flags.h
include/linux/pagemap.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/proc_fs.h
include/linux/quicklist.h [new file with mode: 0644]
include/linux/reboot_fixups.h [deleted file]
include/linux/rfkill.h [new file with mode: 0644]
include/linux/serial_core.h
include/linux/serial_reg.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/slub_def.h [new file with mode: 0644]
include/linux/spi/ad7877.h [new file with mode: 0644]
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/suspend.h
include/linux/tifm.h
include/linux/usb_sl811.h [new file with mode: 0644]
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/pcmcia/ds.h
include/rdma/ib_mad.h
include/rdma/ib_verbs.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/Kconfig
init/do_mounts_initrd.c
init/main.c
ipc/mqueue.c
kernel/cpuset.c
kernel/delayacct.c
kernel/exit.c
kernel/fork.c
kernel/irq/chip.c
kernel/ksysfs.c
kernel/module.c
kernel/params.c
kernel/pid.c
kernel/power/Kconfig
kernel/power/disk.c
kernel/power/main.c
kernel/power/power.h
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/swap.c
kernel/power/swsusp.c
kernel/power/user.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/taskstats.c
lib/Kconfig
lib/Kconfig.debug
lib/cpumask.c
lib/inflate.c
lib/iomap.c
lib/kobject.c
lib/parser.c
lib/zlib_inflate/inflate.c
mm/Kconfig
mm/Makefile
mm/filemap.c
mm/highmem.c
mm/internal.h
mm/madvise.c
mm/memory.c
mm/mmap.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/quicklist.c [new file with mode: 0644]
mm/readahead.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/slob.c
mm/slub.c [new file with mode: 0644]
mm/sparse.c
mm/swap.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
net/8021q/vlan.c
net/8021q/vlanproc.c
net/Kconfig
net/Makefile
net/bluetooth/hci_sock.c
net/bluetooth/hci_sysfs.c
net/bluetooth/l2cap.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/tty.c
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/ipv6/netfilter/Kconfig
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/netfilter/Kconfig
net/netlink/af_netlink.c
net/netrom/nr_route.c
net/rfkill/Kconfig [new file with mode: 0644]
net/rfkill/Makefile [new file with mode: 0644]
net/rfkill/rfkill-input.c [new file with mode: 0644]
net/rfkill/rfkill.c [new file with mode: 0644]
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/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/rpc_pipe.c
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/Kconfig
net/tipc/eth_media.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
scripts/Makefile.build
scripts/Makefile.host
scripts/Makefile.modpost
scripts/basic/fixdep.c
scripts/checksyscalls.sh [new file with mode: 0755]
scripts/cleanfile [new file with mode: 0755]
scripts/cleanpatch [new file with mode: 0755]
scripts/gen_initramfs_list.sh
scripts/genksyms/genksyms.c
scripts/kconfig/Makefile
scripts/kconfig/conf.c
scripts/kconfig/lex.zconf.c_shipped
scripts/kconfig/lkc.h
scripts/kconfig/lxdialog/dialog.h
scripts/kconfig/lxdialog/util.c
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/kconfig/qconf.cc
scripts/kconfig/qconf.h
scripts/kconfig/symbol.c
scripts/kconfig/zconf.l
scripts/kconfig/zconf.tab.c_shipped
scripts/kconfig/zconf.y
scripts/mkcompile_h
scripts/mkuboot.sh
scripts/mod/file2alias.c
scripts/mod/mk_elfconfig.c
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/mod/sumversion.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/sh_dac_audio.c
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
usr/Kconfig

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 867608a..10b5cd6 100644 (file)
@@ -41,7 +41,7 @@ psdocs: $(PS)
 PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
 pdfdocs: $(PDF)
 
-HTML := $(patsubst %.xml, %.html, $(BOOKS))
+HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
 htmldocs: $(HTML)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
@@ -152,6 +152,7 @@ quiet_cmd_db2man = MAN     $@
        @(which xmlto > /dev/null 2>&1) || \
         (echo "*** You need to install xmlto ***"; \
          exit 1)
+       $(Q)mkdir -p $(obj)/man
        $(call cmd,db2man)
        @touch $@
 
@@ -212,11 +213,7 @@ clean-files := $(DOCBOOKS) \
        $(patsubst %.xml, %.9,    $(DOCBOOKS)) \
        $(C-procfs-example)
 
-clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
-
-#man put files in man subdir - traverse down
-subdir- := man/
-
+clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
 
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable se we can use it in if_changed and friends.
diff --git a/Documentation/DocBook/man/Makefile b/Documentation/DocBook/man/Makefile
deleted file mode 100644 (file)
index 4fb7ea0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Rules are put in Documentation/DocBook
-
-clean-files := *.9.gz *.sgml manpage.links manpage.refs
diff --git a/Documentation/blackfin/00-INDEX b/Documentation/blackfin/00-INDEX
new file mode 100644 (file)
index 0000000..7cb3b35
--- /dev/null
@@ -0,0 +1,11 @@
+00-INDEX
+       - This file
+
+cache-lock.txt
+       - HOWTO for blackfin cache locking.
+
+cachefeatures.txt
+       - Supported cache features.
+
+Filesystems
+       - Requirements for mounting the root file system.
diff --git a/Documentation/blackfin/Filesystems b/Documentation/blackfin/Filesystems
new file mode 100644 (file)
index 0000000..51260a1
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * File:         Documentation/blackfin/Filesystems
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Rev:          $Id: Filesystems 2384 2006-11-01 04:12:43Z magicyang $
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+               How to mount the root file system in uClinux/Blackfin
+               -----------------------------------------------------
+
+1      Mounting EXT3 File system.
+       ------------------------
+
+       Creating an EXT3 File system for uClinux/Blackfin:
+
+
+Please follow the steps to form the EXT3 File system and mount the same as root
+file system.
+
+a      Make an ext3 file system as large as you want the final root file
+       system.
+
+               mkfs.ext3  /dev/ram0 <your-rootfs-size-in-1k-blocks>
+
+b      Mount this Empty file system on a free directory as:
+
+               mount -t ext3 /dev/ram0  ./test
+                       where ./test is the empty directory.
+
+c      Copy your root fs directory that you have so carefully made over.
+
+               cp -af  /tmp/my_final_rootfs_files/* ./test
+
+               (For ex: cp -af uClinux-dist/romfs/* ./test)
+
+d      If you have done everything right till now you should be able to see
+       the required "root" dir's (that's etc, root, bin, lib, sbin...)
+
+e      Now unmount the file system
+
+               umount  ./test
+
+f      Create the root file system image.
+
+               dd if=/dev/ram0 bs=1k count=<your-rootfs-size-in-1k-blocks> \
+               > ext3fs.img
+
+
+Now you have to tell the kernel that will be mounting this file system as
+rootfs.
+So do a make menuconfig under kernel and select the Ext3 journaling file system
+support under File system --> submenu.
+
+
+2.     Mounting EXT2 File system.
+       -------------------------
+
+By default the ext2 file system image will be created if you invoke make from
+the top uClinux-dist directory.
+
+
+3.     Mounting CRAMFS File System
+       ----------------------------
+
+To create a CRAMFS file system image execute the command
+
+       mkfs.cramfs ./test cramfs.img
+
+       where ./test is the target directory.
+
+
+4.     Mounting ROMFS File System
+       --------------------------
+
+To create a ROMFS file system image execute the command
+
+       genromfs -v -V "ROMdisk" -f romfs.img -d ./test
+
+       where ./test is the target directory
+
+
+5.     Mounting the JFFS2 Filesystem
+       -----------------------------
+
+To create a compressed JFFS filesystem (JFFS2), please execute the command
+
+       mkfs.jffs2 -d ./test -o jffs2.img
+
+       where ./test is the target directory.
+
+However, please make sure the following is in your kernel config.
+
+/*
+ * RAM/ROM/Flash chip drivers
+ */
+#define CONFIG_MTD_CFI 1
+#define CONFIG_MTD_ROM 1
+/*
+ * Mapping drivers for chip access
+ */
+#define CONFIG_MTD_COMPLEX_MAPPINGS 1
+#define CONFIG_MTD_BF533 1
+#undef CONFIG_MTD_UCLINUX
+
+Through the u-boot boot loader, use the jffs2.img in the corresponding
+partition made in linux-2.6.x/drivers/mtd/maps/bf533_flash.c.
+
+NOTE -         Currently the Flash driver is available only for EZKIT. Watch out for a
+       STAMP driver soon.
+
+
+6.     Mounting the NFS File system
+       -----------------------------
+
+       For mounting the NFS please do the following in the kernel config.
+
+       In Networking Support --> Networking options --> TCP/IP networking -->
+               IP: kernel level autoconfiguration
+
+       Enable BOOTP Support.
+
+       In Kernel hacking --> Compiled-in kernel boot parameter add the following
+
+               root=/dev/nfs rw ip=bootp
+
+       In File system --> Network File system, Enable
+
+               NFS file system support --> NFSv3 client support
+               Root File system on NFS
+
+       in uClibc menuconfig, do the following
+       In Networking Support
+               enable Remote Procedure Call (RPC) support
+                       Full RPC Support
+
+       On the Host side, ensure that /etc/dhcpd.conf looks something like this
+
+               ddns-update-style ad-hoc;
+               allow bootp;
+               subnet 10.100.4.0 netmask 255.255.255.0 {
+               default-lease-time 122209600;
+               max-lease-time 31557600;
+               group {
+                       host bf533 {
+                               hardware ethernet 00:CF:52:49:C3:01;
+                               fixed-address 10.100.4.50;
+                               option root-path "/home/nfsmount";
+                       }
+               }
+
+       ensure that /etc/exports looks something like this
+               /home/nfsmount *(rw,no_root_squash,no_all_squash)
+
+        run the following commands as root (may differ depending on your
+        distribution) :
+               -  service nfs start
+               -  service portmap start
+               -  service dhcpd start
+               -  /usr/sbin/exportfs
diff --git a/Documentation/blackfin/cache-lock.txt b/Documentation/blackfin/cache-lock.txt
new file mode 100644 (file)
index 0000000..88ba1e6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * File:         Documentation/blackfin/cache-lock.txt
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Rev:          $Id: cache-lock.txt 2384 2006-11-01 04:12:43Z magicyang $
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+How to lock your code in cache in uClinux/blackfin
+--------------------------------------------------
+
+There are only a few steps required to lock your code into the cache.
+Currently you can lock the code by Way.
+
+Below are the interface provided for locking the cache.
+
+
+1. cache_grab_lock(int Ways);
+
+This function grab the lock for locking your code into the cache specified
+by Ways.
+
+
+2. cache_lock(int Ways);
+
+This function should be called after your critical code has been executed.
+Once the critical code exits, the code is now loaded into the cache. This
+function locks the code into the cache.
+
+
+So, the example sequence will be:
+
+       cache_grab_lock(WAY0_L);        /* Grab the lock */
+
+       critical_code();                /* Execute the code of interest */
+
+       cache_lock(WAY0_L);             /* Lock the cache */
+
+Where WAY0_L signifies WAY0 locking.
diff --git a/Documentation/blackfin/cachefeatures.txt b/Documentation/blackfin/cachefeatures.txt
new file mode 100644 (file)
index 0000000..0fbec23
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * File:         Documentation/blackfin/cachefeatures.txt
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Rev:          $Id: cachefeatures.txt 2384 2006-11-01 04:12:43Z magicyang $
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+       - Instruction and Data cache initialization.
+               icache_init();
+               dcache_init();
+
+       -  Instruction and Data cache Invalidation Routines, when flushing the
+          same is not required.
+               _icache_invalidate();
+               _dcache_invalidate();
+
+       Also, for invalidating the entire instruction and data cache, the below
+       routines are provided (another method for invalidation, refer page no 267 and 287 of
+       ADSP-BF533 Hardware Reference manual)
+
+               invalidate_entire_dcache();
+               invalidate_entire_icache();
+
+       -External Flushing of Instruction and data cache routines.
+
+               flush_instruction_cache();
+               flush_data_cache();
+
+       - Internal Flushing of Instruction and Data Cache.
+
+               icplb_flush();
+               dcplb_flush();
+
+       - Locking the cache.
+
+               cache_grab_lock();
+               cache_lock();
+
+       Please refer linux-2.6.x/Documentation/blackfin/cache-lock.txt for how to
+       lock the cache.
+
+       Locking the cache is optional feature.
+
+       - Miscellaneous cache functions.
+
+               flush_cache_all();
+               flush_cache_mm();
+               invalidate_dcache_range();
+               flush_dcache_range();
+               flush_dcache_page();
+               flush_cache_range();
+               flush_cache_page();
+               invalidate_dcache_range();
+               flush_page_to_ram();
+
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 7aaf09b..3f4b226 100644 (file)
@@ -122,21 +122,22 @@ subdirectory has the entries listed in Table 1-1.
 
 Table 1-1: Process specific entries in /proc 
 ..............................................................................
- File    Content                                        
- cmdline Command line arguments                         
- cpu    Current and last cpu in which it was executed          (2.4)(smp)
- cwd    Link to the current working directory
- environ Values of environment variables      
- exe    Link to the executable of this process
- fd      Directory, which contains all file descriptors 
- maps   Memory maps to executables and library files           (2.4)
- mem     Memory held by this process                    
- root   Link to the root directory of this process
- stat    Process status                                 
- statm   Process memory status information              
- status  Process status in human readable form          
- wchan   If CONFIG_KALLSYMS is set, a pre-decoded wchan
- smaps  Extension based on maps, presenting the rss size for each mapped file
+ File          Content
+ clear_refs    Clears page referenced bits shown in smaps output
+ cmdline       Command line arguments
+ cpu           Current and last cpu in which it was executed   (2.4)(smp)
+ cwd           Link to the current working directory
+ environ       Values of environment variables
+ exe           Link to the executable of this process
+ fd            Directory, which contains all file descriptors
+ maps          Memory maps to executables and library files    (2.4)
+ mem           Memory held by this process
+ root          Link to the root directory of this process
+ stat          Process status
+ statm         Process memory status information
+ status                Process status in human readable form
+ wchan         If CONFIG_KALLSYMS is set, a pre-decoded wchan
+ smaps         Extension based on maps, the rss size for each mapped file
 ..............................................................................
 
 For example, to get the status information of a process, all you have to do is
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
diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c
new file mode 100644 (file)
index 0000000..3153167
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Exercise /dev/mem mmap cases that have been troublesome in the past
+ *
+ * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
+ *     Bjorn Helgaas <bjorn.helgaas@hp.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 <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+int sum;
+
+int map_mem(char *path, off_t offset, size_t length, int touch)
+{
+       int fd, rc;
+       void *addr;
+       int *c;
+
+       fd = open(path, O_RDWR);
+       if (fd == -1) {
+               perror(path);
+               return -1;
+       }
+
+       addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
+       if (addr == MAP_FAILED)
+               return 1;
+
+       if (touch) {
+               c = (int *) addr;
+               while (c < (int *) (offset + length))
+                       sum += *c++;
+       }
+
+       rc = munmap(addr, length);
+       if (rc == -1) {
+               perror("munmap");
+               return -1;
+       }
+
+       close(fd);
+       return 0;
+}
+
+int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
+{
+       struct dirent **namelist;
+       char *name, *path2;
+       int i, n, r, rc, result = 0;
+       struct stat buf;
+
+       n = scandir(path, &namelist, 0, alphasort);
+       if (n < 0) {
+               perror("scandir");
+               return -1;
+       }
+
+       for (i = 0; i < n; i++) {
+               name = namelist[i]->d_name;
+
+               if (fnmatch(".", name, 0) == 0)
+                       goto skip;
+               if (fnmatch("..", name, 0) == 0)
+                       goto skip;
+
+               path2 = malloc(strlen(path) + strlen(name) + 3);
+               strcpy(path2, path);
+               strcat(path2, "/");
+               strcat(path2, name);
+
+               if (fnmatch(file, name, 0) == 0) {
+                       rc = map_mem(path2, offset, length, touch);
+                       if (rc == 0)
+                               fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
+                       else if (rc > 0)
+                               fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
+                       else {
+                               fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
+                               return rc;
+                       }
+               } else {
+                       r = lstat(path2, &buf);
+                       if (r == 0 && S_ISDIR(buf.st_mode)) {
+                               rc = scan_sysfs(path2, file, offset, length, touch);
+                               if (rc < 0)
+                                       return rc;
+                       }
+               }
+
+               result |= rc;
+               free(path2);
+
+skip:
+               free(namelist[i]);
+       }
+       free(namelist);
+       return rc;
+}
+
+char buf[1024];
+
+int read_rom(char *path)
+{
+       int fd, rc;
+       size_t size = 0;
+
+       fd = open(path, O_RDWR);
+       if (fd == -1) {
+               perror(path);
+               return -1;
+       }
+
+       rc = write(fd, "1", 2);
+       if (rc <= 0) {
+               perror("write");
+               return -1;
+       }
+
+       do {
+               rc = read(fd, buf, sizeof(buf));
+               if (rc > 0)
+                       size += rc;
+       } while (rc > 0);
+
+       close(fd);
+       return size;
+}
+
+int scan_rom(char *path, char *file)
+{
+       struct dirent **namelist;
+       char *name, *path2;
+       int i, n, r, rc, result = 0;
+       struct stat buf;
+
+       n = scandir(path, &namelist, 0, alphasort);
+       if (n < 0) {
+               perror("scandir");
+               return -1;
+       }
+
+       for (i = 0; i < n; i++) {
+               name = namelist[i]->d_name;
+
+               if (fnmatch(".", name, 0) == 0)
+                       goto skip;
+               if (fnmatch("..", name, 0) == 0)
+                       goto skip;
+
+               path2 = malloc(strlen(path) + strlen(name) + 3);
+               strcpy(path2, path);
+               strcat(path2, "/");
+               strcat(path2, name);
+
+               if (fnmatch(file, name, 0) == 0) {
+                       rc = read_rom(path2);
+
+                       /*
+                        * It's OK if the ROM is unreadable.  Maybe there
+                        * is no ROM, or some other error ocurred.  The
+                        * important thing is that no MCA happened.
+                        */
+                       if (rc > 0)
+                               fprintf(stderr, "PASS: %s read %ld bytes\n", path2, rc);
+                       else {
+                               fprintf(stderr, "PASS: %s not readable\n", path2);
+                               return rc;
+                       }
+               } else {
+                       r = lstat(path2, &buf);
+                       if (r == 0 && S_ISDIR(buf.st_mode)) {
+                               rc = scan_rom(path2, file);
+                               if (rc < 0)
+                                       return rc;
+                       }
+               }
+
+               result |= rc;
+               free(path2);
+
+skip:
+               free(namelist[i]);
+       }
+       free(namelist);
+       return rc;
+}
+
+main()
+{
+       int rc;
+
+       if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
+               fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
+       else
+               fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
+
+       /*
+        * It's not safe to blindly read the VGA frame buffer.  If you know
+        * how to poke the card the right way, it should respond, but it's
+        * not safe in general.  Many machines, e.g., Intel chipsets, cover
+        * up a non-responding card by just returning -1, but others will
+        * report the failure as a machine check.
+        */
+       if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
+               fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
+       else
+               fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
+
+       if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
+               fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
+       else
+               fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
+
+       /*
+        * Often you can map all the individual pieces above (0-0xA0000,
+        * 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
+        * thing at once.  This is because the individual pieces use different
+        * attributes, and there's no single attribute supported over the
+        * whole region.
+        */
+       rc = map_mem("/dev/mem", 0, 1024*1024, 0);
+       if (rc == 0)
+               fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
+       else if (rc > 0)
+               fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
+       else
+               fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
+
+       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
+       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
+       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
+       scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
+
+       scan_rom("/sys/devices", "rom");
+}
index 38f9a52..9a431a7 100644 (file)
@@ -112,16 +112,6 @@ POTENTIAL ATTRIBUTE ALIASING CASES
 
        The /dev/mem mmap constraints apply.
 
-       However, since this is for mapping legacy MMIO space, WB access
-       does not make sense.  This matters on machines without legacy
-       VGA support: these machines may have WB memory for the entire
-       first megabyte (or even the entire first granule).
-
-       On these machines, we could mmap legacy_mem as WB, which would
-       be safe in terms of attribute aliasing, but X has no way of
-       knowing that it is accessing regular memory, not a frame buffer,
-       so the kernel should fail the mmap rather than doing it with WB.
-
     read/write of /dev/mem
 
        This uses copy_from_user(), which implicitly uses a kernel
@@ -138,14 +128,20 @@ POTENTIAL ATTRIBUTE ALIASING CASES
 
     ioremap()
 
-       This returns a kernel identity mapping for use inside the
-       kernel.
+       This returns a mapping for use inside the kernel.
 
        If the region is in kern_memmap, we should use the attribute
-       specified there.  Otherwise, if the EFI memory map reports that
-       the entire granule supports WB, we should use that (granules
-       that are partially reserved or occupied by firmware do not appear
-       in kern_memmap).  Otherwise, we should use a UC mapping.
+       specified there.
+
+       If the EFI memory map reports that the entire granule supports
+       WB, we should use that (granules that are partially reserved
+       or occupied by firmware do not appear in kern_memmap).
+
+       If the granule contains non-WB memory, but we can cover the
+       region safely with kernel page table mappings, we can use
+       ioremap_page_range() as most other architectures do.
+
+       Failing all of the above, we have to fall back to a UC mapping.
 
 PAST PROBLEM CASES
 
@@ -158,7 +154,7 @@ PAST PROBLEM CASES
       succeed.  It may create either WB or UC user mappings, depending
       on whether the region is in kern_memmap or the EFI memory map.
 
-    mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
+    mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
 
       See https://bugzilla.novell.com/show_bug.cgi?id=140858.
 
@@ -171,28 +167,25 @@ PAST PROBLEM CASES
       so it is safe to use WB mappings.
 
       The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
-      which will use a granule-sized UC mapping covering 0-0xFFFFF.  This
-      granule covers some WB-only memory, but since UC is non-speculative,
-      the processor will never generate an uncacheable reference to the
-      WB-only areas unless the driver explicitly touches them.
+      which uses a granule-sized UC mapping.  This granule will cover some
+      WB-only memory, but since UC is non-speculative, the processor will
+      never generate an uncacheable reference to the WB-only areas unless
+      the driver explicitly touches them.
 
     mmap of 0x0-0xFFFFF legacy_mem by "X"
 
-      If the EFI memory map reports this entire range as WB, there
-      is no VGA MMIO hole, and the mmap should fail or be done with
-      a WB mapping.
+      If the EFI memory map reports that the entire range supports the
+      same attributes, we can allow the mmap (and we will prefer WB if
+      supported, as is the case with HP sx[12]000 machines with VGA
+      disabled).
 
-      There's no easy way for X to determine whether the 0xA0000-0xBFFFF
-      region is a frame buffer or just memory, so I think it's best to
-      just fail this mmap request rather than using a WB mapping.  As
-      far as I know, there's no need to map legacy_mem with WB
-      mappings.
+      If EFI reports the range as partly WB and partly UC (as on sx[12]000
+      machines with VGA enabled), we must fail the mmap because there's no
+      safe attribute to use.
 
-      Otherwise, a UC mapping of the entire region is probably safe.
-      The VGA hole means the region will not be in kern_memmap.  The
-      HP sx1000 chipset doesn't support UC access to the memory surrounding
-      the VGA hole, but X doesn't need that area anyway and should not
-      reference it.
+      If EFI reports some of the range but not all (as on Intel firmware
+      that doesn't report the VGA frame buffer at all), we should fail the
+      mmap and force the user to map just the specific region of interest.
 
     mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
 
@@ -202,6 +195,16 @@ PAST PROBLEM CASES
       This is a special case of the previous case, and the mmap should
       fail for the same reason as above.
 
+    read of /sys/devices/.../rom
+
+      For VGA devices, this may cause an ioremap() of 0xC0000.  This
+      used to be done with a UC mapping, because the VGA frame buffer
+      at 0xA0000 prevents use of a WB granule.  The UC mapping causes
+      an MCA on HP sx[12]000 chipsets.
+
+      We should use WB page table mappings to avoid covering the VGA
+      frame buffer.
+
 NOTES
 
     [1] SDM rev 2.2, vol 2, sec 4.4.1.
diff --git a/Documentation/ia64/err_inject.txt b/Documentation/ia64/err_inject.txt
new file mode 100644 (file)
index 0000000..6449a70
--- /dev/null
@@ -0,0 +1,1068 @@
+
+IPF Machine Check (MC) error inject tool
+========================================
+
+IPF Machine Check (MC) error inject tool is used to inject MC
+errors from Linux. The tool is a test bed for IPF MC work flow including
+hardware correctable error handling, OS recoverable error handling, MC
+event logging, etc.
+
+The tool includes two parts: a kernel driver and a user application
+sample. The driver provides interface to PAL to inject error
+and query error injection capabilities. The driver code is in
+arch/ia64/kernel/err_inject.c. The application sample (shown below)
+provides a combination of various errors and calls the driver's interface
+(sysfs interface) to inject errors or query error injection capabilities.
+
+The tool can be used to test Intel IPF machine MC handling capabilities.
+It's especially useful for people who can not access hardware MC injection
+tool to inject error. It's also very useful to integrate with other
+software test suits to do stressful testing on IPF.
+
+Below is a sample application as part of the whole tool. The sample
+can be used as a working test tool. Or it can be expanded to include
+more features. It also can be a integrated into a libary or other user
+application to have more thorough test.
+
+The sample application takes err.conf as error configuation input. Gcc
+compiles the code. After you install err_inject driver, you can run
+this sample application to inject errors.
+
+Errata: Itanium 2 Processors Specification Update lists some errata against
+the pal_mc_error_inject PAL procedure. The following err.conf has been tested
+on latest Montecito PAL.
+
+err.conf:
+
+#This is configuration file for err_inject_tool.
+#The format of the each line is:
+#cpu, loop, interval, err_type_info, err_struct_info, err_data_buffer
+#where
+#      cpu: logical cpu number the error will be inject in.
+#      loop: times the error will be injected.
+#      interval: In second. every so often one error is injected.
+#      err_type_info, err_struct_info: PAL parameters.
+#
+#Note: All values are hex w/o or w/ 0x prefix.
+
+
+#On cpu2, inject only total 0x10 errors, interval 5 seconds
+#corrected, data cache, hier-2, physical addr(assigned by tool code).
+#working on Montecito latest PAL.
+2, 10, 5, 4101, 95
+
+#On cpu4, inject and consume total 0x10 errors, interval 5 seconds
+#corrected, data cache, hier-2, physical addr(assigned by tool code).
+#working on Montecito latest PAL.
+4, 10, 5, 4109, 95
+
+#On cpu15, inject and consume total 0x10 errors, interval 5 seconds
+#recoverable, DTR0, hier-2.
+#working on Montecito latest PAL.
+0xf, 0x10, 5, 4249, 15
+
+The sample application source code:
+
+err_injection_tool.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, 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.
+ *
+ * Copyright (C) 2006 Intel Co
+ *     Fenghua Yu <fenghua.yu@intel.com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sched.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+
+#define MAX_FN_SIZE            256
+#define MAX_BUF_SIZE           256
+#define DATA_BUF_SIZE          256
+#define NR_CPUS                512
+#define MAX_TASK_NUM           2048
+#define MIN_INTERVAL           5       // seconds
+#define        ERR_DATA_BUFFER_SIZE    3       // Three 8-byte.
+#define PARA_FIELD_NUM         5
+#define MASK_SIZE              (NR_CPUS/64)
+#define PATH_FORMAT "/sys/devices/system/cpu/cpu%d/err_inject/"
+
+int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);
+
+int verbose;
+#define vbprintf if (verbose) printf
+
+int log_info(int cpu, const char *fmt, ...)
+{
+       FILE *log;
+       char fn[MAX_FN_SIZE];
+       char buf[MAX_BUF_SIZE];
+       va_list args;
+
+       sprintf(fn, "%d.log", cpu);
+       log=fopen(fn, "a+");
+       if (log==NULL) {
+               perror("Error open:");
+               return -1;
+       }
+
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       memset(buf, 0, MAX_BUF_SIZE);
+       vsprintf(buf, fmt, args);
+       va_end(args);
+
+       fwrite(buf, sizeof(buf), 1, log);
+       fclose(log);
+
+       return 0;
+}
+
+typedef unsigned long u64;
+typedef unsigned int  u32;
+
+typedef union err_type_info_u {
+       struct {
+               u64     mode            : 3,    /* 0-2 */
+                       err_inj         : 3,    /* 3-5 */
+                       err_sev         : 2,    /* 6-7 */
+                       err_struct      : 5,    /* 8-12 */
+                       struct_hier     : 3,    /* 13-15 */
+                       reserved        : 48;   /* 16-63 */
+       } err_type_info_u;
+       u64     err_type_info;
+} err_type_info_t;
+
+typedef union err_struct_info_u {
+       struct {
+               u64     siv             : 1,    /* 0     */
+                       c_t             : 2,    /* 1-2   */
+                       cl_p            : 3,    /* 3-5   */
+                       cl_id           : 3,    /* 6-8   */
+                       cl_dp           : 1,    /* 9     */
+                       reserved1       : 22,   /* 10-31 */
+                       tiv             : 1,    /* 32    */
+                       trigger         : 4,    /* 33-36 */
+                       trigger_pl      : 3,    /* 37-39 */
+                       reserved2       : 24;   /* 40-63 */
+       } err_struct_info_cache;
+       struct {
+               u64     siv             : 1,    /* 0     */
+                       tt              : 2,    /* 1-2   */
+                       tc_tr           : 2,    /* 3-4   */
+                       tr_slot         : 8,    /* 5-12  */
+                       reserved1       : 19,   /* 13-31 */
+                       tiv             : 1,    /* 32    */
+                       trigger         : 4,    /* 33-36 */
+                       trigger_pl      : 3,    /* 37-39 */
+                       reserved2       : 24;   /* 40-63 */
+       } err_struct_info_tlb;
+       struct {
+               u64     siv             : 1,    /* 0     */
+                       regfile_id      : 4,    /* 1-4   */
+                       reg_num         : 7,    /* 5-11  */
+                       reserved1       : 20,   /* 12-31 */
+                       tiv             : 1,    /* 32    */
+                       trigger         : 4,    /* 33-36 */
+                       trigger_pl      : 3,    /* 37-39 */
+                       reserved2       : 24;   /* 40-63 */
+       } err_struct_info_register;
+       struct {
+               u64     reserved;
+       } err_struct_info_bus_processor_interconnect;
+       u64     err_struct_info;
+} err_struct_info_t;
+
+typedef union err_data_buffer_u {
+       struct {
+               u64     trigger_addr;           /* 0-63         */
+               u64     inj_addr;               /* 64-127       */
+               u64     way             : 5,    /* 128-132      */
+                       index           : 20,   /* 133-152      */
+                                       : 39;   /* 153-191      */
+       } err_data_buffer_cache;
+       struct {
+               u64     trigger_addr;           /* 0-63         */
+               u64     inj_addr;               /* 64-127       */
+               u64     way             : 5,    /* 128-132      */
+                       index           : 20,   /* 133-152      */
+                       reserved        : 39;   /* 153-191      */
+       } err_data_buffer_tlb;
+       struct {
+               u64     trigger_addr;           /* 0-63         */
+       } err_data_buffer_register;
+       struct {
+               u64     reserved;               /* 0-63         */
+       } err_data_buffer_bus_processor_interconnect;
+       u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
+} err_data_buffer_t;
+
+typedef union capabilities_u {
+       struct {
+               u64     i               : 1,
+                       d               : 1,
+                       rv              : 1,
+                       tag             : 1,
+                       data            : 1,
+                       mesi            : 1,
+                       dp              : 1,
+                       reserved1       : 3,
+                       pa              : 1,
+                       va              : 1,
+                       wi              : 1,
+                       reserved2       : 20,
+                       trigger         : 1,
+                       trigger_pl      : 1,
+                       reserved3       : 30;
+       } capabilities_cache;
+       struct {
+               u64     d               : 1,
+                       i               : 1,
+                       rv              : 1,
+                       tc              : 1,
+                       tr              : 1,
+                       reserved1       : 27,
+                       trigger         : 1,
+                       trigger_pl      : 1,
+                       reserved2       : 30;
+       } capabilities_tlb;
+       struct {
+               u64     gr_b0           : 1,
+                       gr_b1           : 1,
+                       fr              : 1,
+                       br              : 1,
+                       pr              : 1,
+                       ar              : 1,
+                       cr              : 1,
+                       rr              : 1,
+                       pkr             : 1,
+                       dbr             : 1,
+                       ibr             : 1,
+                       pmc             : 1,
+                       pmd             : 1,
+                       reserved1       : 3,
+                       regnum          : 1,
+                       reserved2       : 15,
+                       trigger         : 1,
+                       trigger_pl      : 1,
+                       reserved3       : 30;
+       } capabilities_register;
+       struct {
+               u64     reserved;
+       } capabilities_bus_processor_interconnect;
+} capabilities_t;
+
+typedef struct resources_s {
+       u64     ibr0            : 1,
+               ibr2            : 1,
+               ibr4            : 1,
+               ibr6            : 1,
+               dbr0            : 1,
+               dbr2            : 1,
+               dbr4            : 1,
+               dbr6            : 1,
+               reserved        : 48;
+} resources_t;
+
+
+long get_page_size(void)
+{
+       long page_size=sysconf(_SC_PAGESIZE);
+       return page_size;
+}
+
+#define PAGE_SIZE (get_page_size()==-1?0x4000:get_page_size())
+#define SHM_SIZE (2*PAGE_SIZE*NR_CPUS)
+#define SHM_VA 0x2000000100000000
+
+int shmid;
+void *shmaddr;
+
+int create_shm(void)
+{
+       key_t key;
+       char fn[MAX_FN_SIZE];
+
+       /* cpu0 is always existing */
+       sprintf(fn, PATH_FORMAT, 0);
+       if ((key = ftok(fn, 's')) == -1) {
+               perror("ftok");
+               return -1;
+       }
+
+       shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
+       if (shmid == -1) {
+               if (errno==EEXIST) {
+                       shmid = shmget(key, SHM_SIZE, 0);
+                       if (shmid == -1) {
+                               perror("shmget");
+                               return -1;
+                       }
+               }
+               else {
+                       perror("shmget");
+                       return -1;
+               }
+       }
+       vbprintf("shmid=%d", shmid);
+
+       /* connect to the segment: */
+       shmaddr = shmat(shmid, (void *)SHM_VA, 0);
+       if (shmaddr == (void*)-1) {
+               perror("shmat");
+               return -1;
+       }
+
+       memset(shmaddr, 0, SHM_SIZE);
+       mlock(shmaddr, SHM_SIZE);
+
+       return 0;
+}
+
+int free_shm()
+{
+       munlock(shmaddr, SHM_SIZE);
+        shmdt(shmaddr);
+       semctl(shmid, 0, IPC_RMID);
+
+       return 0;
+}
+
+#ifdef _SEM_SEMUN_UNDEFINED
+union semun
+{
+       int val;
+       struct semid_ds *buf;
+       unsigned short int *array;
+       struct seminfo *__buf;
+};
+#endif
+
+u32 mode=1; /* 1: physical mode; 2: virtual mode. */
+int one_lock=1;
+key_t key[NR_CPUS];
+int semid[NR_CPUS];
+
+int create_sem(int cpu)
+{
+       union semun arg;
+       char fn[MAX_FN_SIZE];
+       int sid;
+
+       sprintf(fn, PATH_FORMAT, cpu);
+       sprintf(fn, "%s/%s", fn, "err_type_info");
+       if ((key[cpu] = ftok(fn, 'e')) == -1) {
+               perror("ftok");
+               return -1;
+       }
+
+       if (semid[cpu]!=0)
+               return 0;
+
+       /* clear old semaphore */
+       if ((sid = semget(key[cpu], 1, 0)) != -1)
+               semctl(sid, 0, IPC_RMID);
+
+       /* get one semaphore */
+       if ((semid[cpu] = semget(key[cpu], 1, IPC_CREAT | IPC_EXCL)) == -1) {
+               perror("semget");
+               printf("Please remove semaphore with key=0x%lx, then run the tool.\n",
+                       (u64)key[cpu]);
+               return -1;
+       }
+
+       vbprintf("semid[%d]=0x%lx, key[%d]=%lx\n",cpu,(u64)semid[cpu],cpu,
+               (u64)key[cpu]);
+       /* initialize the semaphore to 1: */
+       arg.val = 1;
+       if (semctl(semid[cpu], 0, SETVAL, arg) == -1) {
+               perror("semctl");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int lock(int cpu)
+{
+       struct sembuf lock;
+
+       lock.sem_num = cpu;
+       lock.sem_op = 1;
+       semop(semid[cpu], &lock, 1);
+
+        return 0;
+}
+
+static int unlock(int cpu)
+{
+       struct sembuf unlock;
+
+       unlock.sem_num = cpu;
+       unlock.sem_op = -1;
+       semop(semid[cpu], &unlock, 1);
+
+        return 0;
+}
+
+void free_sem(int cpu)
+{
+       semctl(semid[cpu], 0, IPC_RMID);
+}
+
+int wr_multi(char *fn, unsigned long *data, int size)
+{
+       int fd;
+       char buf[MAX_BUF_SIZE];
+       int ret;
+
+       if (size==1)
+               sprintf(buf, "%lx", *data);
+       else if (size==3)
+               sprintf(buf, "%lx,%lx,%lx", data[0], data[1], data[2]);
+       else {
+               fprintf(stderr,"write to file with wrong size!\n");
+               return -1;
+       }
+
+       fd=open(fn, O_RDWR);
+       if (!fd) {
+               perror("Error:");
+               return -1;
+       }
+       ret=write(fd, buf, sizeof(buf));
+       close(fd);
+       return ret;
+}
+
+int wr(char *fn, unsigned long data)
+{
+       return wr_multi(fn, &data, 1);
+}
+
+int rd(char *fn, unsigned long *data)
+{
+       int fd;
+       char buf[MAX_BUF_SIZE];
+
+       fd=open(fn, O_RDONLY);
+       if (fd<0) {
+               perror("Error:");
+               return -1;
+       }
+       read(fd, buf, MAX_BUF_SIZE);
+       *data=strtoul(buf, NULL, 16);
+       close(fd);
+       return 0;
+}
+
+int rd_status(char *path, int *status)
+{
+       char fn[MAX_FN_SIZE];
+       sprintf(fn, "%s/status", path);
+       if (rd(fn, (u64*)status)<0) {
+               perror("status reading error.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int rd_capabilities(char *path, u64 *capabilities)
+{
+       char fn[MAX_FN_SIZE];
+       sprintf(fn, "%s/capabilities", path);
+       if (rd(fn, capabilities)<0) {
+               perror("capabilities reading error.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int rd_all(char *path)
+{
+       unsigned long err_type_info, err_struct_info, err_data_buffer;
+       int status;
+       unsigned long capabilities, resources;
+       char fn[MAX_FN_SIZE];
+
+       sprintf(fn, "%s/err_type_info", path);
+       if (rd(fn, &err_type_info)<0) {
+               perror("err_type_info reading error.\n");
+               return -1;
+       }
+       printf("err_type_info=%lx\n", err_type_info);
+
+       sprintf(fn, "%s/err_struct_info", path);
+       if (rd(fn, &err_struct_info)<0) {
+               perror("err_struct_info reading error.\n");
+               return -1;
+       }
+       printf("err_struct_info=%lx\n", err_struct_info);
+
+       sprintf(fn, "%s/err_data_buffer", path);
+       if (rd(fn, &err_data_buffer)<0) {
+               perror("err_data_buffer reading error.\n");
+               return -1;
+       }
+       printf("err_data_buffer=%lx\n", err_data_buffer);
+
+       sprintf(fn, "%s/status", path);
+       if (rd("status", (u64*)&status)<0) {
+               perror("status reading error.\n");
+               return -1;
+       }
+       printf("status=%d\n", status);
+
+       sprintf(fn, "%s/capabilities", path);
+       if (rd(fn,&capabilities)<0) {
+               perror("capabilities reading error.\n");
+               return -1;
+       }
+       printf("capabilities=%lx\n", capabilities);
+
+       sprintf(fn, "%s/resources", path);
+       if (rd(fn, &resources)<0) {
+               perror("resources reading error.\n");
+               return -1;
+       }
+       printf("resources=%lx\n", resources);
+
+       return 0;
+}
+
+int query_capabilities(char *path, err_type_info_t err_type_info,
+                       u64 *capabilities)
+{
+       char fn[MAX_FN_SIZE];
+       err_struct_info_t err_struct_info;
+       err_data_buffer_t err_data_buffer;
+
+       err_struct_info.err_struct_info=0;
+       memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8);
+
+       sprintf(fn, "%s/err_type_info", path);
+       wr(fn, err_type_info.err_type_info);
+       sprintf(fn, "%s/err_struct_info", path);
+       wr(fn, 0x0);
+       sprintf(fn, "%s/err_data_buffer", path);
+       wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
+
+       // Fire pal_mc_error_inject procedure.
+       sprintf(fn, "%s/call_start", path);
+       wr(fn, mode);
+
+       if (rd_capabilities(path, capabilities)<0)
+               return -1;
+
+       return 0;
+}
+
+int query_all_capabilities()
+{
+       int status;
+       err_type_info_t err_type_info;
+       int err_sev, err_struct, struct_hier;
+       int cap=0;
+       u64 capabilities;
+       char path[MAX_FN_SIZE];
+
+       err_type_info.err_type_info=0;                  // Initial
+       err_type_info.err_type_info_u.mode=0;           // Query mode;
+       err_type_info.err_type_info_u.err_inj=0;
+
+       printf("All capabilities implemented in pal_mc_error_inject:\n");
+       sprintf(path, PATH_FORMAT ,0);
+       for (err_sev=0;err_sev<3;err_sev++)
+               for (err_struct=0;err_struct<5;err_struct++)
+                       for (struct_hier=0;struct_hier<5;struct_hier++)
+       {
+               status=-1;
+               capabilities=0;
+               err_type_info.err_type_info_u.err_sev=err_sev;
+               err_type_info.err_type_info_u.err_struct=err_struct;
+               err_type_info.err_type_info_u.struct_hier=struct_hier;
+
+               if (query_capabilities(path, err_type_info, &capabilities)<0)
+                       continue;
+
+               if (rd_status(path, &status)<0)
+                       continue;
+
+               if (status==0) {
+                       cap=1;
+                       printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ",
+                               err_sev, err_struct, struct_hier);
+                       printf("capabilities 0x%lx\n", capabilities);
+               }
+       }
+       if (!cap) {
+               printf("No capabilities supported.\n");
+               return 0;
+       }
+
+       return 0;
+}
+
+int err_inject(int cpu, char *path, err_type_info_t err_type_info,
+               err_struct_info_t err_struct_info,
+               err_data_buffer_t err_data_buffer)
+{
+       int status;
+       char fn[MAX_FN_SIZE];
+
+       log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ",
+               err_type_info.err_type_info,
+               err_struct_info.err_struct_info);
+       log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n",
+               err_data_buffer.err_data_buffer[0],
+               err_data_buffer.err_data_buffer[1],
+               err_data_buffer.err_data_buffer[2]);
+       sprintf(fn, "%s/err_type_info", path);
+       wr(fn, err_type_info.err_type_info);
+       sprintf(fn, "%s/err_struct_info", path);
+       wr(fn, err_struct_info.err_struct_info);
+       sprintf(fn, "%s/err_data_buffer", path);
+       wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
+
+       // Fire pal_mc_error_inject procedure.
+       sprintf(fn, "%s/call_start", path);
+       wr(fn,mode);
+
+       if (rd_status(path, &status)<0) {
+               vbprintf("fail: read status\n");
+               return -100;
+       }
+
+       if (status!=0) {
+               log_info(cpu, "fail: status=%d\n", status);
+               return status;
+       }
+
+       return status;
+}
+
+static int construct_data_buf(char *path, err_type_info_t err_type_info,
+               err_struct_info_t err_struct_info,
+               err_data_buffer_t *err_data_buffer,
+               void *va1)
+{
+       char fn[MAX_FN_SIZE];
+       u64 virt_addr=0, phys_addr=0;
+
+       vbprintf("va1=%lx\n", (u64)va1);
+       memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8);
+
+       switch (err_type_info.err_type_info_u.err_struct) {
+               case 1: // Cache
+                       switch (err_struct_info.err_struct_info_cache.cl_id) {
+                               case 1: //Virtual addr
+                                       err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1;
+                                       break;
+                               case 2: //Phys addr
+                                       sprintf(fn, "%s/virtual_to_phys", path);
+                                       virt_addr=(u64)va1;
+                                       if (wr(fn,virt_addr)<0)
+                                               return -1;
+                                       rd(fn, &phys_addr);
+                                       err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr;
+                                       break;
+                               default:
+                                       printf("Not supported cl_id\n");
+                                       break;
+                       }
+                       break;
+               case 2: //  TLB
+                       break;
+               case 3: //  Register file
+                       break;
+               case 4: //  Bus/system interconnect
+               default:
+                       printf("Not supported err_struct\n");
+                       break;
+       }
+
+       return 0;
+}
+
+typedef struct {
+       u64 cpu;
+       u64 loop;
+       u64 interval;
+       u64 err_type_info;
+       u64 err_struct_info;
+       u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
+} parameters_t;
+
+parameters_t line_para;
+int para;
+
+static int empty_data_buffer(u64 *err_data_buffer)
+{
+       int empty=1;
+       int i;
+
+       for (i=0;i<ERR_DATA_BUFFER_SIZE; i++)
+          if (err_data_buffer[i]!=-1)
+               empty=0;
+
+       return empty;
+}
+
+int err_inj()
+{
+       err_type_info_t err_type_info;
+       err_struct_info_t err_struct_info;
+       err_data_buffer_t err_data_buffer;
+       int count;
+       FILE *fp;
+       unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf;
+       u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE];
+       int num;
+       int i;
+       char path[MAX_FN_SIZE];
+       parameters_t parameters[MAX_TASK_NUM]={};
+       pid_t child_pid[MAX_TASK_NUM];
+       time_t current_time;
+       int status;
+
+       if (!para) {
+           fp=fopen("err.conf", "r");
+           if (fp==NULL) {
+               perror("Error open err.conf");
+               return -1;
+           }
+
+           num=0;
+           while (!feof(fp)) {
+               char buf[256];
+               memset(buf,0,256);
+               fgets(buf, 256, fp);
+               count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
+                               &cpu, &loop, &interval,&err_type_info_conf,
+                               &err_struct_info_conf,
+                               &err_data_buffer_conf[0],
+                               &err_data_buffer_conf[1],
+                               &err_data_buffer_conf[2]);
+               if (count!=PARA_FIELD_NUM+3) {
+                       err_data_buffer_conf[0]=-1;
+                       err_data_buffer_conf[1]=-1;
+                       err_data_buffer_conf[2]=-1;
+                       count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n",
+                               &cpu, &loop, &interval,&err_type_info_conf,
+                               &err_struct_info_conf);
+                       if (count!=PARA_FIELD_NUM)
+                               continue;
+               }
+
+               parameters[num].cpu=cpu;
+               parameters[num].loop=loop;
+               parameters[num].interval= interval>MIN_INTERVAL
+                                         ?interval:MIN_INTERVAL;
+               parameters[num].err_type_info=err_type_info_conf;
+               parameters[num].err_struct_info=err_struct_info_conf;
+               memcpy(parameters[num++].err_data_buffer,
+                       err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ;
+
+               if (num>=MAX_TASK_NUM)
+                       break;
+           }
+       }
+       else {
+               parameters[0].cpu=line_para.cpu;
+               parameters[0].loop=line_para.loop;
+               parameters[0].interval= line_para.interval>MIN_INTERVAL
+                                         ?line_para.interval:MIN_INTERVAL;
+               parameters[0].err_type_info=line_para.err_type_info;
+               parameters[0].err_struct_info=line_para.err_struct_info;
+               memcpy(parameters[0].err_data_buffer,
+                       line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ;
+
+               num=1;
+       }
+
+       /* Create semaphore: If one_lock, one semaphore for all processors.
+          Otherwise, one sempaphore for each processor. */
+       if (one_lock) {
+               if (create_sem(0)) {
+                       printf("Can not create semaphore...exit\n");
+                       free_sem(0);
+                       return -1;
+               }
+       }
+       else {
+               for (i=0;i<num;i++) {
+                  if (create_sem(parameters[i].cpu)) {
+                       printf("Can not create semaphore for cpu%d...exit\n",i);
+                       free_sem(parameters[num].cpu);
+                       return -1;
+                  }
+               }
+       }
+
+       /* Create a shm segment which will be used to inject/consume errors on.*/
+       if (create_shm()==-1) {
+               printf("Error to create shm...exit\n");
+               return -1;
+       }
+
+       for (i=0;i<num;i++) {
+               pid_t pid;
+
+               current_time=time(NULL);
+               log_info(parameters[i].cpu, "\nBegine at %s", ctime(&current_time));
+               log_info(parameters[i].cpu, "Configurations:\n");
+               log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)",
+                       parameters[i].cpu,
+                       parameters[i].loop,
+                       parameters[i].interval);
+               log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n",
+                       parameters[i].err_type_info,
+                       parameters[i].err_struct_info);
+
+               sprintf(path, PATH_FORMAT, (int)parameters[i].cpu);
+               err_type_info.err_type_info=parameters[i].err_type_info;
+               err_struct_info.err_struct_info=parameters[i].err_struct_info;
+               memcpy(err_data_buffer.err_data_buffer,
+                       parameters[i].err_data_buffer,
+                       ERR_DATA_BUFFER_SIZE*8);
+
+               pid=fork();
+               if (pid==0) {
+                       unsigned long mask[MASK_SIZE];
+                       int j, k;
+
+                       void *va1, *va2;
+
+                       /* Allocate two memory areas va1 and va2 in shm */
+                       va1=shmaddr+parameters[i].cpu*PAGE_SIZE;
+                       va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE;
+
+                       vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2);
+                       memset(va1, 0x1, PAGE_SIZE);
+                       memset(va2, 0x2, PAGE_SIZE);
+
+                       if (empty_data_buffer(err_data_buffer.err_data_buffer))
+                               /* If not specified yet, construct data buffer
+                                * with va1
+                                */
+                               construct_data_buf(path, err_type_info,
+                                       err_struct_info, &err_data_buffer,va1);
+
+                       for (j=0;j<MASK_SIZE;j++)
+                               mask[j]=0;
+
+                       cpu=parameters[i].cpu;
+                       k = cpu%64;
+                       j = cpu/64;
+                       mask[j]=1<<k;
+
+                       if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
+                               perror("Error sched_setaffinity:");
+                               return -1;
+                       }
+
+                       for (j=0; j<parameters[i].loop; j++) {
+                               log_info(parameters[i].cpu,"Injection ");
+                               log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ",
+
+                                       parameters[i].cpu,j+1, parameters[i].loop);
+
+                               /* Hold the lock */
+                               if (one_lock)
+                                       lock(0);
+                               else
+                               /* Hold lock on this cpu */
+                                       lock(parameters[i].cpu);
+
+                               if ((status=err_inject(parameters[i].cpu,
+                                          path, err_type_info,
+                                          err_struct_info, err_data_buffer))
+                                          ==0) {
+                                       /* consume the error for "inject only"*/
+                                       memcpy(va2, va1, PAGE_SIZE);
+                                       memcpy(va1, va2, PAGE_SIZE);
+                                       log_info(parameters[i].cpu,
+                                               "successful\n");
+                               }
+                               else {
+                                       log_info(parameters[i].cpu,"fail:");
+                                       log_info(parameters[i].cpu,
+                                               "status=%d\n", status);
+                                       unlock(parameters[i].cpu);
+                                       break;
+                               }
+                               if (one_lock)
+                               /* Release the lock */
+                                       unlock(0);
+                               /* Release lock on this cpu */
+                               else
+                                       unlock(parameters[i].cpu);
+
+                               if (j < parameters[i].loop-1)
+                                       sleep(parameters[i].interval);
+                       }
+                       current_time=time(NULL);
+                       log_info(parameters[i].cpu, "Done at %s", ctime(&current_time));
+                       return 0;
+               }
+               else if (pid<0) {
+                       perror("Error fork:");
+                       continue;
+               }
+               child_pid[i]=pid;
+       }
+       for (i=0;i<num;i++)
+               waitpid(child_pid[i], NULL, 0);
+
+       if (one_lock)
+               free_sem(0);
+       else
+               for (i=0;i<num;i++)
+                       free_sem(parameters[i].cpu);
+
+       printf("All done.\n");
+
+       return 0;
+}
+
+void help()
+{
+       printf("err_inject_tool:\n");
+       printf("\t-q: query all capabilities. default: off\n");
+       printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n");
+       printf("\t-i: inject errors. default: off\n");
+       printf("\t-l: one lock per cpu. default: one lock for all\n");
+       printf("\t-e: error parameters:\n");
+       printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n");
+       printf("\t\t   cpu: logical cpu number the error will be inject in.\n");
+       printf("\t\t   loop: times the error will be injected.\n");
+       printf("\t\t   interval: In second. every so often one error is injected.\n");
+       printf("\t\t   err_type_info, err_struct_info: PAL parameters.\n");
+       printf("\t\t   err_data_buffer: PAL parameter. Optional. If not present,\n");
+       printf("\t\t                    it's constructed by tool automatically. Be\n");
+       printf("\t\t                    careful to provide err_data_buffer and make\n");
+       printf("\t\t                    sure it's working with the environment.\n");
+       printf("\t    Note:no space between error parameters.\n");
+       printf("\t    default: Take error parameters from err.conf instead of command line.\n");
+       printf("\t-v: verbose. default: off\n");
+       printf("\t-h: help\n\n");
+       printf("The tool will take err.conf file as ");
+       printf("input to inject single or multiple errors ");
+       printf("on one or multiple cpus in parallel.\n");
+}
+
+int main(int argc, char **argv)
+{
+       char c;
+       int do_err_inj=0;
+       int do_query_all=0;
+       int count;
+       u32 m;
+
+       /* Default one lock for all cpu's */
+       one_lock=1;
+       while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF)
+               switch (c) {
+                       case 'm':       /* Procedure mode. 1: phys 2: virt */
+                               count=sscanf(optarg, "%x", &m);
+                               if (count!=1 || (m!=1 && m!=2)) {
+                                       printf("Wrong mode number.\n");
+                                       help();
+                                       return -1;
+                               }
+                               mode=m;
+                               break;
+                       case 'i':       /* Inject errors */
+                               do_err_inj=1;
+                               break;
+                       case 'q':       /* Query */
+                               do_query_all=1;
+                               break;
+                       case 'v':       /* Verbose */
+                               verbose=1;
+                               break;
+                       case 'l':       /* One lock per cpu */
+                               one_lock=0;
+                               break;
+                       case 'e':       /* error arguments */
+                               /* Take parameters:
+                                * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer]
+                                * err_data_buffer is optional. Recommend not to specify
+                                * err_data_buffer. Better to use tool to generate it.
+                                */
+                               count=sscanf(optarg,
+                                       "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
+                                       &line_para.cpu,
+                                       &line_para.loop,
+                                       &line_para.interval,
+                                       &line_para.err_type_info,
+                                       &line_para.err_struct_info,
+                                       &line_para.err_data_buffer[0],
+                                       &line_para.err_data_buffer[1],
+                                       &line_para.err_data_buffer[2]);
+                               if (count!=PARA_FIELD_NUM+3) {
+                                   line_para.err_data_buffer[0]=-1,
+                                   line_para.err_data_buffer[1]=-1,
+                                   line_para.err_data_buffer[2]=-1;
+                                   count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n",
+                                               &line_para.cpu,
+                                               &line_para.loop,
+                                               &line_para.interval,
+                                               &line_para.err_type_info,
+                                               &line_para.err_struct_info);
+                                   if (count!=PARA_FIELD_NUM) {
+                                       printf("Wrong error arguments.\n");
+                                       help();
+                                       return -1;
+                                   }
+                               }
+                               para=1;
+                               break;
+                       continue;
+                               break;
+                       case 'h':
+                               help();
+                               return 0;
+                       default:
+                               break;
+               }
+
+       if (do_query_all)
+               query_all_capabilities();
+       if (do_err_inj)
+               err_inj();
+
+       if (!do_query_all &&  !do_err_inj)
+               help();
+
+       return 0;
+}
+
index 769ee05..1d247d5 100644 (file)
@@ -249,7 +249,7 @@ following files:
                --> filename: Makefile
                KERNELDIR := /lib/modules/`uname -r`/build
                all::
-                       $(MAKE) -C $KERNELDIR M=`pwd` $@
+                       $(MAKE) -C $(KERNELDIR) M=`pwd` $@
 
                # Module specific targets
                genbin:
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
diff --git a/Documentation/pcmcia/driver.txt b/Documentation/pcmcia/driver.txt
new file mode 100644 (file)
index 0000000..0ac1679
--- /dev/null
@@ -0,0 +1,30 @@
+PCMCIA Driver
+-------------
+
+
+sysfs
+-----
+
+New PCMCIA IDs may be added to a device driver pcmcia_device_id table at
+runtime as shown below:
+
+echo "match_flags manf_id card_id func_id function device_no \
+prod_id_hash[0] prod_id_hash[1] prod_id_hash[2] prod_id_hash[3]" > \
+/sys/bus/pcmcia/drivers/{driver}/new_id
+
+All fields are passed in as hexadecimal values (no leading 0x).
+The meaning is described in the PCMCIA specification, the match_flags is
+a bitwise or-ed combination from PCMCIA_DEV_ID_MATCH_* constants
+defined in include/linux/mod_devicetable.h.
+
+Once added, the driver probe routine will be invoked for any unclaimed
+PCMCIA device listed in its (newly updated) pcmcia_device_id list.
+
+A common use-case is to add a new device according to the manufacturer ID
+and the card ID (form the manf_id and card_id file in the device tree).
+For this, just use:
+
+echo "0x3 manf_id card_id 0 0 0 0 0 0 0" > \
+        /sys/bus/pcmcia/drivers/{driver}/new_id
+
+after loading the driver.
index 8c5b41b..fd5192a 100644 (file)
@@ -34,8 +34,12 @@ for 5 seconds, resume devices, unfreeze tasks and enable nonboot CPUs.  Then,
 we are able to look in the log messages and work out, for example, which code
 is being slow and which device drivers are misbehaving.
 
-Reading from this file will display what the mode is currently set
-to. Writing to this file will accept one of
+Reading from this file will display all supported modes and the currently
+selected one in brackets, for example
+
+       [shutdown] reboot test testproc
+
+Writing to this file will accept one of
 
        'platform' (only if the platform supports it)
        'shutdown'
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
diff --git a/Documentation/sh/clk.txt b/Documentation/sh/clk.txt
new file mode 100644 (file)
index 0000000..9aef710
--- /dev/null
@@ -0,0 +1,32 @@
+Clock framework on SuperH architecture
+
+The framework on SH extends existing API by the function clk_set_rate_ex,
+which prototype is as follows:
+
+    clk_set_rate_ex (struct clk *clk, unsigned long rate, int algo_id)
+
+The algo_id parameter is used to specify algorithm used to recalculate clocks,
+adjanced to clock, specified as first argument. It is assumed that algo_id==0
+means no changes to adjanced clock
+
+Internally, the clk_set_rate_ex forwards request to clk->ops->set_rate method,
+if it is present in ops structure. The method should set the clock rate and adjust
+all needed clocks according to the passed algo_id.
+Exact values for algo_id are machine-dependend. For the sh7722, the following
+values are defined:
+
+       NO_CHANGE       = 0,
+       IUS_N1_N1,      /* I:U = N:1, U:Sh = N:1 */
+       IUS_322,        /* I:U:Sh = 3:2:2        */
+       IUS_522,        /* I:U:Sh = 5:2:2        */
+       IUS_N11,        /* I:U:Sh = N:1:1        */
+       SB_N1,          /* Sh:B = N:1            */
+       SB3_N1,         /* Sh:B3 = N:1           */
+       SB3_32,         /* Sh:B3 = 3:2           */
+       SB3_43,         /* Sh:B3 = 4:3           */
+       SB3_54,         /* Sh:B3 = 5:4           */
+       BP_N1,          /* B:P   = N:1           */
+       IP_N1           /* I:P   = N:1           */
+
+Each of these constants means relation between clocks that can be set via the FRQCR
+register
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 e96a341..1d19256 100644 (file)
@@ -197,11 +197,22 @@ and may not be fast.
 
 panic_on_oom
 
-This enables or disables panic on out-of-memory feature.  If this is set to 1,
-the kernel panics when out-of-memory happens.  If this is set to 0, the kernel
-will kill some rogue process, called oom_killer.  Usually, oom_killer can kill
-rogue processes and system will survive.  If you want to panic the system
-rather than killing rogue processes, set this to 1.
+This enables or disables panic on out-of-memory feature.
 
-The default value is 0.
+If this is set to 0, the kernel will kill some rogue process,
+called oom_killer.  Usually, oom_killer can kill rogue processes and
+system will survive.
+
+If this is set to 1, the kernel panics when out-of-memory happens.
+However, if a process limits using nodes by mempolicy/cpusets,
+and those nodes become memory exhaustion status, one process
+may be killed by oom-killer. No panic occurs in this case.
+Because other nodes' memory may be free. This means system total status
+may be not fatal yet.
 
+If this is set to 2, the kernel panics compulsorily even on the
+above-mentioned.
+
+The default value is 0.
+1 and 2 are for failover of clustering. Please select either
+according to your policy of failover.
index d43aa9d..ba328f2 100644 (file)
@@ -1,6 +1,6 @@
 Linux Magic System Request Key Hacks
 Documentation for sysrq.c
-Last update: 2007-JAN-06
+Last update: 2007-MAR-14
 
 *  What is the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -75,7 +75,7 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
 'f'    - Will call oom_kill to kill a memory hog process.
 
-'g'    - Used by kgdb on ppc platforms.
+'g'    - Used by kgdb on ppc and sh platforms.
 
 'h'     - Will display help (actually any other key than those listed
           above will display help. but 'h' is easy to remember :-)
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
diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c
new file mode 100644 (file)
index 0000000..41710cc
--- /dev/null
@@ -0,0 +1,943 @@
+/*
+ * Slabinfo: Tool to get reports about slabs
+ *
+ * (C) 2007 sgi, Christoph Lameter <clameter@sgi.com>
+ *
+ * Compile by:
+ *
+ * gcc -o slabinfo slabinfo.c
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <regex.h>
+
+#define MAX_SLABS 500
+#define MAX_ALIASES 500
+#define MAX_NODES 1024
+
+struct slabinfo {
+       char *name;
+       int alias;
+       int refs;
+       int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
+       int hwcache_align, object_size, objs_per_slab;
+       int sanity_checks, slab_size, store_user, trace;
+       int order, poison, reclaim_account, red_zone;
+       unsigned long partial, objects, slabs;
+       int numa[MAX_NODES];
+       int numa_partial[MAX_NODES];
+} slabinfo[MAX_SLABS];
+
+struct aliasinfo {
+       char *name;
+       char *ref;
+       struct slabinfo *slab;
+} aliasinfo[MAX_ALIASES];
+
+int slabs = 0;
+int aliases = 0;
+int alias_targets = 0;
+int highest_node = 0;
+
+char buffer[4096];
+
+int show_alias = 0;
+int show_slab = 0;
+int skip_zero = 1;
+int show_numa = 0;
+int show_track = 0;
+int show_first_alias = 0;
+int validate = 0;
+int shrink = 0;
+int show_inverted = 0;
+int show_single_ref = 0;
+int show_totals = 0;
+int sort_size = 0;
+
+int page_size;
+
+regex_t pattern;
+
+void fatal(const char *x, ...)
+{
+       va_list ap;
+
+       va_start(ap, x);
+       vfprintf(stderr, x, ap);
+       va_end(ap);
+       exit(1);
+}
+
+void usage(void)
+{
+       printf("slabinfo [-ahnpvtsz] [slab-regexp]\n"
+               "-a|--aliases           Show aliases\n"
+               "-h|--help              Show usage information\n"
+               "-n|--numa              Show NUMA information\n"
+               "-s|--shrink            Shrink slabs\n"
+               "-v|--validate          Validate slabs\n"
+               "-t|--tracking          Show alloc/free information\n"
+               "-T|--Totals            Show summary information\n"
+               "-l|--slabs             Show slabs\n"
+               "-S|--Size              Sort by size\n"
+               "-z|--zero              Include empty slabs\n"
+               "-f|--first-alias       Show first alias\n"
+               "-i|--inverted          Inverted list\n"
+               "-1|--1ref              Single reference\n"
+       );
+}
+
+unsigned long read_obj(char *name)
+{
+       FILE *f = fopen(name, "r");
+
+       if (!f)
+               buffer[0] = 0;
+       else {
+               if (!fgets(buffer,sizeof(buffer), f))
+                       buffer[0] = 0;
+               fclose(f);
+               if (buffer[strlen(buffer)] == '\n')
+                       buffer[strlen(buffer)] = 0;
+       }
+       return strlen(buffer);
+}
+
+
+/*
+ * Get the contents of an attribute
+ */
+unsigned long get_obj(char *name)
+{
+       if (!read_obj(name))
+               return 0;
+
+       return atol(buffer);
+}
+
+unsigned long get_obj_and_str(char *name, char **x)
+{
+       unsigned long result = 0;
+       char *p;
+
+       *x = NULL;
+
+       if (!read_obj(name)) {
+               x = NULL;
+               return 0;
+       }
+       result = strtoul(buffer, &p, 10);
+       while (*p == ' ')
+               p++;
+       if (*p)
+               *x = strdup(p);
+       return result;
+}
+
+void set_obj(struct slabinfo *s, char *name, int n)
+{
+       char x[100];
+
+       sprintf(x, "%s/%s", s->name, name);
+
+       FILE *f = fopen(x, "w");
+
+       if (!f)
+               fatal("Cannot write to %s\n", x);
+
+       fprintf(f, "%d\n", n);
+       fclose(f);
+}
+
+/*
+ * Put a size string together
+ */
+int store_size(char *buffer, unsigned long value)
+{
+       unsigned long divisor = 1;
+       char trailer = 0;
+       int n;
+
+       if (value > 1000000000UL) {
+               divisor = 100000000UL;
+               trailer = 'G';
+       } else if (value > 1000000UL) {
+               divisor = 100000UL;
+               trailer = 'M';
+       } else if (value > 1000UL) {
+               divisor = 100;
+               trailer = 'K';
+       }
+
+       value /= divisor;
+       n = sprintf(buffer, "%ld",value);
+       if (trailer) {
+               buffer[n] = trailer;
+               n++;
+               buffer[n] = 0;
+       }
+       if (divisor != 1) {
+               memmove(buffer + n - 2, buffer + n - 3, 4);
+               buffer[n-2] = '.';
+               n++;
+       }
+       return n;
+}
+
+void decode_numa_list(int *numa, char *t)
+{
+       int node;
+       int nr;
+
+       memset(numa, 0, MAX_NODES * sizeof(int));
+
+       while (*t == 'N') {
+               t++;
+               node = strtoul(t, &t, 10);
+               if (*t == '=') {
+                       t++;
+                       nr = strtoul(t, &t, 10);
+                       numa[node] = nr;
+                       if (node > highest_node)
+                               highest_node = node;
+               }
+               while (*t == ' ')
+                       t++;
+       }
+}
+
+void slab_validate(struct slabinfo *s)
+{
+       set_obj(s, "validate", 1);
+}
+
+void slab_shrink(struct slabinfo *s)
+{
+       set_obj(s, "shrink", 1);
+}
+
+int line = 0;
+
+void first_line(void)
+{
+       printf("Name                 Objects   Objsize    Space "
+               "Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
+}
+
+/*
+ * Find the shortest alias of a slab
+ */
+struct aliasinfo *find_one_alias(struct slabinfo *find)
+{
+       struct aliasinfo *a;
+       struct aliasinfo *best = NULL;
+
+       for(a = aliasinfo;a < aliasinfo + aliases; a++) {
+               if (a->slab == find &&
+                       (!best || strlen(best->name) < strlen(a->name))) {
+                               best = a;
+                               if (strncmp(a->name,"kmall", 5) == 0)
+                                       return best;
+                       }
+       }
+       if (best)
+               return best;
+       fatal("Cannot find alias for %s\n", find->name);
+       return NULL;
+}
+
+unsigned long slab_size(struct slabinfo *s)
+{
+       return  s->slabs * (page_size << s->order);
+}
+
+
+void slabcache(struct slabinfo *s)
+{
+       char size_str[20];
+       char dist_str[40];
+       char flags[20];
+       char *p = flags;
+
+       if (skip_zero && !s->slabs)
+               return;
+
+       store_size(size_str, slab_size(s));
+       sprintf(dist_str,"%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);
+
+       if (!line++)
+               first_line();
+
+       if (s->aliases)
+               *p++ = '*';
+       if (s->cache_dma)
+               *p++ = 'd';
+       if (s->hwcache_align)
+               *p++ = 'A';
+       if (s->poison)
+               *p++ = 'P';
+       if (s->reclaim_account)
+               *p++ = 'a';
+       if (s->red_zone)
+               *p++ = 'Z';
+       if (s->sanity_checks)
+               *p++ = 'F';
+       if (s->store_user)
+               *p++ = 'U';
+       if (s->trace)
+               *p++ = 'T';
+
+       *p = 0;
+       printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
+               s->name, s->objects, s->object_size, size_str, dist_str,
+               s->objs_per_slab, s->order,
+               s->slabs ? (s->partial * 100) / s->slabs : 100,
+               s->slabs ? (s->objects * s->object_size * 100) /
+                       (s->slabs * (page_size << s->order)) : 100,
+               flags);
+}
+
+void slab_numa(struct slabinfo *s)
+{
+       int node;
+
+       if (!highest_node)
+               fatal("No NUMA information available.\n");
+
+       if (skip_zero && !s->slabs)
+               return;
+
+       if (!line) {
+               printf("\nSlab             Node ");
+               for(node = 0; node <= highest_node; node++)
+                       printf(" %4d", node);
+               printf("\n----------------------");
+               for(node = 0; node <= highest_node; node++)
+                       printf("-----");
+               printf("\n");
+       }
+       printf("%-21s ", s->name);
+       for(node = 0; node <= highest_node; node++) {
+               char b[20];
+
+               store_size(b, s->numa[node]);
+               printf(" %4s", b);
+       }
+       printf("\n");
+       line++;
+}
+
+void show_tracking(struct slabinfo *s)
+{
+       printf("\n%s: Calls to allocate a slab object\n", s->name);
+       printf("---------------------------------------------------\n");
+       if (read_obj("alloc_calls"))
+               printf(buffer);
+
+       printf("%s: Calls to free a slab object\n", s->name);
+       printf("-----------------------------------------------\n");
+       if (read_obj("free_calls"))
+               printf(buffer);
+
+}
+
+void totals(void)
+{
+       struct slabinfo *s;
+
+       int used_slabs = 0;
+       char b1[20], b2[20], b3[20], b4[20];
+       unsigned long long max = 1ULL << 63;
+
+       /* Object size */
+       unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
+
+       /* Number of partial slabs in a slabcache */
+       unsigned long long min_partial = max, max_partial = 0,
+                               avg_partial, total_partial = 0;
+
+       /* Number of slabs in a slab cache */
+       unsigned long long min_slabs = max, max_slabs = 0,
+                               avg_slabs, total_slabs = 0;
+
+       /* Size of the whole slab */
+       unsigned long long min_size = max, max_size = 0,
+                               avg_size, total_size = 0;
+
+       /* Bytes used for object storage in a slab */
+       unsigned long long min_used = max, max_used = 0,
+                               avg_used, total_used = 0;
+
+       /* Waste: Bytes used for alignment and padding */
+       unsigned long long min_waste = max, max_waste = 0,
+                               avg_waste, total_waste = 0;
+       /* Number of objects in a slab */
+       unsigned long long min_objects = max, max_objects = 0,
+                               avg_objects, total_objects = 0;
+       /* Waste per object */
+       unsigned long long min_objwaste = max,
+                               max_objwaste = 0, avg_objwaste,
+                               total_objwaste = 0;
+
+       /* Memory per object */
+       unsigned long long min_memobj = max,
+                               max_memobj = 0, avg_memobj,
+                               total_objsize = 0;
+
+       /* Percentage of partial slabs per slab */
+       unsigned long min_ppart = 100, max_ppart = 0,
+                               avg_ppart, total_ppart = 0;
+
+       /* Number of objects in partial slabs */
+       unsigned long min_partobj = max, max_partobj = 0,
+                               avg_partobj, total_partobj = 0;
+
+       /* Percentage of partial objects of all objects in a slab */
+       unsigned long min_ppartobj = 100, max_ppartobj = 0,
+                               avg_ppartobj, total_ppartobj = 0;
+
+
+       for (s = slabinfo; s < slabinfo + slabs; s++) {
+               unsigned long long size;
+               unsigned long used;
+               unsigned long long wasted;
+               unsigned long long objwaste;
+               long long objects_in_partial_slabs;
+               unsigned long percentage_partial_slabs;
+               unsigned long percentage_partial_objs;
+
+               if (!s->slabs || !s->objects)
+                       continue;
+
+               used_slabs++;
+
+               size = slab_size(s);
+               used = s->objects * s->object_size;
+               wasted = size - used;
+               objwaste = s->slab_size - s->object_size;
+
+               objects_in_partial_slabs = s->objects -
+                       (s->slabs - s->partial - s ->cpu_slabs) *
+                       s->objs_per_slab;
+
+               if (objects_in_partial_slabs < 0)
+                       objects_in_partial_slabs = 0;
+
+               percentage_partial_slabs = s->partial * 100 / s->slabs;
+               if (percentage_partial_slabs > 100)
+                       percentage_partial_slabs = 100;
+
+               percentage_partial_objs = objects_in_partial_slabs * 100
+                                                       / s->objects;
+
+               if (percentage_partial_objs > 100)
+                       percentage_partial_objs = 100;
+
+               if (s->object_size < min_objsize)
+                       min_objsize = s->object_size;
+               if (s->partial < min_partial)
+                       min_partial = s->partial;
+               if (s->slabs < min_slabs)
+                       min_slabs = s->slabs;
+               if (size < min_size)
+                       min_size = size;
+               if (wasted < min_waste)
+                       min_waste = wasted;
+               if (objwaste < min_objwaste)
+                       min_objwaste = objwaste;
+               if (s->objects < min_objects)
+                       min_objects = s->objects;
+               if (used < min_used)
+                       min_used = used;
+               if (objects_in_partial_slabs < min_partobj)
+                       min_partobj = objects_in_partial_slabs;
+               if (percentage_partial_slabs < min_ppart)
+                       min_ppart = percentage_partial_slabs;
+               if (percentage_partial_objs < min_ppartobj)
+                       min_ppartobj = percentage_partial_objs;
+               if (s->slab_size < min_memobj)
+                       min_memobj = s->slab_size;
+
+               if (s->object_size > max_objsize)
+                       max_objsize = s->object_size;
+               if (s->partial > max_partial)
+                       max_partial = s->partial;
+               if (s->slabs > max_slabs)
+                       max_slabs = s->slabs;
+               if (size > max_size)
+                       max_size = size;
+               if (wasted > max_waste)
+                       max_waste = wasted;
+               if (objwaste > max_objwaste)
+                       max_objwaste = objwaste;
+               if (s->objects > max_objects)
+                       max_objects = s->objects;
+               if (used > max_used)
+                       max_used = used;
+               if (objects_in_partial_slabs > max_partobj)
+                       max_partobj = objects_in_partial_slabs;
+               if (percentage_partial_slabs > max_ppart)
+                       max_ppart = percentage_partial_slabs;
+               if (percentage_partial_objs > max_ppartobj)
+                       max_ppartobj = percentage_partial_objs;
+               if (s->slab_size > max_memobj)
+                       max_memobj = s->slab_size;
+
+               total_partial += s->partial;
+               total_slabs += s->slabs;
+               total_size += size;
+               total_waste += wasted;
+
+               total_objects += s->objects;
+               total_used += used;
+               total_partobj += objects_in_partial_slabs;
+               total_ppart += percentage_partial_slabs;
+               total_ppartobj += percentage_partial_objs;
+
+               total_objwaste += s->objects * objwaste;
+               total_objsize += s->objects * s->slab_size;
+       }
+
+       if (!total_objects) {
+               printf("No objects\n");
+               return;
+       }
+       if (!used_slabs) {
+               printf("No slabs\n");
+               return;
+       }
+
+       /* Per slab averages */
+       avg_partial = total_partial / used_slabs;
+       avg_slabs = total_slabs / used_slabs;
+       avg_size = total_size / used_slabs;
+       avg_waste = total_waste / used_slabs;
+
+       avg_objects = total_objects / used_slabs;
+       avg_used = total_used / used_slabs;
+       avg_partobj = total_partobj / used_slabs;
+       avg_ppart = total_ppart / used_slabs;
+       avg_ppartobj = total_ppartobj / used_slabs;
+
+       /* Per object object sizes */
+       avg_objsize = total_used / total_objects;
+       avg_objwaste = total_objwaste / total_objects;
+       avg_partobj = total_partobj * 100 / total_objects;
+       avg_memobj = total_objsize / total_objects;
+
+       printf("Slabcache Totals\n");
+       printf("----------------\n");
+       printf("Slabcaches : %3d      Aliases  : %3d->%-3d Active: %3d\n",
+                       slabs, aliases, alias_targets, used_slabs);
+
+       store_size(b1, total_size);store_size(b2, total_waste);
+       store_size(b3, total_waste * 100 / total_used);
+       printf("Memory used: %6s   # Loss   : %6s   MRatio: %6s%%\n", b1, b2, b3);
+
+       store_size(b1, total_objects);store_size(b2, total_partobj);
+       store_size(b3, total_partobj * 100 / total_objects);
+       printf("# Objects  : %6s   # PartObj: %6s   ORatio: %6s%%\n", b1, b2, b3);
+
+       printf("\n");
+       printf("Per Cache    Average         Min         Max       Total\n");
+       printf("---------------------------------------------------------\n");
+
+       store_size(b1, avg_objects);store_size(b2, min_objects);
+       store_size(b3, max_objects);store_size(b4, total_objects);
+       printf("#Objects  %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_slabs);store_size(b2, min_slabs);
+       store_size(b3, max_slabs);store_size(b4, total_slabs);
+       printf("#Slabs    %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_partial);store_size(b2, min_partial);
+       store_size(b3, max_partial);store_size(b4, total_partial);
+       printf("#PartSlab %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+       store_size(b1, avg_ppart);store_size(b2, min_ppart);
+       store_size(b3, max_ppart);
+       store_size(b4, total_partial * 100  / total_slabs);
+       printf("%%PartSlab %10s%% %10s%% %10s%% %10s%%\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_partobj);store_size(b2, min_partobj);
+       store_size(b3, max_partobj);
+       store_size(b4, total_partobj);
+       printf("PartObjs  %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
+       store_size(b3, max_ppartobj);
+       store_size(b4, total_partobj * 100 / total_objects);
+       printf("%% PartObj %10s%% %10s%% %10s%% %10s%%\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_size);store_size(b2, min_size);
+       store_size(b3, max_size);store_size(b4, total_size);
+       printf("Memory    %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_used);store_size(b2, min_used);
+       store_size(b3, max_used);store_size(b4, total_used);
+       printf("Used      %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_waste);store_size(b2, min_waste);
+       store_size(b3, max_waste);store_size(b4, total_waste);
+       printf("Loss      %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       printf("\n");
+       printf("Per Object   Average         Min         Max\n");
+       printf("---------------------------------------------\n");
+
+       store_size(b1, avg_memobj);store_size(b2, min_memobj);
+       store_size(b3, max_memobj);
+       printf("Memory    %10s  %10s  %10s\n",
+                       b1,     b2,     b3);
+       store_size(b1, avg_objsize);store_size(b2, min_objsize);
+       store_size(b3, max_objsize);
+       printf("User      %10s  %10s  %10s\n",
+                       b1,     b2,     b3);
+
+       store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
+       store_size(b3, max_objwaste);
+       printf("Loss      %10s  %10s  %10s\n",
+                       b1,     b2,     b3);
+}
+
+void sort_slabs(void)
+{
+       struct slabinfo *s1,*s2;
+
+       for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
+               for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
+                       int result;
+
+                       if (sort_size)
+                               result = slab_size(s1) < slab_size(s2);
+                       else
+                               result = strcasecmp(s1->name, s2->name);
+
+                       if (show_inverted)
+                               result = -result;
+
+                       if (result > 0) {
+                               struct slabinfo t;
+
+                               memcpy(&t, s1, sizeof(struct slabinfo));
+                               memcpy(s1, s2, sizeof(struct slabinfo));
+                               memcpy(s2, &t, sizeof(struct slabinfo));
+                       }
+               }
+       }
+}
+
+void sort_aliases(void)
+{
+       struct aliasinfo *a1,*a2;
+
+       for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
+               for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
+                       char *n1, *n2;
+
+                       n1 = a1->name;
+                       n2 = a2->name;
+                       if (show_alias && !show_inverted) {
+                               n1 = a1->ref;
+                               n2 = a2->ref;
+                       }
+                       if (strcasecmp(n1, n2) > 0) {
+                               struct aliasinfo t;
+
+                               memcpy(&t, a1, sizeof(struct aliasinfo));
+                               memcpy(a1, a2, sizeof(struct aliasinfo));
+                               memcpy(a2, &t, sizeof(struct aliasinfo));
+                       }
+               }
+       }
+}
+
+void link_slabs(void)
+{
+       struct aliasinfo *a;
+       struct slabinfo *s;
+
+       for (a = aliasinfo; a < aliasinfo + aliases; a++) {
+
+               for(s = slabinfo; s < slabinfo + slabs; s++)
+                       if (strcmp(a->ref, s->name) == 0) {
+                               a->slab = s;
+                               s->refs++;
+                               break;
+                       }
+               if (s == slabinfo + slabs)
+                       fatal("Unresolved alias %s\n", a->ref);
+       }
+}
+
+void alias(void)
+{
+       struct aliasinfo *a;
+       char *active = NULL;
+
+       sort_aliases();
+       link_slabs();
+
+       for(a = aliasinfo; a < aliasinfo + aliases; a++) {
+
+               if (!show_single_ref && a->slab->refs == 1)
+                       continue;
+
+               if (!show_inverted) {
+                       if (active) {
+                               if (strcmp(a->slab->name, active) == 0) {
+                                       printf(" %s", a->name);
+                                       continue;
+                               }
+                       }
+                       printf("\n%-20s <- %s", a->slab->name, a->name);
+                       active = a->slab->name;
+               }
+               else
+                       printf("%-20s -> %s\n", a->name, a->slab->name);
+       }
+       if (active)
+               printf("\n");
+}
+
+
+void rename_slabs(void)
+{
+       struct slabinfo *s;
+       struct aliasinfo *a;
+
+       for (s = slabinfo; s < slabinfo + slabs; s++) {
+               if (*s->name != ':')
+                       continue;
+
+               if (s->refs > 1 && !show_first_alias)
+                       continue;
+
+               a = find_one_alias(s);
+
+               s->name = a->name;
+       }
+}
+
+int slab_mismatch(char *slab)
+{
+       return regexec(&pattern, slab, 0, NULL, 0);
+}
+
+void read_slab_dir(void)
+{
+       DIR *dir;
+       struct dirent *de;
+       struct slabinfo *slab = slabinfo;
+       struct aliasinfo *alias = aliasinfo;
+       char *p;
+       char *t;
+       int count;
+
+       dir = opendir(".");
+       while ((de = readdir(dir))) {
+               if (de->d_name[0] == '.' ||
+                               slab_mismatch(de->d_name))
+                       continue;
+               switch (de->d_type) {
+                  case DT_LNK:
+                       alias->name = strdup(de->d_name);
+                       count = readlink(de->d_name, buffer, sizeof(buffer));
+
+                       if (count < 0)
+                               fatal("Cannot read symlink %s\n", de->d_name);
+
+                       buffer[count] = 0;
+                       p = buffer + count;
+                       while (p > buffer && p[-1] != '/')
+                               p--;
+                       alias->ref = strdup(p);
+                       alias++;
+                       break;
+                  case DT_DIR:
+                       if (chdir(de->d_name))
+                               fatal("Unable to access slab %s\n", slab->name);
+                       slab->name = strdup(de->d_name);
+                       slab->alias = 0;
+                       slab->refs = 0;
+                       slab->aliases = get_obj("aliases");
+                       slab->align = get_obj("align");
+                       slab->cache_dma = get_obj("cache_dma");
+                       slab->cpu_slabs = get_obj("cpu_slabs");
+                       slab->destroy_by_rcu = get_obj("destroy_by_rcu");
+                       slab->hwcache_align = get_obj("hwcache_align");
+                       slab->object_size = get_obj("object_size");
+                       slab->objects = get_obj("objects");
+                       slab->objs_per_slab = get_obj("objs_per_slab");
+                       slab->order = get_obj("order");
+                       slab->partial = get_obj("partial");
+                       slab->partial = get_obj_and_str("partial", &t);
+                       decode_numa_list(slab->numa_partial, t);
+                       slab->poison = get_obj("poison");
+                       slab->reclaim_account = get_obj("reclaim_account");
+                       slab->red_zone = get_obj("red_zone");
+                       slab->sanity_checks = get_obj("sanity_checks");
+                       slab->slab_size = get_obj("slab_size");
+                       slab->slabs = get_obj_and_str("slabs", &t);
+                       decode_numa_list(slab->numa, t);
+                       slab->store_user = get_obj("store_user");
+                       slab->trace = get_obj("trace");
+                       chdir("..");
+                       if (slab->name[0] == ':')
+                               alias_targets++;
+                       slab++;
+                       break;
+                  default :
+                       fatal("Unknown file type %lx\n", de->d_type);
+               }
+       }
+       closedir(dir);
+       slabs = slab - slabinfo;
+       aliases = alias - aliasinfo;
+       if (slabs > MAX_SLABS)
+               fatal("Too many slabs\n");
+       if (aliases > MAX_ALIASES)
+               fatal("Too many aliases\n");
+}
+
+void output_slabs(void)
+{
+       struct slabinfo *slab;
+
+       for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
+
+               if (slab->alias)
+                       continue;
+
+
+               if (show_numa)
+                       slab_numa(slab);
+               else
+               if (show_track)
+                       show_tracking(slab);
+               else
+               if (validate)
+                       slab_validate(slab);
+               else
+               if (shrink)
+                       slab_shrink(slab);
+               else {
+                       if (show_slab)
+                               slabcache(slab);
+               }
+       }
+}
+
+struct option opts[] = {
+       { "aliases", 0, NULL, 'a' },
+       { "slabs", 0, NULL, 'l' },
+       { "numa", 0, NULL, 'n' },
+       { "zero", 0, NULL, 'z' },
+       { "help", 0, NULL, 'h' },
+       { "validate", 0, NULL, 'v' },
+       { "first-alias", 0, NULL, 'f' },
+       { "shrink", 0, NULL, 's' },
+       { "track", 0, NULL, 't'},
+       { "inverted", 0, NULL, 'i'},
+       { "1ref", 0, NULL, '1'},
+       { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+       int c;
+       int err;
+       char *pattern_source;
+
+       page_size = getpagesize();
+       if (chdir("/sys/slab"))
+               fatal("This kernel does not have SLUB support.\n");
+
+       while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1)
+       switch(c) {
+               case '1':
+                       show_single_ref = 1;
+                       break;
+               case 'a':
+                       show_alias = 1;
+                       break;
+               case 'f':
+                       show_first_alias = 1;
+                       break;
+               case 'h':
+                       usage();
+                       return 0;
+               case 'i':
+                       show_inverted = 1;
+                       break;
+               case 'n':
+                       show_numa = 1;
+                       break;
+               case 's':
+                       shrink = 1;
+                       break;
+               case 'l':
+                       show_slab = 1;
+                       break;
+               case 't':
+                       show_track = 1;
+                       break;
+               case 'v':
+                       validate = 1;
+                       break;
+               case 'z':
+                       skip_zero = 0;
+                       break;
+               case 'T':
+                       show_totals = 1;
+                       break;
+               case 'S':
+                       sort_size = 1;
+                       break;
+
+               default:
+                       fatal("%s: Invalid option '%c'\n", argv[0], optopt);
+
+       }
+
+       if (!show_slab && !show_alias && !show_track
+               && !validate && !shrink)
+                       show_slab = 1;
+
+       if (argc > optind)
+               pattern_source = argv[optind];
+       else
+               pattern_source = ".*";
+
+       err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
+       if (err)
+               fatal("%s: Invalid pattern '%s' code %d\n",
+                       argv[0], pattern_source, err);
+       read_slab_dir();
+       if (show_alias)
+               alias();
+       else
+       if (show_totals)
+               totals();
+       else {
+               link_slabs();
+               rename_slabs();
+               sort_slabs();
+               output_slabs();
+       }
+       return 0;
+}
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
new file mode 100644 (file)
index 0000000..727c8d8
--- /dev/null
@@ -0,0 +1,113 @@
+Short users guide for SLUB
+--------------------------
+
+First of all slub should transparently replace SLAB. If you enable
+SLUB then everything should work the same (Note the word "should".
+There is likely not much value in that word at this point).
+
+The basic philosophy of SLUB is very different from SLAB. SLAB
+requires rebuilding the kernel to activate debug options for all
+SLABS. SLUB always includes full debugging but its off by default.
+SLUB can enable debugging only for selected slabs in order to avoid
+an impact on overall system performance which may make a bug more
+difficult to find.
+
+In order to switch debugging on one can add a option "slub_debug"
+to the kernel command line. That will enable full debugging for
+all slabs.
+
+Typically one would then use the "slabinfo" command to get statistical
+data and perform operation on the slabs. By default slabinfo only lists
+slabs that have data in them. See "slabinfo -h" for more options when
+running the command. slabinfo can be compiled with
+
+gcc -o slabinfo Documentation/vm/slabinfo.c
+
+Some of the modes of operation of slabinfo require that slub debugging
+be enabled on the command line. F.e. no tracking information will be
+available without debugging on and validation can only partially
+be performed if debugging was not switched on.
+
+Some more sophisticated uses of slub_debug:
+-------------------------------------------
+
+Parameters may be given to slub_debug. If none is specified then full
+debugging is enabled. Format:
+
+slub_debug=<Debug-Options>       Enable options for all slabs
+slub_debug=<Debug-Options>,<slab name>
+                               Enable options only for select slabs
+
+Possible debug options are
+       F               Sanity checks on (enables SLAB_DEBUG_FREE. Sorry
+                       SLAB legacy issues)
+       Z               Red zoning
+       P               Poisoning (object and padding)
+       U               User tracking (free and alloc)
+       T               Trace (please only use on single slabs)
+
+F.e. in order to boot just with sanity checks and red zoning one would specify:
+
+       slub_debug=FZ
+
+Trying to find an issue in the dentry cache? Try
+
+       slub_debug=,dentry_cache
+
+to only enable debugging on the dentry cache.
+
+Red zoning and tracking may realign the slab.  We can just apply sanity checks
+to the dentry cache with
+
+       slub_debug=F,dentry_cache
+
+In case you forgot to enable debugging on the kernel command line: It is
+possible to enable debugging manually when the kernel is up. Look at the
+contents of:
+
+/sys/slab/<slab name>/
+
+Look at the writable files. Writing 1 to them will enable the
+corresponding debug option. All options can be set on a slab that does
+not contain objects. If the slab already contains objects then sanity checks
+and tracing may only be enabled. The other options may cause the realignment
+of objects.
+
+Careful with tracing: It may spew out lots of information and never stop if
+used on the wrong slab.
+
+SLAB Merging
+------------
+
+If no debugging is specified then SLUB may merge similar slabs together
+in order to reduce overhead and increase cache hotness of objects.
+slabinfo -a displays which slabs were merged together.
+
+Getting more performance
+------------------------
+
+To some degree SLUB's performance is limited by the need to take the
+list_lock once in a while to deal with partial slabs. That overhead is
+governed by the order of the allocation for each slab. The allocations
+can be influenced by kernel parameters:
+
+slub_min_objects=x             (default 8)
+slub_min_order=x               (default 0)
+slub_max_order=x               (default 4)
+
+slub_min_objects allows to specify how many objects must at least fit
+into one slab in order for the allocation order to be acceptable.
+In general slub will be able to perform this number of allocations
+on a slab without consulting centralized resources (list_lock) where
+contention may occur.
+
+slub_min_order specifies a minim order of slabs. A similar effect like
+slub_min_objects.
+
+slub_max_order specified the order at which slub_min_objects should no
+longer be checked. This is useful to avoid SLUB trying to generate
+super large order pages to fit slub_min_objects of a slab cache with
+large object sizes into one high order page.
+
+
+Christoph Lameter, <clameter@sgi.com>, April 10, 2007
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
diff --git a/Kbuild b/Kbuild
index 0451f69..163f8cb 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -2,6 +2,7 @@
 # Kbuild for top-level directory of the kernel
 # This file takes care of the following:
 # 1) Generate asm-offsets.h
+# 2) Check for missing system calls
 
 #####
 # 1) Generate asm-offsets.h
@@ -46,3 +47,13 @@ $(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild
        $(Q)mkdir -p $(dir $@)
        $(call cmd,offsets)
 
+#####
+# 2) Check for missing system calls
+#
+
+quiet_cmd_syscalls = CALL    $<
+      cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags)
+
+PHONY += missing-syscalls
+missing-syscalls: scripts/checksyscalls.sh FORCE
+       $(call cmd,syscalls)
index af1c792..6d665ac 100644 (file)
@@ -700,6 +700,44 @@ P: Richard Purdie
 M:     rpurdie@rpsys.net
 S:     Maintained
 
+BLACKFIN ARCHITECTURE
+P:     Aubrey Li
+M:     aubrey.li@analog.com
+P:     Bernd Schmidt
+M:     bernd.schmidt@analog.com
+P:     Bryan Wu
+M:     bryan.wu@analog.com
+P:     Grace Pan
+M:     grace.pan@analog.com
+P:     Michael Hennerich
+M:     michael.hennerich@analog.com
+P:     Mike Frysinger
+M:     michael.frysinger@analog.com
+P:     Jane Lv
+M:     jane.lv@analog.com
+P:     Jerry Zeng
+M:     jerry.zeng@analog.com
+P:     Jie Zhang
+M:     jie.zhang@analog.com
+P:     Robin Getz
+M:     robin.getz@analog.com
+P:     Roy Huang
+M:     roy.huang@analog.com
+P:     Sonic Zhang
+M:     sonic.zhang@analog.com
+P:     Yi Li
+M:     yi.li@analog.com
+L:     uclinux-dist-devel@blackfin.uclinux.org
+W:     http://blackfin.uclinux.org
+S:     Supported
+
+BLACKFIN SERIAL DRIVER
+P:     Aubrey Li
+M:     aubrey.li@analog.com
+L:     uclinux-dist-devel@blackfin.uclinux.org
+W:     http://blackfin.uclinux.org
+S:     Supported
+
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
 P:     Thomas Sailer
 M:     t.sailer@alumni.ethz.ch
@@ -733,6 +771,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 +1504,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 +1655,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 +1681,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 +2266,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 +2690,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 +3707,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 +3927,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 d970cb1..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
@@ -576,7 +576,7 @@ libs-y              := $(libs-y1) $(libs-y2)
 # ---------------------------------------------------------------------------
 # vmlinux is built from the objects selected by $(vmlinux-init) and
 # $(vmlinux-main). Most are built-in.o files from top-level directories
-# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
+# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
 # Ordering when linking is important, and $(vmlinux-init) must be first.
 #
 # vmlinux
@@ -603,6 +603,7 @@ vmlinux-init := $(head-y) $(init-y)
 vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
 vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
 vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
+export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
 
 # Rule to link vmlinux - also used during CONFIG_KALLSYMS
 # May be overridden by arch/$(ARCH)/Makefile
@@ -855,6 +856,7 @@ archprepare: prepare1 scripts_basic
 
 prepare0: archprepare FORCE
        $(Q)$(MAKE) $(build)=.
+       $(Q)$(MAKE) $(build)=. missing-syscalls
 
 # All the preparing..
 prepare: prepare0
@@ -1277,10 +1279,7 @@ endif
 ALLSOURCE_ARCHS := $(ARCH)
 
 define find-sources
-        ( find $(__srctree) $(RCS_FIND_IGNORE) \
-              \( -name include -o -name arch \) -prune -o \
-              -name $1 -print; \
-         for ARCH in $(ALLSOURCE_ARCHS) ; do \
+        ( for ARCH in $(ALLSOURCE_ARCHS) ; do \
               find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
                    -name $1 -print; \
          done ; \
@@ -1294,7 +1293,11 @@ define find-sources
                    -name $1 -print; \
          done ; \
          find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-              -name $1 -print )
+              -name $1 -print; \
+         find $(__srctree) $(RCS_FIND_IGNORE) \
+              \( -name include -o -name arch \) -prune -o \
+              -name $1 -print; \
+         )
 endef
 
 define all-sources
index 4307bde..1036b51 100644 (file)
@@ -467,3 +467,9 @@ start_kernel(void)
 #endif
        runkernel();
 }
+
+ /* dummy function, should never be called. */
+void *__kmalloc(size_t size, gfp_t flags)
+{
+       return (void *)NULL;
+}
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 67beb1b..96154e7 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/a.out.h>
 #include <linux/coff.h>
 #include <linux/param.h>
-#include <linux/string.h>
 #ifdef __ELF__
 # include <linux/elf.h>
 #endif
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 be133f1..ea405f5 100644 (file)
@@ -93,7 +93,6 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
  * offset differences aren't the same as "d_reclen").
  */
 #define NAME_OFFSET    offsetof (struct osf_dirent, d_name)
-#define ROUND_UP(x)    (((x)+3) & ~3)
 
 struct osf_dirent {
        unsigned int d_ino;
@@ -115,7 +114,7 @@ osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
 {
        struct osf_dirent __user *dirent;
        struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
-       unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
+       unsigned int reclen = ALIGN(NAME_OFFSET + namlen + 1, sizeof(u32));
        unsigned int d_ino;
 
        buf->error = -EINVAL;   /* only used if we fail */
@@ -174,7 +173,6 @@ osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
        return error;
 }
 
-#undef ROUND_UP
 #undef NAME_OFFSET
 
 asmlinkage unsigned long
@@ -1267,6 +1265,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        if (len > limit)
                return -ENOMEM;
 
+       if (flags & MAP_FIXED)
+               return addr;
+
        /* First, see if the given suggestion fits.
 
           The OSF/1 loader (/sbin/loader) relies on us returning an
index 7569232..85a821a 100644 (file)
@@ -164,9 +164,9 @@ srmcons_get_private_struct(struct srmcons_private **ps)
        int retval = 0;
 
        if (srmconsp == NULL) {
+               srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
                spin_lock_irqsave(&srmconsp_lock, flags);
 
-               srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
                if (srmconsp == NULL)
                        retval = -ENOMEM;
                else {
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 b0b5f46..2c4c242 100644 (file)
@@ -49,8 +49,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 #endif
 
        /*
-        * We should enforce the MAP_FIXED case.  However, currently
-        * the generic kernel code doesn't allow us to handle this.
+        * We enforce the MAP_FIXED case.
         */
        if (flags & MAP_FIXED) {
                if (aliasing && flags & MAP_SHARED && addr & (SHMLBA - 1))
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 989113d..20688bc 100644 (file)
@@ -57,9 +57,6 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
-config GENERIC_BUST_SPINLOCK
-       bool
-
 config ZONE_DMA
        bool
        default y
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"
 
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
new file mode 100644 (file)
index 0000000..1a49305
--- /dev/null
@@ -0,0 +1,989 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "uClinux/Blackfin (w/o MMU) Kernel Configuration"
+
+config MMU
+       bool
+       default n
+
+config FPU
+       bool
+       default n
+
+config RWSEM_GENERIC_SPINLOCK
+       bool
+       default y
+
+config RWSEM_XCHGADD_ALGORITHM
+       bool
+       default n
+
+config BLACKFIN
+       bool
+       default y
+
+config BFIN
+       bool
+       default y
+
+config SEMAPHORE_SLEEPERS
+       bool
+       default y
+
+config GENERIC_FIND_NEXT_BIT
+       bool
+       default y
+
+config GENERIC_HWEIGHT
+       bool
+       default y
+
+config GENERIC_HARDIRQS
+       bool
+       default y
+
+config GENERIC_IRQ_PROBE
+        bool
+       default y
+
+config GENERIC_TIME
+       bool
+       default n
+
+config GENERIC_CALIBRATE_DELAY
+       bool
+       default y
+
+config FORCE_MAX_ZONEORDER
+       int
+       default "14"
+
+config GENERIC_CALIBRATE_DELAY
+       bool
+       default y
+
+config IRQCHIP_DEMUX_GPIO
+       bool
+       default y
+
+source "init/Kconfig"
+source "kernel/Kconfig.preempt"
+
+menu "Blackfin Processor Options"
+
+comment "Processor and Board Settings"
+
+choice
+       prompt "CPU"
+       default BF533
+
+config BF531
+       bool "BF531"
+       help
+         BF531 Processor Support.
+
+config BF532
+       bool "BF532"
+       help
+         BF532 Processor Support.
+
+config BF533
+       bool "BF533"
+       help
+         BF533 Processor Support.
+
+config BF534
+       bool "BF534"
+       help
+         BF534 Processor Support.
+
+config BF536
+       bool "BF536"
+       help
+         BF536 Processor Support.
+
+config BF537
+       bool "BF537"
+       help
+         BF537 Processor Support.
+
+config BF561
+       bool "BF561"
+       help
+         Not Supported Yet - Work in progress - BF561 Processor Support.
+
+endchoice
+
+choice
+       prompt "Silicon Rev"
+       default BF_REV_0_2 if BF537
+       default BF_REV_0_3 if BF533
+
+config BF_REV_0_2
+       bool "0.2"
+       depends on (BF537 || BF536 || BF534)
+
+config BF_REV_0_3
+       bool "0.3"
+       depends on (BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531)
+
+config BF_REV_0_4
+       bool "0.4"
+       depends on (BF561 || BF533 || BF532 || BF531)
+
+config BF_REV_0_5
+       bool "0.5"
+       depends on (BF561 || BF533 || BF532 || BF531)
+
+endchoice
+
+config BFIN_DUAL_CORE
+       bool
+       depends on (BF561)
+       default y
+
+config BFIN_SINGLE_CORE
+       bool
+       depends on !BFIN_DUAL_CORE
+       default y
+
+choice
+       prompt "System type"
+       default BFIN533_STAMP
+       help
+         Do NOT change the board here.  Please use the top level
+         configuration to ensure that all the other settings are
+         correct.
+
+config BFIN533_EZKIT
+       bool "BF533-EZKIT"
+       depends on (BF533 || BF532 || BF531)
+       help
+         BF533-EZKIT-LITE board Support.
+
+config  BFIN533_STAMP
+       bool "BF533-STAMP"
+       depends on (BF533 || BF532 || BF531)
+       help
+         BF533-STAMP board Support.
+
+config BFIN537_STAMP
+       bool "BF537-STAMP"
+       depends on (BF537 || BF536 || BF534)
+       help
+         BF537-STAMP board Support.
+
+config BFIN533_BLUETECHNIX_CM
+       bool "Bluetechnix CM-BF533"
+       depends on (BF533)
+       help
+         CM-BF533 support for EVAL- and DEV-Board.
+
+config BFIN537_BLUETECHNIX_CM
+       bool "Bluetechnix CM-BF537"
+       depends on (BF537)
+       help
+         CM-BF537 support for EVAL- and DEV-Board.
+
+config BFIN561_BLUETECHNIX_CM
+       bool "BF561-CM"
+       depends on (BF561)
+       help
+         CM-BF561 support for EVAL- and DEV-Board.
+
+config BFIN561_EZKIT
+       bool "BF561-EZKIT"
+       depends on (BF561)
+       help
+         BF561-EZKIT-LITE board Support.
+
+config PNAV10
+       bool "PNAV 1.0 board"
+       depends on (BF537)
+       help
+         PNAV 1.0 board Support.
+
+config GENERIC_BOARD
+       bool "Custom"
+       depends on (BF537 || BF536 \
+               || BF534 || BF561 || BF535 || BF533 || BF532 || BF531)
+       help
+         GENERIC or Custom board Support.
+
+endchoice
+
+config MEM_GENERIC_BOARD
+       bool
+       depends on GENERIC_BOARD
+       default y
+
+config MEM_MT48LC64M4A2FB_7E
+       bool
+       depends on (BFIN533_STAMP)
+       default y
+
+config MEM_MT48LC16M16A2TG_75
+       bool
+       depends on (BFIN533_EZKIT || BFIN561_EZKIT \
+               || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM)
+       default y
+
+config MEM_MT48LC32M8A2_75
+       bool
+       depends on (BFIN537_STAMP || PNAV10)
+       default y
+
+config MEM_MT48LC8M32B2B5_7
+       bool
+       depends on (BFIN561_BLUETECHNIX_CM)
+       default y
+
+config BFIN_SHARED_FLASH_ENET
+       bool
+       depends on (BFIN533_STAMP)
+       default y
+
+source "arch/blackfin/mach-bf533/Kconfig"
+source "arch/blackfin/mach-bf561/Kconfig"
+source "arch/blackfin/mach-bf537/Kconfig"
+
+menu "Board customizations"
+
+config CMDLINE_BOOL
+       bool "Default bootloader kernel arguments"
+
+config CMDLINE
+       string "Initial kernel command string"
+       depends on CMDLINE_BOOL
+       default "console=ttyBF0,57600"
+       help
+         If you don't have a boot loader capable of passing a command line string
+         to the kernel, you may specify one here. As a minimum, you should specify
+         the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
+
+comment "Board Setup"
+
+config CLKIN_HZ
+       int "Crystal Frequency in Hz"
+       default "11059200" if BFIN533_STAMP
+       default "27000000" if BFIN533_EZKIT
+       default "25000000" if BFIN537_STAMP
+       default "30000000" if BFIN561_EZKIT
+       default "24576000" if PNAV10
+       help
+         The frequency of CLKIN crystal oscillator on the board in Hz.
+
+config MEM_SIZE
+       int "SDRAM Memory Size in MBytes"
+       default  32 if BFIN533_EZKIT
+       default  64 if BFIN537_STAMP
+       default  64 if BFIN561_EZKIT
+       default 128 if BFIN533_STAMP
+       default  64 if PNAV10
+
+config MEM_ADD_WIDTH
+       int "SDRAM Memory Address Width"
+       default  9 if BFIN533_EZKIT
+       default  9 if BFIN561_EZKIT
+       default 10 if BFIN537_STAMP
+       default 11 if BFIN533_STAMP
+       default 10 if PNAV10
+
+config ENET_FLASH_PIN
+       int "PF port/pin used for flash and ethernet sharing"
+       depends on (BFIN533_STAMP)
+       default  0
+       help
+         PF port/pin used for flash and ethernet sharing to allow other PF
+         pins to be used on other platforms without having to touch common
+         code.
+         For example: PF0 --> 0,PF1 --> 1,PF2 --> 2, etc.
+
+config BOOT_LOAD
+       hex "Kernel load address for booting"
+       default "0x1000"
+       help
+         This option allows you to set the load address of the kernel.
+         This can be useful if you are on a board which has a small amount
+         of memory or you wish to reserve some memory at the beginning of
+         the address space.
+
+         Note that you generally want to keep this value at or above 4k
+         (0x1000) as this will allow the kernel to capture NULL pointer
+         references.
+
+comment "LED Status Indicators"
+       depends on (BFIN533_STAMP || BFIN533_BLUETECHNIX_CM)
+
+config BFIN_ALIVE_LED
+       bool "Enable Board Alive"
+       depends on (BFIN533_STAMP || BFIN533_BLUETECHNIX_CM)
+       default n
+       help
+         Blink the LEDs you select when the kernel is running.  Helps detect
+         a hung kernel.
+
+config BFIN_ALIVE_LED_NUM
+       int "LED"
+       depends on BFIN_ALIVE_LED
+       range 1 3 if BFIN533_STAMP
+       default "3" if BFIN533_STAMP
+       help
+         Select the LED (marked on the board) for you to blink.
+
+config BFIN_IDLE_LED
+       bool "Enable System Load/Idle LED"
+       depends on (BFIN533_STAMP || BFIN533_BLUETECHNIX_CM)
+       default n
+       help
+         Blinks the LED you select when to determine kernel load.
+
+config BFIN_IDLE_LED_NUM
+       int "LED"
+       depends on BFIN_IDLE_LED
+       range 1 3 if BFIN533_STAMP
+       default "2" if BFIN533_STAMP
+       help
+         Select the LED (marked on the board) for you to blink.
+
+#
+# Sorry - but you need to put the hex address here -
+#
+
+# Flag Data register
+config BFIN_ALIVE_LED_PORT
+       hex
+       default 0xFFC00700 if (BFIN533_STAMP)
+
+# Peripheral Flag Direction Register
+config BFIN_ALIVE_LED_DPORT
+       hex
+       default 0xFFC00730 if (BFIN533_STAMP)
+
+config BFIN_ALIVE_LED_PIN
+       hex
+       default 0x04 if (BFIN533_STAMP && BFIN_ALIVE_LED_NUM = 1)
+       default 0x08 if (BFIN533_STAMP && BFIN_ALIVE_LED_NUM = 2)
+       default 0x10 if (BFIN533_STAMP && BFIN_ALIVE_LED_NUM = 3)
+
+config BFIN_IDLE_LED_PORT
+       hex
+       default 0xFFC00700 if (BFIN533_STAMP)
+
+# Peripheral Flag Direction Register
+config BFIN_IDLE_LED_DPORT
+       hex
+       default 0xFFC00730 if (BFIN533_STAMP)
+
+config BFIN_IDLE_LED_PIN
+       hex
+       default 0x04 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 1)
+       default 0x08 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 2)
+       default 0x10 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 3)
+
+comment "Console UART Setup"
+
+choice
+       prompt "Baud Rate"
+       default BAUD_57600
+config BAUD_9600
+       bool "9600"
+config BAUD_19200
+       bool "19200"
+config BAUD_38400
+       bool "38400"
+config BAUD_57600
+       bool "57600"
+config BAUD_115200
+       bool "115200"
+endchoice
+
+choice
+       prompt "Parity"
+       default BAUD_NO_PARITY
+config  BAUD_NO_PARITY
+       bool "No Parity"
+config  BAUD_PARITY
+       bool "Parity"
+endchoice
+
+choice
+       prompt "Stop Bits"
+       default BAUD_1_STOPBIT
+config  BAUD_1_STOPBIT
+       bool "1"
+config  BAUD_2_STOPBIT
+       bool "2"
+endchoice
+
+endmenu
+
+
+menu "Blackfin Kernel Optimizations"
+
+comment "Timer Tick"
+
+source kernel/Kconfig.hz
+
+comment "Memory Optimizations"
+
+config I_ENTRY_L1
+       bool "Locate interrupt entry code in L1 Memory"
+       default y
+       help
+         If enabled interrupt entry code (STORE/RESTORE CONTEXT) is linked
+         into L1 instruction memory.(less latency)
+
+config EXCPT_IRQ_SYSC_L1
+       bool "Locate entire ASM lowlevel excepetion / interrupt - Syscall and CPLB handler code in L1 Memory"
+       default y
+       help
+         If enabled entire ASM lowlevel exception and interrupt entry code (STORE/RESTORE CONTEXT) is linked
+         into L1 instruction memory.(less latency)
+
+config DO_IRQ_L1
+       bool "Locate frequently called do_irq dispatcher function in L1 Memory"
+       default y
+       help
+         If enabled frequently called do_irq dispatcher function is linked
+         into L1 instruction memory.(less latency)
+
+config CORE_TIMER_IRQ_L1
+       bool "Locate frequently called timer_interrupt() function in L1 Memory"
+       default y
+       help
+         If enabled frequently called timer_interrupt() function is linked
+         into L1 instruction memory.(less latency)
+
+config IDLE_L1
+       bool "Locate frequently idle function in L1 Memory"
+       default y
+       help
+         If enabled frequently called idle function is linked
+         into L1 instruction memory.(less latency)
+
+config SCHEDULE_L1
+       bool "Locate kernel schedule function in L1 Memory"
+       default y
+       help
+         If enabled frequently called kernel schedule is linked
+         into L1 instruction memory.(less latency)
+
+config ARITHMETIC_OPS_L1
+       bool "Locate kernel owned arithmetic functions in L1 Memory"
+       default y
+       help
+         If enabled arithmetic functions are linked
+         into L1 instruction memory.(less latency)
+
+config ACCESS_OK_L1
+       bool "Locate access_ok function in L1 Memory"
+       default y
+       help
+         If enabled access_ok function is linked
+         into L1 instruction memory.(less latency)
+
+config MEMSET_L1
+       bool "Locate memset function in L1 Memory"
+       default y
+       help
+         If enabled memset function is linked
+         into L1 instruction memory.(less latency)
+
+config MEMCPY_L1
+       bool "Locate memcpy function in L1 Memory"
+       default y
+       help
+         If enabled memcpy function is linked
+         into L1 instruction memory.(less latency)
+
+config SYS_BFIN_SPINLOCK_L1
+       bool "Locate sys_bfin_spinlock function in L1 Memory"
+       default y
+       help
+         If enabled sys_bfin_spinlock function is linked
+         into L1 instruction memory.(less latency)
+
+config IP_CHECKSUM_L1
+       bool "Locate IP Checksum function in L1 Memory"
+       default n
+       help
+         If enabled IP Checksum function is linked
+         into L1 instruction memory.(less latency)
+
+config CACHELINE_ALIGNED_L1
+       bool "Locate cacheline_aligned data to L1 Data Memory"
+       default y
+       depends on !BF531
+       help
+         If enabled cacheline_anligned data is linked
+         into L1 data memory.(less latency)
+
+config SYSCALL_TAB_L1
+       bool "Locate Syscall Table L1 Data Memory"
+       default n
+       depends on !BF531
+       help
+         If enabled the Syscall LUT is linked
+         into L1 data memory.(less latency)
+
+config CPLB_SWITCH_TAB_L1
+       bool "Locate CPLB Switch Tables L1 Data Memory"
+       default n
+       depends on !BF531
+       help
+         If enabled the CPLB Switch Tables are linked
+         into L1 data memory.(less latency)
+
+endmenu
+
+
+choice
+       prompt "Kernel executes from"
+       help
+         Choose the memory type that the kernel will be running in.
+
+config RAMKERNEL
+       bool "RAM"
+       help
+         The kernel will be resident in RAM when running.
+
+config ROMKERNEL
+       bool "ROM"
+       help
+         The kernel will be resident in FLASH/ROM when running.
+
+endchoice
+
+source "mm/Kconfig"
+
+config LARGE_ALLOCS
+       bool "Allow allocating large blocks (> 1MB) of memory"
+       help
+         Allow the slab memory allocator to keep chains for very large
+         memory sizes - upto 32MB. You may need this if your system has
+         a lot of RAM, and you need to able to allocate very large
+         contiguous chunks. If unsure, say N.
+
+config BFIN_DMA_5XX
+       bool "Enable DMA Support"
+       depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561)
+       default y
+       help
+         DMA driver for BF5xx.
+
+choice
+       prompt "Uncached SDRAM region"
+       default DMA_UNCACHED_1M
+       depends BFIN_DMA_5XX
+config DMA_UNCACHED_2M
+       bool "Enable 2M DMA region"
+config DMA_UNCACHED_1M
+       bool "Enable 1M DMA region"
+config DMA_UNCACHED_NONE
+       bool "Disable DMA region"
+endchoice
+
+
+comment "Cache Support"
+config BLKFIN_CACHE
+       bool "Enable ICACHE"
+config BLKFIN_DCACHE
+       bool "Enable DCACHE"
+config BLKFIN_DCACHE_BANKA
+       bool "Enable only 16k BankA DCACHE - BankB is SRAM"
+       depends on BLKFIN_DCACHE && !BF531
+       default n
+config BLKFIN_CACHE_LOCK
+       bool "Enable Cache Locking"
+
+choice
+       prompt "Policy"
+       depends on BLKFIN_DCACHE
+       default BLKFIN_WB
+config BLKFIN_WB
+       bool "Write back"
+       help
+         Write Back Policy:
+           Cached data will be written back to SDRAM only when needed.
+           This can give a nice increase in performance, but beware of
+           broken drivers that do not properly invalidate/flush their
+           cache.
+
+         Write Through Policy:
+           Cached data will always be written back to SDRAM when the
+           cache is updated.  This is a completely safe setting, but
+           performance is worse than Write Back.
+
+         If you are unsure of the options and you want to be safe,
+         then go with Write Through.
+
+config BLKFIN_WT
+       bool "Write through"
+       help
+         Write Back Policy:
+           Cached data will be written back to SDRAM only when needed.
+           This can give a nice increase in performance, but beware of
+           broken drivers that do not properly invalidate/flush their
+           cache.
+
+         Write Through Policy:
+           Cached data will always be written back to SDRAM when the
+           cache is updated.  This is a completely safe setting, but
+           performance is worse than Write Back.
+
+         If you are unsure of the options and you want to be safe,
+         then go with Write Through.
+
+endchoice
+
+config L1_MAX_PIECE
+       int "Set the max L1 SRAM pieces"
+       default 16
+       help
+         Set the max memory pieces for the L1 SRAM allocation algorithm.
+         Min value is 16. Max value is 1024.
+
+menu "Clock Settings"
+
+
+config BFIN_KERNEL_CLOCK
+       bool "Re-program Clocks while Kernel boots?"
+       default n
+       help
+         This option decides if kernel clocks are re-programed from the
+         bootloader settings. If the clocks are not set, the SDRAM settings
+         are also not changed, and the Bootloader does 100% of the hardware
+         configuration.
+
+config VCO_MULT
+       int "VCO Multiplier"
+       depends on BFIN_KERNEL_CLOCK
+       default "22" if BFIN533_EZKIT
+       default "45" if BFIN533_STAMP
+       default "20" if BFIN537_STAMP
+       default "22" if BFIN533_BLUETECHNIX_CM
+       default "20" if BFIN537_BLUETECHNIX_CM
+       default "20" if BFIN561_BLUETECHNIX_CM
+       default "20" if BFIN561_EZKIT
+
+config CCLK_DIV
+       int "Core Clock Divider"
+       depends on BFIN_KERNEL_CLOCK
+       default 1 if BFIN533_EZKIT
+       default 1 if BFIN533_STAMP
+       default 1 if BFIN537_STAMP
+       default 1 if BFIN533_BLUETECHNIX_CM
+       default 1 if BFIN537_BLUETECHNIX_CM
+       default 1 if BFIN561_BLUETECHNIX_CM
+       default 1 if BFIN561_EZKIT
+
+config SCLK_DIV
+       int "System Clock Divider"
+       depends on BFIN_KERNEL_CLOCK
+       default 5 if BFIN533_EZKIT
+       default 5 if BFIN533_STAMP
+       default 4 if BFIN537_STAMP
+       default 5 if BFIN533_BLUETECHNIX_CM
+       default 4 if BFIN537_BLUETECHNIX_CM
+       default 4 if BFIN561_BLUETECHNIX_CM
+       default 5 if BFIN561_EZKIT
+
+config CLKIN_HALF
+       bool "Half ClockIn"
+       depends on BFIN_KERNEL_CLOCK
+       default n
+
+config PLL_BYPASS
+       bool "Bypass PLL"
+       depends on BFIN_KERNEL_CLOCK
+       default n
+
+endmenu
+
+comment "Asynchonous Memory Configuration"
+
+menu "EBIU_AMBCTL Global Control"
+config C_AMCKEN
+       bool "Enable CLKOUT"
+       default y
+
+config C_CDPRIO
+       bool "DMA has priority over core for ext. accesses"
+       default n
+
+config C_B0PEN
+       depends on BF561
+       bool "Bank 0 16 bit packing enable"
+       default y
+
+config C_B1PEN
+       depends on BF561
+       bool "Bank 1 16 bit packing enable"
+       default y
+
+config C_B2PEN
+       depends on BF561
+       bool "Bank 2 16 bit packing enable"
+       default y
+
+config C_B3PEN
+       depends on BF561
+       bool "Bank 3 16 bit packing enable"
+       default n
+
+choice
+       prompt"Enable Asynchonous Memory Banks"
+       default C_AMBEN_ALL
+
+config C_AMBEN
+       bool "Disable All Banks"
+
+config C_AMBEN_B0
+       bool "Enable Bank 0"
+
+config C_AMBEN_B0_B1
+       bool "Enable Bank 0 & 1"
+
+config C_AMBEN_B0_B1_B2
+       bool "Enable Bank 0 & 1 & 2"
+
+config C_AMBEN_ALL
+       bool "Enable All Banks"
+endchoice
+endmenu
+
+menu "EBIU_AMBCTL Control"
+config BANK_0
+       hex "Bank 0"
+       default 0x7BB0
+
+config BANK_1
+       hex "Bank 1"
+       default 0x7BB0
+
+config BANK_2
+       hex "Bank 2"
+       default 0x7BB0
+
+config BANK_3
+       hex "Bank 3"
+       default 0x99B3
+endmenu
+
+endmenu
+
+#############################################################################
+menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+config PCI
+       bool "PCI support"
+       help
+         Support for PCI bus.
+
+source "drivers/pci/Kconfig"
+
+config HOTPLUG
+       bool "Support for hot-pluggable device"
+         help
+         Say Y here if you want to plug devices into your computer while
+         the system is running, and be able to use them quickly.  In many
+         cases, the devices can likewise be unplugged at any time too.
+
+         One well known example of this is PCMCIA- or PC-cards, credit-card
+         size devices such as network cards, modems or hard drives which are
+         plugged into slots found on all modern laptop computers.  Another
+         example, used on modern desktops as well as laptops, is USB.
+
+         Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
+         software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+         Then your kernel will automatically call out to a user mode "policy
+         agent" (/sbin/hotplug) to load modules and set up software needed
+         to use devices as you hotplug them.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+menu "Power management options"
+source "kernel/power/Kconfig"
+
+choice
+       prompt "Select PM Wakeup Event Source"
+       default PM_WAKEUP_GPIO_BY_SIC_IWR
+       depends on PM
+       help
+         If you have a GPIO already configured as input with the corresponding PORTx_MASK
+         bit set - "Specify Wakeup Event by SIC_IWR value"
+
+config PM_WAKEUP_GPIO_BY_SIC_IWR
+       bool "Specify Wakeup Event by SIC_IWR value"
+config PM_WAKEUP_BY_GPIO
+       bool "Cause Wakeup Event by GPIO"
+config PM_WAKEUP_GPIO_API
+       bool "Configure Wakeup Event by PM GPIO API"
+
+endchoice
+
+config PM_WAKEUP_SIC_IWR
+       hex "Wakeup Events (SIC_IWR)"
+       depends on PM_WAKEUP_GPIO_BY_SIC_IWR
+       default 0x80000000 if (BF537 || BF536 || BF534)
+       default 0x100000 if (BF533 || BF532 || BF531)
+
+config PM_WAKEUP_GPIO_NUMBER
+       int "Wakeup GPIO number"
+       range 0 47
+       depends on PM_WAKEUP_BY_GPIO
+       default 2 if BFIN537_STAMP
+
+choice
+       prompt "GPIO Polarity"
+       depends on PM_WAKEUP_BY_GPIO
+       default PM_WAKEUP_GPIO_POLAR_H
+config  PM_WAKEUP_GPIO_POLAR_H
+       bool "Active High"
+config  PM_WAKEUP_GPIO_POLAR_L
+       bool "Active Low"
+config  PM_WAKEUP_GPIO_POLAR_EDGE_F
+       bool "Falling EDGE"
+config  PM_WAKEUP_GPIO_POLAR_EDGE_R
+       bool "Rising EDGE"
+config  PM_WAKEUP_GPIO_POLAR_EDGE_B
+       bool "Both EDGE"
+endchoice
+
+endmenu
+
+if (BF537 || BF533)
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+config CPU_FREQ
+       bool
+       default n
+       help
+         If you want to enable this option, you should select the
+         DPMC driver from Character Devices.
+endmenu
+
+endif
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/blackfin/oprofile/Kconfig"
+
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_HWERR
+       bool "Hardware error interrupt debugging"
+       depends on DEBUG_KERNEL
+       help
+         When enabled, the hardware error interrupt is never disabled, and
+         will happen immediately when an error condition occurs.  This comes
+         at a slight cost in code size, but is necessary if you are getting
+         hardware error interrupts and need to know where they are coming
+         from.
+
+config DEBUG_ICACHE_CHECK
+       bool "Check Instruction cache coherancy"
+       depends on DEBUG_KERNEL
+       depends on DEBUG_HWERR
+       help
+         Say Y here if you are getting wierd unexplained errors. This will
+         ensure that icache is what SDRAM says it should be, by doing a
+         byte wise comparision between SDRAM and instruction cache. This
+         also relocates the irq_panic() function to L1 memory, (which is
+         un-cached).
+
+config DEBUG_KERNEL_START
+       bool "Debug Kernel Startup"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to put in an mini-execption handler before the kernel
+         replaces the bootloader exception handler. This will stop kernels
+         from dieing at startup with no visible error messages.
+
+config DEBUG_SERIAL_EARLY_INIT
+       bool "Initialize serial driver early"
+       default n
+       depends on SERIAL_BFIN
+       help
+         Say Y here if you want to get kernel output early when kernel
+         crashes before the normal console initialization. If this option
+         is enable, console output will always go to the ttyBF0, no matter
+         what kernel boot paramters you set.
+
+config DEBUG_HUNT_FOR_ZERO
+       bool "Catch NULL pointer reads/writes"
+       default y
+       help
+         Say Y here to catch reads/writes to anywhere in the memory range
+         from 0x0000 - 0x0FFF (the first 4k) of memory.  This is useful in
+         catching common programming errors such as NULL pointer dereferences.
+
+         Misbehaving applications will be killed (generate a SEGV) while the
+         kernel will trigger a panic.
+
+         Enabling this option will take up an extra entry in CPLB table.
+         Otherwise, there is no extra overhead.
+
+config DEBUG_BFIN_NO_KERN_HWTRACE
+       bool "Trace user apps (turn off hwtrace in kernel)"
+       default n
+       help
+         Some pieces of the kernel contain a lot of flow changes which can
+         quickly fill up the hardware trace buffer.  When debugging crashes,
+         the hardware trace may indicate that the problem lies in kernel
+         space when in reality an application is buggy.
+
+         Say Y here to disable hardware tracing in some known "jumpy" pieces
+         of code so that the trace buffer will extend further back.
+
+config DUAL_CORE_TEST_MODULE
+       tristate "Dual Core Test Module"
+       depends on (BF561)
+       default n
+       help
+         Say Y here to build-in dual core test module for dual core test.
+
+config CPLB_INFO
+       bool "Display the CPLB information"
+       help
+         Display the CPLB information.
+
+config ACCESS_CHECK
+       bool "Check the user pointer address"
+       default y
+       help
+         Usually the pointer transfer from user space is checked to see if its
+         address is in the kernel space.
+
+         Say N here to disable that check to improve the performance.
+
+endmenu
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
new file mode 100644 (file)
index 0000000..52d4dbd
--- /dev/null
@@ -0,0 +1,80 @@
+#
+# arch/blackfin/Makefile
+#
+# 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.
+#
+
+
+CROSS_COMPILE    ?= bfin-uclinux-
+LDFLAGS_vmlinux  := -X
+OBJCOPYFLAGS     := -O binary -R .note -R .comment -S
+GZFLAGS          := -9
+
+CFLAGS_MODULE    += -mlong-calls
+KALLSYMS         += --symbol-prefix=_
+
+
+# setup the machine name and the machine dependent settings
+machine-$(CONFIG_BF531) := bf533
+machine-$(CONFIG_BF532) := bf533
+machine-$(CONFIG_BF533) := bf533
+machine-$(CONFIG_BF534) := bf537
+machine-$(CONFIG_BF536) := bf537
+machine-$(CONFIG_BF537) := bf537
+machine-$(CONFIG_BF561) := bf561
+MACHINE := $(machine-y)
+export MACHINE
+
+
+head-y   := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
+
+core-y   += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
+
+# If we have a machine-specific directory, then include it in the build.
+ifneq ($(machine-y),)
+core-y   += arch/$(ARCH)/mach-$(MACHINE)/
+core-y   += arch/$(ARCH)/mach-$(MACHINE)/boards/
+endif
+
+libs-y   += arch/$(ARCH)/lib/
+
+drivers-$(CONFIG_OPROFILE) += arch/$(ARCH)/oprofile/
+
+
+
+#      Update machine arch symlinks if something which affects
+#      them changed.  We use .mach to indicate when they were updated
+#      last, otherwise make uses the target directory mtime.
+
+include/asm-blackfin/.mach: $(wildcard include/config/arch/*.h) include/config/auto.conf
+       @echo '  SYMLINK include/asm-$(ARCH)/mach-$(MACHINE) -> include/asm-$(ARCH)/mach'
+ifneq ($(KBUILD_SRC),)
+       $(Q)mkdir -p include/asm-$(ARCH)
+       $(Q)ln -fsn $(srctree)/include/asm-$(ARCH)/mach-$(MACHINE) include/asm-$(ARCH)/mach
+else
+       $(Q)ln -fsn mach-$(MACHINE) include/asm-$(ARCH)/mach
+endif
+       @touch $@
+
+CLEAN_FILES += \
+       include/asm-$(ARCH)/asm-offsets.h \
+       arch/$(ARCH)/kernel/asm-offsets.s \
+       include/asm-$(ARCH)/mach \
+       include/asm-$(ARCH)/.mach
+
+archprepare: include/asm-blackfin/.mach
+archclean:
+       $(Q)$(MAKE) $(clean)=$(boot)
+
+
+all: vmImage
+boot := arch/$(ARCH)/boot
+BOOT_TARGETS = vmImage
+.PHONY: $(BOOT_TARGETS)
+$(BOOT_TARGETS): vmlinux
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+define archhelp
+  echo  '* vmImage         - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)'
+endef
diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile
new file mode 100644 (file)
index 0000000..49e8098
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# arch/blackfin/boot/Makefile
+#
+# 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.
+#
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+targets := vmImage
+extra-y += vmlinux.bin vmlinux.gz
+
+quiet_cmd_uimage = UIMAGE  $@
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
+                   -C gzip -a $(CONFIG_BOOT_LOAD) -e $(CONFIG_BOOT_LOAD) -n 'Linux-$(KERNELRELEASE)' \
+                   -d $< $@
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+       $(call if_changed,objcopy)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,gzip)
+
+$(obj)/vmImage: $(obj)/vmlinux.gz
+       $(call if_changed,uimage)
+       @echo 'Kernel: $@ is ready'
diff --git a/arch/blackfin/defconfig b/arch/blackfin/defconfig
new file mode 100644 (file)
index 0000000..d5904ca
--- /dev/null
@@ -0,0 +1,1314 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_UCLINUX=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+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_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# 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 is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS 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_LIMIT_PAGECACHE is not set
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+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=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF535 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+CONFIG_BLACKFIN=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+CONFIG_BFIN537_STAMP=y
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC32M8A2_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# PORT F/G Selection
+#
+CONFIG_BF537_PORT_F=y
+# CONFIG_BF537_PORT_G is not set
+# CONFIG_BF537_PORT_H is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PROG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+
+#
+# Board customizations
+#
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=25000000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Console UART Setup
+#
+# CONFIG_BAUD_9600 is not set
+# CONFIG_BAUD_19200 is not set
+# CONFIG_BAUD_38400 is not set
+CONFIG_BAUD_57600=y
+# CONFIG_BAUD_115200 is not set
+CONFIG_BAUD_NO_PARITY=y
+# CONFIG_BAUD_PARITY is not set
+CONFIG_BAUD_1_STOPBIT=y
+# CONFIG_BAUD_2_STOPBIT is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+# CONFIG_PM_WAKEUP_GPIO_API is not set
+CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY 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 is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# 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 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL 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 is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# 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=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER 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 is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+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 is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# 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 is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+
+#
+# FLASH_EBIU_AMBCTL Control
+#
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# 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=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM 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
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK 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 is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII 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 is not set
+# CONFIG_SLIP is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE 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=m
+# 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=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS is not set
+CONFIG_TWI_KEYPAD=m
+CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_TWI_LCD=m
+CONFIG_TWI_LCD_SLAVE_ADDR=34
+# CONFIG_AD5304 is not set
+# 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_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART1 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+CONFIG_CAN4LINUX=y
+
+#
+# linux embedded drivers
+#
+# CONFIG_CAN_MCF5282 is not set
+# CONFIG_CAN_UNCTWINCAN is not set
+CONFIG_CAN_BLACKFIN=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+CONFIG_BLACKFIN_DPMC=y
+# 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_BFIN_GPIO is not set
+CONFIG_I2C_BFIN_TWI=m
+CONFIG_TWICLK_KHZ=50
+# 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 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_AD5252=m
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 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
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_BFIN=y
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# 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_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 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_LM70 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_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 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_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB=m
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_BFIN_7171=m
+CONFIG_FB_BFIN_7393=m
+CONFIG_NTSC=y
+# CONFIG_PAL is not set
+# CONFIG_NTSC_640x480 is not set
+# CONFIG_PAL_640x480 is not set
+# CONFIG_NTSC_YCBCR is not set
+# CONFIG_PAL_YCBCR is not set
+CONFIG_ADV7393_1XMEM=y
+# CONFIG_ADV7393_2XMEM is not set
+CONFIG_FB_BF537_LQ035=m
+CONFIG_LQ035_SLAVE_ADDR=0x58
+# CONFIG_FB_BFIN_LANDSCAPE is not set
+# CONFIG_FB_BFIN_BGR is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# 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_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# 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 is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS 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_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN 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=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+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 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# 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 is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+CONFIG_CPLB_INFO=y
+# CONFIG_NO_ACCESS_CHECK is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
new file mode 100644 (file)
index 0000000..f3b7d2f
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# arch/blackfin/kernel/Makefile
+#
+
+extra-y := init_task.o vmlinux.lds
+
+obj-y := \
+       entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
+       sys_bfin.o time.o traps.o irqchip.o dma-mapping.o bfin_gpio.o \
+       flat.o
+
+obj-$(CONFIG_MODULES)                += module.o
+obj-$(CONFIG_BFIN_DMA_5XX)           += bfin_dma_5xx.o
+obj-$(CONFIG_DUAL_CORE_TEST_MODULE)  += dualcore_test.o
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..41d9a9f
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * File:         arch/blackfin/kernel/asm-offsets.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  generate definitions needed by assembly language modules.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <asm/irq.h>
+#include <asm/thread_info.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+int main(void)
+{
+       /* offsets into the task struct */
+       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+       DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
+       DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+       DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+       DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
+
+       /* offsets into the irq_cpustat_t struct */
+       DEFINE(CPUSTAT_SOFTIRQ_PENDING,
+              offsetof(irq_cpustat_t, __softirq_pending));
+
+       /* offsets into the thread struct */
+       DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+       DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+       DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat));
+       DEFINE(PT_SR, offsetof(struct thread_struct, seqstat));
+       DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+       DEFINE(THREAD_PC, offsetof(struct thread_struct, pc));
+       DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
+
+       /* offsets into the pt_regs */
+       DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0));
+       DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc));
+       DEFINE(PT_R0, offsetof(struct pt_regs, r0));
+       DEFINE(PT_R1, offsetof(struct pt_regs, r1));
+       DEFINE(PT_R2, offsetof(struct pt_regs, r2));
+       DEFINE(PT_R3, offsetof(struct pt_regs, r3));
+       DEFINE(PT_R4, offsetof(struct pt_regs, r4));
+       DEFINE(PT_R5, offsetof(struct pt_regs, r5));
+       DEFINE(PT_R6, offsetof(struct pt_regs, r6));
+       DEFINE(PT_R7, offsetof(struct pt_regs, r7));
+
+       DEFINE(PT_P0, offsetof(struct pt_regs, p0));
+       DEFINE(PT_P1, offsetof(struct pt_regs, p1));
+       DEFINE(PT_P2, offsetof(struct pt_regs, p2));
+       DEFINE(PT_P3, offsetof(struct pt_regs, p3));
+       DEFINE(PT_P4, offsetof(struct pt_regs, p4));
+       DEFINE(PT_P5, offsetof(struct pt_regs, p5));
+
+       DEFINE(PT_FP, offsetof(struct pt_regs, fp));
+       DEFINE(PT_USP, offsetof(struct pt_regs, usp));
+       DEFINE(PT_I0, offsetof(struct pt_regs, i0));
+       DEFINE(PT_I1, offsetof(struct pt_regs, i1));
+       DEFINE(PT_I2, offsetof(struct pt_regs, i2));
+       DEFINE(PT_I3, offsetof(struct pt_regs, i3));
+       DEFINE(PT_M0, offsetof(struct pt_regs, m0));
+       DEFINE(PT_M1, offsetof(struct pt_regs, m1));
+       DEFINE(PT_M2, offsetof(struct pt_regs, m2));
+       DEFINE(PT_M3, offsetof(struct pt_regs, m3));
+       DEFINE(PT_L0, offsetof(struct pt_regs, l0));
+       DEFINE(PT_L1, offsetof(struct pt_regs, l1));
+       DEFINE(PT_L2, offsetof(struct pt_regs, l2));
+       DEFINE(PT_L3, offsetof(struct pt_regs, l3));
+       DEFINE(PT_B0, offsetof(struct pt_regs, b0));
+       DEFINE(PT_B1, offsetof(struct pt_regs, b1));
+       DEFINE(PT_B2, offsetof(struct pt_regs, b2));
+       DEFINE(PT_B3, offsetof(struct pt_regs, b3));
+       DEFINE(PT_A0X, offsetof(struct pt_regs, a0x));
+       DEFINE(PT_A0W, offsetof(struct pt_regs, a0w));
+       DEFINE(PT_A1X, offsetof(struct pt_regs, a1x));
+       DEFINE(PT_A1W, offsetof(struct pt_regs, a1w));
+       DEFINE(PT_LC0, offsetof(struct pt_regs, lc0));
+       DEFINE(PT_LC1, offsetof(struct pt_regs, lc1));
+       DEFINE(PT_LT0, offsetof(struct pt_regs, lt0));
+       DEFINE(PT_LT1, offsetof(struct pt_regs, lt1));
+       DEFINE(PT_LB0, offsetof(struct pt_regs, lb0));
+       DEFINE(PT_LB1, offsetof(struct pt_regs, lb1));
+       DEFINE(PT_ASTAT, offsetof(struct pt_regs, astat));
+       DEFINE(PT_RESERVED, offsetof(struct pt_regs, reserved));
+       DEFINE(PT_RETS, offsetof(struct pt_regs, rets));
+       DEFINE(PT_PC, offsetof(struct pt_regs, pc));
+       DEFINE(PT_RETX, offsetof(struct pt_regs, retx));
+       DEFINE(PT_RETN, offsetof(struct pt_regs, retn));
+       DEFINE(PT_RETE, offsetof(struct pt_regs, rete));
+       DEFINE(PT_SEQSTAT, offsetof(struct pt_regs, seqstat));
+       DEFINE(PT_SYSCFG, offsetof(struct pt_regs, syscfg));
+       DEFINE(PT_IPEND, offsetof(struct pt_regs, ipend));
+       DEFINE(SIZEOF_PTREGS, sizeof(struct pt_regs));
+       DEFINE(PT_TEXT_ADDR, sizeof(struct pt_regs));        /* Needed by gdb */
+       DEFINE(PT_TEXT_END_ADDR, 4 + sizeof(struct pt_regs));/* Needed by gdb */
+       DEFINE(PT_DATA_ADDR, 8 + sizeof(struct pt_regs));    /* Needed by gdb */
+       DEFINE(PT_FDPIC_EXEC, 12 + sizeof(struct pt_regs));  /* Needed by gdb */
+       DEFINE(PT_FDPIC_INTERP, 16 + sizeof(struct pt_regs));/* Needed by gdb */
+
+       /* signal defines */
+       DEFINE(SIGSEGV, SIGSEGV);
+       DEFINE(SIGTRAP, SIGTRAP);
+
+       return 0;
+}
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
new file mode 100644 (file)
index 0000000..8ea079e
--- /dev/null
@@ -0,0 +1,742 @@
+/*
+ * File:         arch/blackfin/kernel/bfin_dma_5xx.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+
+#include <asm/dma.h>
+#include <asm/cacheflush.h>
+
+/* Remove unused code not exported by symbol or internally called */
+#define REMOVE_DEAD_CODE
+
+/**************************************************************************
+ * Global Variables
+***************************************************************************/
+
+static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
+#if defined (CONFIG_BF561)
+static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+       (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_7_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_11_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_7_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_11_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+       (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+};
+#else
+static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+       (struct dma_register *) DMA0_NEXT_DESC_PTR,
+       (struct dma_register *) DMA1_NEXT_DESC_PTR,
+       (struct dma_register *) DMA2_NEXT_DESC_PTR,
+       (struct dma_register *) DMA3_NEXT_DESC_PTR,
+       (struct dma_register *) DMA4_NEXT_DESC_PTR,
+       (struct dma_register *) DMA5_NEXT_DESC_PTR,
+       (struct dma_register *) DMA6_NEXT_DESC_PTR,
+       (struct dma_register *) DMA7_NEXT_DESC_PTR,
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
+       (struct dma_register *) DMA8_NEXT_DESC_PTR,
+       (struct dma_register *) DMA9_NEXT_DESC_PTR,
+       (struct dma_register *) DMA10_NEXT_DESC_PTR,
+       (struct dma_register *) DMA11_NEXT_DESC_PTR,
+#endif
+       (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+       (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+#endif
+
+/*------------------------------------------------------------------------------
+ *       Set the Buffer Clear bit in the Configuration register of specific DMA
+ *       channel. This will stop the descriptor based DMA operation.
+ *-----------------------------------------------------------------------------*/
+static void clear_dma_buffer(unsigned int channel)
+{
+       dma_ch[channel].regs->cfg |= RESTART;
+       SSYNC();
+       dma_ch[channel].regs->cfg &= ~RESTART;
+       SSYNC();
+}
+
+int __init blackfin_dma_init(void)
+{
+       int i;
+
+       printk(KERN_INFO "Blackfin DMA Controller\n");
+
+       for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
+               dma_ch[i].chan_status = DMA_CHANNEL_FREE;
+               dma_ch[i].regs = base_addr[i];
+               mutex_init(&(dma_ch[i].dmalock));
+       }
+
+       return 0;
+}
+
+arch_initcall(blackfin_dma_init);
+
+/*
+ *     Form the channel find the irq number for that channel.
+ */
+#if !defined(CONFIG_BF561)
+
+static int bf533_channel2irq(unsigned int channel)
+{
+       int ret_irq = -1;
+
+       switch (channel) {
+       case CH_PPI:
+               ret_irq = IRQ_PPI;
+               break;
+
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
+       case CH_EMAC_RX:
+               ret_irq = IRQ_MAC_RX;
+               break;
+
+       case CH_EMAC_TX:
+               ret_irq = IRQ_MAC_TX;
+               break;
+
+       case CH_UART1_RX:
+               ret_irq = IRQ_UART1_RX;
+               break;
+
+       case CH_UART1_TX:
+               ret_irq = IRQ_UART1_TX;
+               break;
+#endif
+
+       case CH_SPORT0_RX:
+               ret_irq = IRQ_SPORT0_RX;
+               break;
+
+       case CH_SPORT0_TX:
+               ret_irq = IRQ_SPORT0_TX;
+               break;
+
+       case CH_SPORT1_RX:
+               ret_irq = IRQ_SPORT1_RX;
+               break;
+
+       case CH_SPORT1_TX:
+               ret_irq = IRQ_SPORT1_TX;
+               break;
+
+       case CH_SPI:
+               ret_irq = IRQ_SPI;
+               break;
+
+       case CH_UART_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+
+       case CH_UART_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+
+       case CH_MEM_STREAM0_SRC:
+       case CH_MEM_STREAM0_DEST:
+               ret_irq = IRQ_MEM_DMA0;
+               break;
+
+       case CH_MEM_STREAM1_SRC:
+       case CH_MEM_STREAM1_DEST:
+               ret_irq = IRQ_MEM_DMA1;
+               break;
+       }
+       return ret_irq;
+}
+
+# define channel2irq(channel) bf533_channel2irq(channel)
+
+#else
+
+static int bf561_channel2irq(unsigned int channel)
+{
+       int ret_irq = -1;
+
+       switch (channel) {
+       case CH_PPI0:
+               ret_irq = IRQ_PPI0;
+               break;
+       case CH_PPI1:
+               ret_irq = IRQ_PPI1;
+               break;
+       case CH_SPORT0_RX:
+               ret_irq = IRQ_SPORT0_RX;
+               break;
+       case CH_SPORT0_TX:
+               ret_irq = IRQ_SPORT0_TX;
+               break;
+       case CH_SPORT1_RX:
+               ret_irq = IRQ_SPORT1_RX;
+               break;
+       case CH_SPORT1_TX:
+               ret_irq = IRQ_SPORT1_TX;
+               break;
+       case CH_SPI:
+               ret_irq = IRQ_SPI;
+               break;
+       case CH_UART_RX:
+               ret_irq = IRQ_UART_RX;
+               break;
+       case CH_UART_TX:
+               ret_irq = IRQ_UART_TX;
+               break;
+
+       case CH_MEM_STREAM0_SRC:
+       case CH_MEM_STREAM0_DEST:
+               ret_irq = IRQ_MEM_DMA0;
+               break;
+       case CH_MEM_STREAM1_SRC:
+       case CH_MEM_STREAM1_DEST:
+               ret_irq = IRQ_MEM_DMA1;
+               break;
+       case CH_MEM_STREAM2_SRC:
+       case CH_MEM_STREAM2_DEST:
+               ret_irq = IRQ_MEM_DMA2;
+               break;
+       case CH_MEM_STREAM3_SRC:
+       case CH_MEM_STREAM3_DEST:
+               ret_irq = IRQ_MEM_DMA3;
+               break;
+
+       case CH_IMEM_STREAM0_SRC:
+       case CH_IMEM_STREAM0_DEST:
+               ret_irq = IRQ_IMEM_DMA0;
+               break;
+       case CH_IMEM_STREAM1_SRC:
+       case CH_IMEM_STREAM1_DEST:
+               ret_irq = IRQ_IMEM_DMA1;
+               break;
+       }
+       return ret_irq;
+}
+
+# define channel2irq(channel) bf561_channel2irq(channel)
+
+#endif
+
+/*------------------------------------------------------------------------------
+ *     Request the specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+int request_dma(unsigned int channel, char *device_id)
+{
+
+       pr_debug("request_dma() : BEGIN \n");
+       mutex_lock(&(dma_ch[channel].dmalock));
+
+       if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
+           || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
+               mutex_unlock(&(dma_ch[channel].dmalock));
+               pr_debug("DMA CHANNEL IN USE  \n");
+               return -EBUSY;
+       } else {
+               dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
+               pr_debug("DMA CHANNEL IS ALLOCATED  \n");
+       }
+
+       mutex_unlock(&(dma_ch[channel].dmalock));
+
+       dma_ch[channel].device_id = device_id;
+       dma_ch[channel].irq_callback = NULL;
+
+       /* This is to be enabled by putting a restriction -
+        * you have to request DMA, before doing any operations on
+        * descriptor/channel
+        */
+       pr_debug("request_dma() : END  \n");
+       return channel;
+}
+EXPORT_SYMBOL(request_dma);
+
+int set_dma_callback(unsigned int channel, dma_interrupt_t callback, void *data)
+{
+       int ret_irq = 0;
+
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       if (callback != NULL) {
+               int ret_val;
+               ret_irq = channel2irq(channel);
+
+               dma_ch[channel].data = data;
+
+               ret_val =
+                   request_irq(ret_irq, (void *)callback, IRQF_DISABLED,
+                               dma_ch[channel].device_id, data);
+               if (ret_val) {
+                       printk(KERN_NOTICE
+                              "Request irq in DMA engine failed.\n");
+                       return -EPERM;
+               }
+               dma_ch[channel].irq_callback = callback;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(set_dma_callback);
+
+void free_dma(unsigned int channel)
+{
+       int ret_irq;
+
+       pr_debug("freedma() : BEGIN \n");
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       /* Halt the DMA */
+       disable_dma(channel);
+       clear_dma_buffer(channel);
+
+       if (dma_ch[channel].irq_callback != NULL) {
+               ret_irq = channel2irq(channel);
+               free_irq(ret_irq, dma_ch[channel].data);
+       }
+
+       /* Clear the DMA Variable in the Channel */
+       mutex_lock(&(dma_ch[channel].dmalock));
+       dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
+       mutex_unlock(&(dma_ch[channel].dmalock));
+
+       pr_debug("freedma() : END \n");
+}
+EXPORT_SYMBOL(free_dma);
+
+void dma_enable_irq(unsigned int channel)
+{
+       int ret_irq;
+
+       pr_debug("dma_enable_irq() : BEGIN \n");
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       ret_irq = channel2irq(channel);
+       enable_irq(ret_irq);
+}
+EXPORT_SYMBOL(dma_enable_irq);
+
+void dma_disable_irq(unsigned int channel)
+{
+       int ret_irq;
+
+       pr_debug("dma_disable_irq() : BEGIN \n");
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       ret_irq = channel2irq(channel);
+       disable_irq(ret_irq);
+}
+EXPORT_SYMBOL(dma_disable_irq);
+
+int dma_channel_active(unsigned int channel)
+{
+       if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+EXPORT_SYMBOL(dma_channel_active);
+
+/*------------------------------------------------------------------------------
+*      stop the specific DMA channel.
+*-----------------------------------------------------------------------------*/
+void disable_dma(unsigned int channel)
+{
+       pr_debug("stop_dma() : BEGIN \n");
+
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->cfg &= ~DMAEN;    /* Clean the enable bit */
+       SSYNC();
+       dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
+       /* Needs to be enabled Later */
+       pr_debug("stop_dma() : END \n");
+       return;
+}
+EXPORT_SYMBOL(disable_dma);
+
+void enable_dma(unsigned int channel)
+{
+       pr_debug("enable_dma() : BEGIN \n");
+
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
+       dma_ch[channel].regs->curr_x_count = 0;
+       dma_ch[channel].regs->curr_y_count = 0;
+
+       dma_ch[channel].regs->cfg |= DMAEN;     /* Set the enable bit */
+       SSYNC();
+       pr_debug("enable_dma() : END \n");
+       return;
+}
+EXPORT_SYMBOL(enable_dma);
+
+/*------------------------------------------------------------------------------
+*              Set the Start Address register for the specific DMA channel
+*              This function can be used for register based DMA,
+*              to setup the start address
+*              addr:           Starting address of the DMA Data to be transferred.
+*-----------------------------------------------------------------------------*/
+void set_dma_start_addr(unsigned int channel, unsigned long addr)
+{
+       pr_debug("set_dma_start_addr() : BEGIN \n");
+
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->start_addr = addr;
+       SSYNC();
+       pr_debug("set_dma_start_addr() : END\n");
+}
+EXPORT_SYMBOL(set_dma_start_addr);
+
+void set_dma_next_desc_addr(unsigned int channel, unsigned long addr)
+{
+       pr_debug("set_dma_next_desc_addr() : BEGIN \n");
+
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->next_desc_ptr = addr;
+       SSYNC();
+       pr_debug("set_dma_start_addr() : END\n");
+}
+EXPORT_SYMBOL(set_dma_next_desc_addr);
+
+void set_dma_x_count(unsigned int channel, unsigned short x_count)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->x_count = x_count;
+       SSYNC();
+}
+EXPORT_SYMBOL(set_dma_x_count);
+
+void set_dma_y_count(unsigned int channel, unsigned short y_count)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->y_count = y_count;
+       SSYNC();
+}
+EXPORT_SYMBOL(set_dma_y_count);
+
+void set_dma_x_modify(unsigned int channel, short x_modify)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->x_modify = x_modify;
+       SSYNC();
+}
+EXPORT_SYMBOL(set_dma_x_modify);
+
+void set_dma_y_modify(unsigned int channel, short y_modify)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->y_modify = y_modify;
+       SSYNC();
+}
+EXPORT_SYMBOL(set_dma_y_modify);
+
+void set_dma_config(unsigned int channel, unsigned short config)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->cfg = config;
+       SSYNC();
+}
+EXPORT_SYMBOL(set_dma_config);
+
+unsigned short
+set_bfin_dma_config(char direction, char flow_mode,
+                   char intr_mode, char dma_mode, char width)
+{
+       unsigned short config;
+
+       config =
+           ((direction << 1) | (width << 2) | (dma_mode << 4) |
+            (intr_mode << 6) | (flow_mode << 12) | RESTART);
+       return config;
+}
+EXPORT_SYMBOL(set_bfin_dma_config);
+
+void set_dma_sg(unsigned int channel, struct dmasg * sg, int nr_sg)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       dma_ch[channel].regs->cfg |= ((nr_sg & 0x0F) << 8);
+
+       dma_ch[channel].regs->next_desc_ptr = (unsigned int)sg;
+
+       SSYNC();
+}
+EXPORT_SYMBOL(set_dma_sg);
+
+/*------------------------------------------------------------------------------
+ *     Get the DMA status of a specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+unsigned short get_dma_curr_irqstat(unsigned int channel)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       return dma_ch[channel].regs->irq_status;
+}
+EXPORT_SYMBOL(get_dma_curr_irqstat);
+
+/*------------------------------------------------------------------------------
+ *     Clear the DMA_DONE bit in DMA status. Stop the DMA completion interrupt.
+ *-----------------------------------------------------------------------------*/
+void clear_dma_irqstat(unsigned int channel)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+       dma_ch[channel].regs->irq_status |= 3;
+}
+EXPORT_SYMBOL(clear_dma_irqstat);
+
+/*------------------------------------------------------------------------------
+ *     Get current DMA xcount of a specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+unsigned short get_dma_curr_xcount(unsigned int channel)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       return dma_ch[channel].regs->curr_x_count;
+}
+EXPORT_SYMBOL(get_dma_curr_xcount);
+
+/*------------------------------------------------------------------------------
+ *     Get current DMA ycount of a specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+unsigned short get_dma_curr_ycount(unsigned int channel)
+{
+       BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+              && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+       return dma_ch[channel].regs->curr_y_count;
+}
+EXPORT_SYMBOL(get_dma_curr_ycount);
+
+void *dma_memcpy(void *dest, const void *src, size_t size)
+{
+       int direction;  /* 1 - address decrease, 0 - address increase */
+       int flag_align; /* 1 - address aligned,  0 - address unaligned */
+       int flag_2D;    /* 1 - 2D DMA needed,    0 - 1D DMA needed */
+
+       if (size <= 0)
+               return NULL;
+
+       if ((unsigned long)src < memory_end)
+               blackfin_dcache_flush_range((unsigned int)src,
+                                           (unsigned int)(src + size));
+
+       bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+       if ((unsigned long)src < (unsigned long)dest)
+               direction = 1;
+       else
+               direction = 0;
+
+       if ((((unsigned long)dest % 2) == 0) && (((unsigned long)src % 2) == 0)
+           && ((size % 2) == 0))
+               flag_align = 1;
+       else
+               flag_align = 0;
+
+       if (size > 0x10000)     /* size > 64K */
+               flag_2D = 1;
+       else
+               flag_2D = 0;
+
+       /* Setup destination and source start address */
+       if (direction) {
+               if (flag_align) {
+                       bfin_write_MDMA_D0_START_ADDR(dest + size - 2);
+                       bfin_write_MDMA_S0_START_ADDR(src + size - 2);
+               } else {
+                       bfin_write_MDMA_D0_START_ADDR(dest + size - 1);
+                       bfin_write_MDMA_S0_START_ADDR(src + size - 1);
+               }
+       } else {
+               bfin_write_MDMA_D0_START_ADDR(dest);
+               bfin_write_MDMA_S0_START_ADDR(src);
+       }
+
+       /* Setup destination and source xcount */
+       if (flag_2D) {
+               if (flag_align) {
+                       bfin_write_MDMA_D0_X_COUNT(1024 / 2);
+                       bfin_write_MDMA_S0_X_COUNT(1024 / 2);
+               } else {
+                       bfin_write_MDMA_D0_X_COUNT(1024);
+                       bfin_write_MDMA_S0_X_COUNT(1024);
+               }
+               bfin_write_MDMA_D0_Y_COUNT(size >> 10);
+               bfin_write_MDMA_S0_Y_COUNT(size >> 10);
+       } else {
+               if (flag_align) {
+                       bfin_write_MDMA_D0_X_COUNT(size / 2);
+                       bfin_write_MDMA_S0_X_COUNT(size / 2);
+               } else {
+                       bfin_write_MDMA_D0_X_COUNT(size);
+                       bfin_write_MDMA_S0_X_COUNT(size);
+               }
+       }
+
+       /* Setup destination and source xmodify and ymodify */
+       if (direction) {
+               if (flag_align) {
+                       bfin_write_MDMA_D0_X_MODIFY(-2);
+                       bfin_write_MDMA_S0_X_MODIFY(-2);
+                       if (flag_2D) {
+                               bfin_write_MDMA_D0_Y_MODIFY(-2);
+                               bfin_write_MDMA_S0_Y_MODIFY(-2);
+                       }
+               } else {
+                       bfin_write_MDMA_D0_X_MODIFY(-1);
+                       bfin_write_MDMA_S0_X_MODIFY(-1);
+                       if (flag_2D) {
+                               bfin_write_MDMA_D0_Y_MODIFY(-1);
+                               bfin_write_MDMA_S0_Y_MODIFY(-1);
+                       }
+               }
+       } else {
+               if (flag_align) {
+                       bfin_write_MDMA_D0_X_MODIFY(2);
+                       bfin_write_MDMA_S0_X_MODIFY(2);
+                       if (flag_2D) {
+                               bfin_write_MDMA_D0_Y_MODIFY(2);
+                               bfin_write_MDMA_S0_Y_MODIFY(2);
+                       }
+               } else {
+                       bfin_write_MDMA_D0_X_MODIFY(1);
+                       bfin_write_MDMA_S0_X_MODIFY(1);
+                       if (flag_2D) {
+                               bfin_write_MDMA_D0_Y_MODIFY(1);
+                               bfin_write_MDMA_S0_Y_MODIFY(1);
+                       }
+               }
+       }
+
+       /* Enable source DMA */
+       if (flag_2D) {
+               if (flag_align) {
+                       bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D | WDSIZE_16);
+                       bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D | WDSIZE_16);
+               } else {
+                       bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D);
+                       bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D);
+               }
+       } else {
+               if (flag_align) {
+                       bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
+                       bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
+               } else {
+                       bfin_write_MDMA_S0_CONFIG(DMAEN);
+                       bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN);
+               }
+       }
+
+       while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+               ;
+
+       bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() |
+                                     (DMA_DONE | DMA_ERR));
+
+       bfin_write_MDMA_S0_CONFIG(0);
+       bfin_write_MDMA_D0_CONFIG(0);
+
+       if ((unsigned long)dest < memory_end)
+               blackfin_dcache_invalidate_range((unsigned int)dest,
+                                                (unsigned int)(dest + size));
+
+       return dest;
+}
+EXPORT_SYMBOL(dma_memcpy);
+
+void *safe_dma_memcpy(void *dest, const void *src, size_t size)
+{
+       int flags = 0;
+       void *addr;
+       local_irq_save(flags);
+       addr = dma_memcpy(dest, src, size);
+       local_irq_restore(flags);
+       return addr;
+}
+EXPORT_SYMBOL(safe_dma_memcpy);
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
new file mode 100644 (file)
index 0000000..e9f24a9
--- /dev/null
@@ -0,0 +1,637 @@
+/*
+ * File:         arch/blackfin/kernel/bfin_gpio.c
+ * Based on:
+ * Author:       Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:  GPIO Abstraction Layer
+ *
+ * Modified:
+ *               Copyright 2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+*  Number     BF537/6/4    BF561    BF533/2/1
+*
+*  GPIO_0       PF0         PF0        PF0
+*  GPIO_1       PF1         PF1        PF1
+*  GPIO_2       PF2         PF2        PF2
+*  GPIO_3       PF3         PF3        PF3
+*  GPIO_4       PF4         PF4        PF4
+*  GPIO_5       PF5         PF5        PF5
+*  GPIO_6       PF6         PF6        PF6
+*  GPIO_7       PF7         PF7        PF7
+*  GPIO_8       PF8         PF8        PF8
+*  GPIO_9       PF9         PF9        PF9
+*  GPIO_10      PF10        PF10       PF10
+*  GPIO_11      PF11        PF11       PF11
+*  GPIO_12      PF12        PF12       PF12
+*  GPIO_13      PF13        PF13       PF13
+*  GPIO_14      PF14        PF14       PF14
+*  GPIO_15      PF15        PF15       PF15
+*  GPIO_16      PG0         PF16
+*  GPIO_17      PG1         PF17
+*  GPIO_18      PG2         PF18
+*  GPIO_19      PG3         PF19
+*  GPIO_20      PG4         PF20
+*  GPIO_21      PG5         PF21
+*  GPIO_22      PG6         PF22
+*  GPIO_23      PG7         PF23
+*  GPIO_24      PG8         PF24
+*  GPIO_25      PG9         PF25
+*  GPIO_26      PG10        PF26
+*  GPIO_27      PG11        PF27
+*  GPIO_28      PG12        PF28
+*  GPIO_29      PG13        PF29
+*  GPIO_30      PG14        PF30
+*  GPIO_31      PG15        PF31
+*  GPIO_32      PH0         PF32
+*  GPIO_33      PH1         PF33
+*  GPIO_34      PH2         PF34
+*  GPIO_35      PH3         PF35
+*  GPIO_36      PH4         PF36
+*  GPIO_37      PH5         PF37
+*  GPIO_38      PH6         PF38
+*  GPIO_39      PH7         PF39
+*  GPIO_40      PH8         PF40
+*  GPIO_41      PH9         PF41
+*  GPIO_42      PH10        PF42
+*  GPIO_43      PH11        PF43
+*  GPIO_44      PH12        PF44
+*  GPIO_45      PH13        PF45
+*  GPIO_46      PH14        PF46
+*  GPIO_47      PH15        PF47
+*/
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <linux/irq.h>
+
+#ifdef BF533_FAMILY
+static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+       (struct gpio_port_t *) FIO_FLAG_D,
+};
+#endif
+
+#ifdef BF537_FAMILY
+static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+       (struct gpio_port_t *) PORTFIO,
+       (struct gpio_port_t *) PORTGIO,
+       (struct gpio_port_t *) PORTHIO,
+};
+
+static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+       (unsigned short *) PORTF_FER,
+       (unsigned short *) PORTG_FER,
+       (unsigned short *) PORTH_FER,
+};
+
+#endif
+
+#ifdef BF561_FAMILY
+static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+       (struct gpio_port_t *) FIO0_FLAG_D,
+       (struct gpio_port_t *) FIO1_FLAG_D,
+       (struct gpio_port_t *) FIO2_FLAG_D,
+};
+#endif
+
+static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+#ifdef CONFIG_PM
+static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
+static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+#ifdef BF533_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB};
+#endif
+
+#ifdef BF537_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX};
+#endif
+
+#ifdef BF561_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
+#endif
+
+#endif /* CONFIG_PM */
+
+inline int check_gpio(unsigned short gpio)
+{
+       if (gpio > MAX_BLACKFIN_GPIOS)
+               return -EINVAL;
+       return 0;
+}
+
+#ifdef BF537_FAMILY
+void port_setup(unsigned short gpio, unsigned short usage)
+{
+       if (usage == GPIO_USAGE) {
+               if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio))
+                       printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral "
+                              "usage and GPIO %d detected!\n", gpio);
+               *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+       } else
+               *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
+       SSYNC();
+}
+#else
+# define port_setup(...)  do { } while (0)
+#endif
+
+
+void default_gpio(unsigned short gpio)
+{
+       unsigned short bank,bitmask;
+
+       bank = gpio_bank(gpio);
+       bitmask = gpio_bit(gpio);
+
+       gpio_bankb[bank]->maska_clear = bitmask;
+       gpio_bankb[bank]->maskb_clear = bitmask;
+       SSYNC();
+       gpio_bankb[bank]->inen &= ~bitmask;
+       gpio_bankb[bank]->dir &= ~bitmask;
+       gpio_bankb[bank]->polar &= ~bitmask;
+       gpio_bankb[bank]->both &= ~bitmask;
+       gpio_bankb[bank]->edge &= ~bitmask;
+}
+
+
+int __init bfin_gpio_init(void)
+{
+       int i;
+
+       printk(KERN_INFO "Blackfin GPIO Controller\n");
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE)
+               reserved_map[gpio_bank(i)] = 0;
+
+#if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+# if defined(CONFIG_BFIN_MAC_RMII)
+       reserved_map[PORT_H] = 0xC373;
+# else
+       reserved_map[PORT_H] = 0xFFFF;
+# endif
+#endif
+
+       return 0;
+}
+
+arch_initcall(bfin_gpio_init);
+
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin General Purpose Ports Access Functions
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: These functions abstract direct register access
+*              to Blackfin processor General Purpose
+*              Ports Regsiters
+*
+* CAUTION: These functions do not belong to the GPIO Driver API
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+/* Set a specific bit */
+
+#define SET_GPIO(name) \
+void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
+{ \
+       unsigned long flags; \
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
+       local_irq_save(flags); \
+       if (arg) \
+               gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
+       else \
+               gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
+       local_irq_restore(flags); \
+} \
+EXPORT_SYMBOL(set_gpio_ ## name);
+
+SET_GPIO(dir)
+SET_GPIO(inen)
+SET_GPIO(polar)
+SET_GPIO(edge)
+SET_GPIO(both)
+
+
+#define SET_GPIO_SC(name) \
+void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
+{ \
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
+       if (arg) \
+               gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
+       else \
+               gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
+} \
+EXPORT_SYMBOL(set_gpio_ ## name);
+
+SET_GPIO_SC(maska)
+SET_GPIO_SC(maskb)
+
+#if defined(ANOMALY_05000311)
+void set_gpio_data(unsigned short gpio, unsigned short arg)
+{
+       unsigned long flags;
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       local_irq_save(flags);
+       if (arg)
+               gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+       else
+               gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
+       bfin_read_CHIPID();
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(set_gpio_data);
+#else
+SET_GPIO_SC(data)
+#endif
+
+
+#if defined(ANOMALY_05000311)
+void set_gpio_toggle(unsigned short gpio)
+{
+       unsigned long flags;
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       local_irq_save(flags);
+       gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+       bfin_read_CHIPID();
+       local_irq_restore(flags);
+}
+#else
+void set_gpio_toggle(unsigned short gpio)
+{
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+}
+#endif
+EXPORT_SYMBOL(set_gpio_toggle);
+
+
+/*Set current PORT date (16-bit word)*/
+
+#define SET_GPIO_P(name) \
+void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \
+{ \
+       gpio_bankb[gpio_bank(gpio)]->name = arg; \
+} \
+EXPORT_SYMBOL(set_gpiop_ ## name);
+
+SET_GPIO_P(dir)
+SET_GPIO_P(inen)
+SET_GPIO_P(polar)
+SET_GPIO_P(edge)
+SET_GPIO_P(both)
+SET_GPIO_P(maska)
+SET_GPIO_P(maskb)
+
+
+#if defined(ANOMALY_05000311)
+void set_gpiop_data(unsigned short gpio, unsigned short arg)
+{
+       unsigned long flags;
+       local_irq_save(flags);
+       gpio_bankb[gpio_bank(gpio)]->data = arg;
+       bfin_read_CHIPID();
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(set_gpiop_data);
+#else
+SET_GPIO_P(data)
+#endif
+
+
+
+/* Get a specific bit */
+
+#define GET_GPIO(name) \
+unsigned short get_gpio_ ## name(unsigned short gpio) \
+{ \
+       return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \
+} \
+EXPORT_SYMBOL(get_gpio_ ## name);
+
+GET_GPIO(dir)
+GET_GPIO(inen)
+GET_GPIO(polar)
+GET_GPIO(edge)
+GET_GPIO(both)
+GET_GPIO(maska)
+GET_GPIO(maskb)
+
+
+#if defined(ANOMALY_05000311)
+unsigned short get_gpio_data(unsigned short gpio)
+{
+       unsigned long flags;
+       unsigned short ret;
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       local_irq_save(flags);
+       ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
+       bfin_read_CHIPID();
+       local_irq_restore(flags);
+       return ret;
+}
+EXPORT_SYMBOL(get_gpio_data);
+#else
+GET_GPIO(data)
+#endif
+
+/*Get current PORT date (16-bit word)*/
+
+#define GET_GPIO_P(name) \
+unsigned short get_gpiop_ ## name(unsigned short gpio) \
+{ \
+       return (gpio_bankb[gpio_bank(gpio)]->name);\
+} \
+EXPORT_SYMBOL(get_gpiop_ ## name);
+
+GET_GPIO_P(dir)
+GET_GPIO_P(inen)
+GET_GPIO_P(polar)
+GET_GPIO_P(edge)
+GET_GPIO_P(both)
+GET_GPIO_P(maska)
+GET_GPIO_P(maskb)
+
+#if defined(ANOMALY_05000311)
+unsigned short get_gpiop_data(unsigned short gpio)
+{
+       unsigned long flags;
+       unsigned short ret;
+       local_irq_save(flags);
+       ret = gpio_bankb[gpio_bank(gpio)]->data;
+       bfin_read_CHIPID();
+       local_irq_restore(flags);
+       return ret;
+}
+EXPORT_SYMBOL(get_gpiop_data);
+#else
+GET_GPIO_P(data)
+#endif
+
+#ifdef CONFIG_PM
+/***********************************************************
+*
+* FUNCTIONS: Blackfin PM Setup API
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+* type -
+*      PM_WAKE_RISING
+*      PM_WAKE_FALLING
+*      PM_WAKE_HIGH
+*      PM_WAKE_LOW
+*      PM_WAKE_BOTH_EDGES
+*
+* DESCRIPTION: Blackfin PM Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type)
+{
+       unsigned long flags;
+
+       if ((check_gpio(gpio) < 0) || !type)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+       wakeup_flags_map[gpio] = type;
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_pm_wakeup_request);
+
+void gpio_pm_wakeup_free(unsigned short gpio)
+{
+       unsigned long flags;
+
+       if (check_gpio(gpio) < 0)
+               return;
+
+       local_irq_save(flags);
+
+       wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_pm_wakeup_free);
+
+static int bfin_gpio_wakeup_type(unsigned short gpio, unsigned char type)
+{
+       port_setup(gpio, GPIO_USAGE);
+       set_gpio_dir(gpio, 0);
+       set_gpio_inen(gpio, 1);
+
+       if (type & (PM_WAKE_RISING | PM_WAKE_FALLING))
+               set_gpio_edge(gpio, 1);
+        else
+               set_gpio_edge(gpio, 0);
+
+       if ((type & (PM_WAKE_BOTH_EDGES)) == (PM_WAKE_BOTH_EDGES))
+               set_gpio_both(gpio, 1);
+       else
+               set_gpio_both(gpio, 0);
+
+       if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW)))
+               set_gpio_polar(gpio, 1);
+       else
+               set_gpio_polar(gpio, 0);
+
+       SSYNC();
+
+       return 0;
+}
+
+u32 gpio_pm_setup(void)
+{
+       u32 sic_iwr = 0;
+       u16 bank, mask, i, gpio;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+               mask = wakeup_map[gpio_bank(i)];
+               bank = gpio_bank(i);
+
+               gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb;
+               gpio_bankb[bank]->maskb = 0;
+
+               if (mask) {
+#ifdef BF537_FAMILY
+                       gpio_bank_saved[bank].fer   = *port_fer[bank];
+#endif
+                       gpio_bank_saved[bank].inen  = gpio_bankb[bank]->inen;
+                       gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
+                       gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;
+                       gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;
+                       gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;
+
+                       gpio = i;
+
+                       while (mask) {
+                               if (mask & 1) {
+                                       bfin_gpio_wakeup_type(gpio, wakeup_flags_map[gpio]);
+                                       set_gpio_data(gpio, 0); /*Clear*/
+                               }
+                               gpio++;
+                               mask >>= 1;
+                       }
+
+                       sic_iwr |= 1 << (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
+                       gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
+               }
+       }
+
+       if (sic_iwr)
+               return sic_iwr;
+       else
+               return IWR_ENABLE_ALL;
+}
+
+
+void gpio_pm_restore(void)
+{
+       u16 bank, mask, i;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+               mask = wakeup_map[gpio_bank(i)];
+               bank = gpio_bank(i);
+
+               if (mask) {
+#ifdef BF537_FAMILY
+                       *port_fer[bank]         = gpio_bank_saved[bank].fer;
+#endif
+                       gpio_bankb[bank]->inen  = gpio_bank_saved[bank].inen;
+                       gpio_bankb[bank]->dir   = gpio_bank_saved[bank].dir;
+                       gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
+                       gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;
+                       gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;
+               }
+
+               gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
+       }
+}
+
+#endif
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: Blackfin GPIO Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+int gpio_request(unsigned short gpio, const char *label)
+{
+       unsigned long flags;
+
+       if (check_gpio(gpio) < 0)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+               printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
+               dump_stack();
+               local_irq_restore(flags);
+               return -EBUSY;
+       }
+       reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+
+       local_irq_restore(flags);
+
+       port_setup(gpio, GPIO_USAGE);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+
+void gpio_free(unsigned short gpio)
+{
+       unsigned long flags;
+
+       if (check_gpio(gpio) < 0)
+               return;
+
+       local_irq_save(flags);
+
+       if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+               printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
+               dump_stack();
+               local_irq_restore(flags);
+               return;
+       }
+
+       default_gpio(gpio);
+
+       reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_free);
+
+
+void gpio_direction_input(unsigned short gpio)
+{
+       unsigned long flags;
+
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+       local_irq_save(flags);
+       gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
+       gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+void gpio_direction_output(unsigned short gpio)
+{
+       unsigned long flags;
+
+       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+       local_irq_save(flags);
+       gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+       gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_output);
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
new file mode 100644 (file)
index 0000000..f64ecb6
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * File:         arch/blackfin/kernel/bfin_ksyms.c
+ * Based on:     none - original work
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <asm/irq.h>
+#include <asm/checksum.h>
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(dump_thread);
+
+EXPORT_SYMBOL(ip_fast_csum);
+
+EXPORT_SYMBOL(kernel_thread);
+
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__down_interruptible);
+
+EXPORT_SYMBOL(is_in_rom);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/* The following are special because they're not called
+ * explicitly (the C compiler generates them).  Fortunately,
+ * their interface isn't gonna change any time soon now, so
+ * it's OK to leave it out of version control.
+ */
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(get_wchan);
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler...  (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __smulsi3_highpart(void);
+extern void __umulsi3_highpart(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+
+/* gcc lib functions */
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__umulsi3_highpart);
+EXPORT_SYMBOL(__smulsi3_highpart);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(irq_flags);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(blackfin_dcache_invalidate_range);
+EXPORT_SYMBOL(blackfin_icache_dcache_flush_range);
+EXPORT_SYMBOL(blackfin_icache_flush_range);
+EXPORT_SYMBOL(blackfin_dcache_flush_range);
+EXPORT_SYMBOL(blackfin_dflush_page);
+
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(__init_begin);
+EXPORT_SYMBOL(__init_end);
+EXPORT_SYMBOL(_ebss_l1);
+EXPORT_SYMBOL(_stext_l1);
+EXPORT_SYMBOL(_etext_l1);
+EXPORT_SYMBOL(_sdata_l1);
+EXPORT_SYMBOL(_ebss_b_l1);
+EXPORT_SYMBOL(_sdata_b_l1);
diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
new file mode 100644 (file)
index 0000000..539eb24
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * File:         arch/blackfin/kernel/dma-mapping.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  Dynamic DMA mapping support.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/bfin-global.h>
+
+static spinlock_t dma_page_lock;
+static unsigned int *dma_page;
+static unsigned int dma_pages;
+static unsigned long dma_base;
+static unsigned long dma_size;
+static unsigned int dma_initialized;
+
+void dma_alloc_init(unsigned long start, unsigned long end)
+{
+       spin_lock_init(&dma_page_lock);
+       dma_initialized = 0;
+
+       dma_page = (unsigned int *)__get_free_page(GFP_KERNEL);
+       memset(dma_page, 0, PAGE_SIZE);
+       dma_base = PAGE_ALIGN(start);
+       dma_size = PAGE_ALIGN(end) - PAGE_ALIGN(start);
+       dma_pages = dma_size >> PAGE_SHIFT;
+       memset((void *)dma_base, 0, DMA_UNCACHED_REGION);
+       dma_initialized = 1;
+
+       printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __FUNCTION__,
+              dma_page, dma_pages, dma_base);
+}
+
+static inline unsigned int get_pages(size_t size)
+{
+       return ((size - 1) >> PAGE_SHIFT) + 1;
+}
+
+static unsigned long __alloc_dma_pages(unsigned int pages)
+{
+       unsigned long ret = 0, flags;
+       int i, count = 0;
+
+       if (dma_initialized == 0)
+               dma_alloc_init(_ramend - DMA_UNCACHED_REGION, _ramend);
+
+       spin_lock_irqsave(&dma_page_lock, flags);
+
+       for (i = 0; i < dma_pages;) {
+               if (dma_page[i++] == 0) {
+                       if (++count == pages) {
+                               while (count--)
+                                       dma_page[--i] = 1;
+                               ret = dma_base + (i << PAGE_SHIFT);
+                               break;
+                       }
+               } else
+                       count = 0;
+       }
+       spin_unlock_irqrestore(&dma_page_lock, flags);
+       return ret;
+}
+
+static void __free_dma_pages(unsigned long addr, unsigned int pages)
+{
+       unsigned long page = (addr - dma_base) >> PAGE_SHIFT;
+       unsigned long flags;
+       int i;
+
+       if ((page + pages) > dma_pages) {
+               printk(KERN_ERR "%s: freeing outside range.\n", __FUNCTION__);
+               BUG();
+       }
+
+       spin_lock_irqsave(&dma_page_lock, flags);
+       for (i = page; i < page + pages; i++) {
+               dma_page[i] = 0;
+       }
+       spin_unlock_irqrestore(&dma_page_lock, flags);
+}
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                        dma_addr_t * dma_handle, gfp_t gfp)
+{
+       void *ret;
+
+       ret = (void *)__alloc_dma_pages(get_pages(size));
+
+       if (ret) {
+               memset(ret, 0, size);
+               *dma_handle = virt_to_phys(ret);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void
+dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+                 dma_addr_t dma_handle)
+{
+       __free_dma_pages((unsigned long)vaddr, get_pages(size));
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+/*
+ * Dummy functions defined for some existing drivers
+ */
+
+dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+              enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       invalidate_dcache_range((unsigned long)ptr,
+                       (unsigned long)ptr + size);
+
+       return (dma_addr_t) ptr;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+          enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(direction == DMA_NONE);
+
+       for (i = 0; i < nents; i++)
+               invalidate_dcache_range(sg_dma_address(&sg[i]),
+                                       sg_dma_address(&sg[i]) +
+                                       sg_dma_len(&sg[i]));
+
+       return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+               enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+}
+EXPORT_SYMBOL(dma_unmap_single);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+               int nhwentries, enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+}
+EXPORT_SYMBOL(dma_unmap_sg);
diff --git a/arch/blackfin/kernel/dualcore_test.c b/arch/blackfin/kernel/dualcore_test.c
new file mode 100644 (file)
index 0000000..8b89c99
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * File:         arch/blackfin/kernel/dualcore_test.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  Small test code for CoreB on a BF561
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+static int *testarg = (int*)0xfeb00000;
+
+static int test_init(void)
+{
+       *testarg = 1;
+       printk("Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
+              *testarg, testarg);
+       return 0;
+}
+
+static void test_exit(void)
+{
+       printk("Dual core test module removed: testarg = [%d]\n", *testarg);
+}
+
+module_init(test_init);
+module_exit(test_exit);
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
new file mode 100644 (file)
index 0000000..5880b27
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * File:         arch/blackfin/kernel/entry.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/asm-offsets.h>
+
+#include <asm/mach-common/context.S>
+
+#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+.section .l1.text
+#else
+.text
+#endif
+
+ENTRY(_ret_from_fork)
+       SP += -12;
+       call _schedule_tail;
+       SP += 12;
+       r0 = [sp + PT_IPEND];
+       cc = bittst(r0,1);
+       if cc jump .Lin_kernel;
+       RESTORE_CONTEXT
+       rti;
+.Lin_kernel:
+       bitclr(r0,1);
+       [sp + PT_IPEND] = r0;
+       /* do a 'fake' RTI by jumping to [RETI]
+        * to avoid clearing supervisor mode in child
+       */
+       RESTORE_ALL_SYS
+       p0 = reti;
+       jump (p0);
+
+ENTRY(_sys_fork)
+       r0 = -EINVAL;
+       rts;
+
+ENTRY(_sys_vfork)
+       r0 = sp;
+       r0 += 24;
+       [--sp] = rets;
+       SP += -12;
+       call _bfin_vfork;
+       SP += 12;
+       rets = [sp++];
+       rts;
+
+ENTRY(_sys_clone)
+       r0 = sp;
+       r0 += 24;
+       [--sp] = rets;
+       SP += -12;
+       call _bfin_clone;
+       SP += 12;
+       rets = [sp++];
+       rts;
+
+ENTRY(_sys_rt_sigreturn)
+       r0 = sp;
+       r0 += 24;
+       [--sp] = rets;
+       SP += -12;
+       call _do_rt_sigreturn;
+       SP += 12;
+       rets = [sp++];
+       rts;
diff --git a/arch/blackfin/kernel/flat.c b/arch/blackfin/kernel/flat.c
new file mode 100644 (file)
index 0000000..a92587b
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  arch/blackfin/kernel/flat.c
+ *
+ *  Copyright (C) 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/sched.h>
+#include <linux/flat.h>
+
+#define FLAT_BFIN_RELOC_TYPE_16_BIT 0
+#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1
+#define FLAT_BFIN_RELOC_TYPE_32_BIT 2
+
+unsigned long bfin_get_addr_from_rp(unsigned long *ptr,
+               unsigned long relval,
+               unsigned long flags,
+               unsigned long *persistent)
+{
+       unsigned short *usptr = (unsigned short *)ptr;
+       int type = (relval >> 26) & 7;
+       unsigned long val;
+
+       switch (type) {
+               case FLAT_BFIN_RELOC_TYPE_16_BIT:
+               case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+                       usptr = (unsigned short *)ptr;
+                       pr_debug("*usptr = %x", get_unaligned(usptr));
+                       val = get_unaligned(usptr);
+                       val += *persistent;
+                       break;
+
+               case FLAT_BFIN_RELOC_TYPE_32_BIT:
+                       pr_debug("*ptr = %lx", get_unaligned(ptr));
+                       val = get_unaligned(ptr);
+                       break;
+
+               default:
+                       pr_debug("BINFMT_FLAT: Unknown relocation type %x\n",
+                               type);
+
+                       return 0;
+       }
+
+       /*
+        * Stack-relative relocs contain the offset into the stack, we
+        * have to add the stack's start address here and return 1 from
+        * flat_addr_absolute to prevent the normal address calculations
+        */
+       if (relval & (1 << 29))
+               return val + current->mm->context.end_brk;
+
+       if ((flags & FLAT_FLAG_GOTPIC) == 0)
+               val = htonl(val);
+       return val;
+}
+EXPORT_SYMBOL(bfin_get_addr_from_rp);
+
+/*
+ * Insert the address ADDR into the symbol reference at RP;
+ * RELVAL is the raw relocation-table entry from which RP is derived
+ */
+void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
+               unsigned long relval)
+{
+       unsigned short *usptr = (unsigned short *)ptr;
+       int type = (relval >> 26) & 7;
+
+       switch (type) {
+               case FLAT_BFIN_RELOC_TYPE_16_BIT:
+                       put_unaligned(addr, usptr);
+                       pr_debug("new value %x at %p", get_unaligned(usptr),
+                               usptr);
+                       break;
+
+               case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+                       put_unaligned(addr >> 16, usptr);
+                       pr_debug("new value %x", get_unaligned(usptr));
+                       break;
+
+               case FLAT_BFIN_RELOC_TYPE_32_BIT:
+                       put_unaligned(addr, ptr);
+                       pr_debug("new ptr =%lx", get_unaligned(ptr));
+                       break;
+       }
+}
+EXPORT_SYMBOL(bfin_put_addr_at_rp);
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c
new file mode 100644 (file)
index 0000000..b45188f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * File:         arch/blackfin/kernel/init_task.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry.
+ */
+union thread_union init_thread_union
+    __attribute__ ((__section__(".data.init_task"))) = {
+INIT_THREAD_INFO(init_task)};
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
new file mode 100644 (file)
index 0000000..df5bf02
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * File:         arch/blackfin/kernel/irqchip.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+static unsigned long irq_err_count;
+static spinlock_t irq_controller_lock;
+
+/*
+ * Dummy mask/unmask handler
+ */
+void dummy_mask_unmask_irq(unsigned int irq)
+{
+}
+
+void ack_bad_irq(unsigned int irq)
+{
+       irq_err_count += 1;
+       printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
+}
+EXPORT_SYMBOL(ack_bad_irq);
+
+static struct irq_chip bad_chip = {
+       .ack = dummy_mask_unmask_irq,
+       .mask = dummy_mask_unmask_irq,
+       .unmask = dummy_mask_unmask_irq,
+};
+
+static struct irq_desc bad_irq_desc = {
+       .chip = &bad_chip,
+       .handle_irq = handle_bad_irq,
+       .depth = 1,
+};
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+       int i = *(loff_t *) v;
+       struct irqaction *action;
+       unsigned long flags;
+
+       if (i < NR_IRQS) {
+               spin_lock_irqsave(&irq_desc[i].lock, flags);
+               action = irq_desc[i].action;
+               if (!action)
+                       goto unlock;
+
+               seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
+               seq_printf(p, "  %s", action->name);
+               for (action = action->next; action; action = action->next)
+                       seq_printf(p, ", %s", action->name);
+
+               seq_putc(p, '\n');
+             unlock:
+               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+       } else if (i == NR_IRQS) {
+               seq_printf(p, "Err: %10lu\n", irq_err_count);
+       }
+       return 0;
+}
+
+/*
+ * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
+ * come via this function.  Instead, they should provide their
+ * own 'handler'
+ */
+
+#ifdef CONFIG_DO_IRQ_L1
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)__attribute__((l1_text));
+#endif
+
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+       struct pt_regs *old_regs;
+       struct irq_desc *desc = irq_desc + irq;
+       unsigned short pending, other_ints;
+
+       old_regs = set_irq_regs(regs);
+
+       /*
+        * Some hardware gives randomly wrong interrupts.  Rather
+        * than crashing, do something sensible.
+        */
+       if (irq >= NR_IRQS)
+               desc = &bad_irq_desc;
+
+       irq_enter();
+
+       generic_handle_irq(irq);
+
+       /* If we're the only interrupt running (ignoring IRQ15 which is for
+          syscalls), lower our priority to IRQ14 so that softirqs run at
+          that level.  If there's another, lower-level interrupt, irq_exit
+          will defer softirqs to that.  */
+       CSYNC();
+       pending = bfin_read_IPEND() & ~0x8000;
+       other_ints = pending & (pending - 1);
+       if (other_ints == 0)
+               lower_to_irq14();
+       irq_exit();
+
+       set_irq_regs(old_regs);
+}
+
+void __init init_IRQ(void)
+{
+       struct irq_desc *desc;
+       int irq;
+
+       spin_lock_init(&irq_controller_lock);
+       for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
+               *desc = bad_irq_desc;
+       }
+
+       init_arch_irq();
+}
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
new file mode 100644 (file)
index 0000000..372f756
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * File:         arch/blackfin/kernel/module.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/cacheflush.h>
+
+/*
+ * handle arithmetic relocations.
+ * See binutils/bfd/elf32-bfin.c for more details
+ */
+#define RELOC_STACK_SIZE 100
+static uint32_t reloc_stack[RELOC_STACK_SIZE];
+static unsigned int reloc_stack_tos;
+
+#define is_reloc_stack_empty() ((reloc_stack_tos > 0)?0:1)
+
+static void reloc_stack_push(uint32_t value)
+{
+       reloc_stack[reloc_stack_tos++] = value;
+}
+
+static uint32_t reloc_stack_pop(void)
+{
+       return reloc_stack[--reloc_stack_tos];
+}
+
+static uint32_t reloc_stack_operate(unsigned int oper, struct module *mod)
+{
+       uint32_t value;
+
+       switch (oper) {
+       case R_add:
+               value = reloc_stack[reloc_stack_tos - 2] +
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_sub:
+               value = reloc_stack[reloc_stack_tos - 2] -
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_mult:
+               value = reloc_stack[reloc_stack_tos - 2] *
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_div:
+               value = reloc_stack[reloc_stack_tos - 2] /
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_mod:
+               value = reloc_stack[reloc_stack_tos - 2] %
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_lshift:
+               value = reloc_stack[reloc_stack_tos - 2] <<
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_rshift:
+               value = reloc_stack[reloc_stack_tos - 2] >>
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_and:
+               value = reloc_stack[reloc_stack_tos - 2] &
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_or:
+               value = reloc_stack[reloc_stack_tos - 2] |
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_xor:
+               value = reloc_stack[reloc_stack_tos - 2] ^
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_land:
+               value = reloc_stack[reloc_stack_tos - 2] &&
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_lor:
+               value = reloc_stack[reloc_stack_tos - 2] ||
+                       reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 2;
+               break;
+       case R_neg:
+               value = -reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos--;
+               break;
+       case R_comp:
+               value = ~reloc_stack[reloc_stack_tos - 1];
+               reloc_stack_tos -= 1;
+               break;
+       default:
+               printk(KERN_WARNING "module %s: unhandled reloction\n",
+                               mod->name);
+               return 0;
+       }
+
+       /* now push the new value back on stack */
+       reloc_stack_push(value);
+
+       return value;
+}
+
+void *module_alloc(unsigned long size)
+{
+       if (size == 0)
+               return NULL;
+       return vmalloc(size);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+       vfree(module_region);
+}
+
+/* Transfer the section to the L1 memory */
+int
+module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
+                         char *secstrings, struct module *mod)
+{
+       Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+       void *dest = NULL;
+
+       for (s = sechdrs; s < sechdrs_end; ++s) {
+               if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
+                       ((strcmp(".text", secstrings + s->sh_name)==0) &&
+                        (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
+                       mod->arch.text_l1 = s;
+                       dest = l1_inst_sram_alloc(s->sh_size);
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                      "module %s: L1 instruction memory allocation failed\n",
+                                      mod->name);
+                               return -1;
+                       }
+                       dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+               if ((strcmp(".l1.data", secstrings + s->sh_name) == 0)||
+                       ((strcmp(".data", secstrings + s->sh_name)==0) &&
+                        (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+                       mod->arch.data_a_l1 = s;
+                       dest = l1_data_sram_alloc(s->sh_size);
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                       "module %s: L1 data memory allocation failed\n",
+                                       mod->name);
+                               return -1;
+                       }
+                       memcpy(dest, (void *)s->sh_addr, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+               if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
+                       ((strcmp(".bss", secstrings + s->sh_name)==0) &&
+                        (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+                       mod->arch.bss_a_l1 = s;
+                       dest = l1_data_sram_alloc(s->sh_size);
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                       "module %s: L1 data memory allocation failed\n",
+                                       mod->name);
+                               return -1;
+                       }
+                       memset(dest, 0, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+               if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) {
+                       mod->arch.data_b_l1 = s;
+                       dest = l1_data_B_sram_alloc(s->sh_size);
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                       "module %s: L1 data memory allocation failed\n",
+                                       mod->name);
+                               return -1;
+                       }
+                       memcpy(dest, (void *)s->sh_addr, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+               if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) {
+                       mod->arch.bss_b_l1 = s;
+                       dest = l1_data_B_sram_alloc(s->sh_size);
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                       "module %s: L1 data memory allocation failed\n",
+                                       mod->name);
+                               return -1;
+                       }
+                       memset(dest, 0, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+       }
+       return 0;
+}
+
+int
+apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
+              unsigned int symindex, unsigned int relsec, struct module *me)
+{
+       printk(KERN_ERR "module %s: .rel unsupported\n", me->name);
+       return -ENOEXEC;
+}
+
+/*************************************************************************/
+/* FUNCTION : apply_relocate_add                                         */
+/* ABSTRACT : Blackfin specific relocation handling for the loadable     */
+/*            modules. Modules are expected to be .o files.              */
+/*            Arithmetic relocations are handled.                        */
+/*            We do not expect LSETUP to be split and hence is not       */
+/*            handled.                                                   */
+/*            R_byte and R_byte2 are also not handled as the gas         */
+/*            does not generate it.                                      */
+/*************************************************************************/
+int
+apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
+                  unsigned int symindex, unsigned int relsec,
+                  struct module *mod)
+{
+       unsigned int i;
+       unsigned short tmp;
+       Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+       Elf32_Sym *sym;
+       uint32_t *location32;
+       uint16_t *location16;
+       uint32_t value;
+
+       pr_debug("Applying relocate section %u to %u\n", relsec,
+              sechdrs[relsec].sh_info);
+       for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+               /* This is where to make the change */
+               location16 =
+                   (uint16_t *) (sechdrs[sechdrs[relsec].sh_info].sh_addr +
+                                 rel[i].r_offset);
+               location32 = (uint32_t *) location16;
+               /* This is the symbol it is referring to. Note that all
+                  undefined symbols have been resolved. */
+               sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
+                   + ELF32_R_SYM(rel[i].r_info);
+               if (is_reloc_stack_empty()) {
+                       value = sym->st_value;
+               } else {
+                       value = reloc_stack_pop();
+               }
+               value += rel[i].r_addend;
+               pr_debug("location is %x, value is %x type is %d \n",
+                        (unsigned int) location32, value,
+                        ELF32_R_TYPE(rel[i].r_info));
+
+               switch (ELF32_R_TYPE(rel[i].r_info)) {
+
+               case R_pcrel24:
+               case R_pcrel24_jump_l:
+                       /* Add the value, subtract its postition */
+                       location16 =
+                           (uint16_t *) (sechdrs[sechdrs[relsec].sh_info].
+                                         sh_addr + rel[i].r_offset - 2);
+                       location32 = (uint32_t *) location16;
+                       value -= (uint32_t) location32;
+                       value >>= 1;
+                       pr_debug("value is %x, before %x-%x after %x-%x\n", value,
+                              *location16, *(location16 + 1),
+                              (*location16 & 0xff00) | (value >> 16 & 0x00ff),
+                              value & 0xffff);
+                       *location16 =
+                           (*location16 & 0xff00) | (value >> 16 & 0x00ff);
+                       *(location16 + 1) = value & 0xffff;
+                       break;
+               case R_pcrel12_jump:
+               case R_pcrel12_jump_s:
+                       value -= (uint32_t) location32;
+                       value >>= 1;
+                       *location16 = (value & 0xfff);
+                       break;
+               case R_pcrel10:
+                       value -= (uint32_t) location32;
+                       value >>= 1;
+                       *location16 = (value & 0x3ff);
+                       break;
+               case R_luimm16:
+                       pr_debug("before %x after %x\n", *location16,
+                                      (value & 0xffff));
+                       tmp = (value & 0xffff);
+                       if((unsigned long)location16 >= L1_CODE_START) {
+                               dma_memcpy(location16, &tmp, 2);
+                       } else
+                               *location16 = tmp;
+                       break;
+               case R_huimm16:
+                       pr_debug("before %x after %x\n", *location16,
+                                      ((value >> 16) & 0xffff));
+                       tmp = ((value >> 16) & 0xffff);
+                       if((unsigned long)location16 >= L1_CODE_START) {
+                               dma_memcpy(location16, &tmp, 2);
+                       } else
+                               *location16 = tmp;
+                       break;
+               case R_rimm16:
+                       *location16 = (value & 0xffff);
+                       break;
+               case R_byte4_data:
+                       pr_debug("before %x after %x\n", *location32, value);
+                       *location32 = value;
+                       break;
+               case R_push:
+                       reloc_stack_push(value);
+                       break;
+               case R_const:
+                       reloc_stack_push(rel[i].r_addend);
+                       break;
+               case R_add:
+               case R_sub:
+               case R_mult:
+               case R_div:
+               case R_mod:
+               case R_lshift:
+               case R_rshift:
+               case R_and:
+               case R_or:
+               case R_xor:
+               case R_land:
+               case R_lor:
+               case R_neg:
+               case R_comp:
+                       reloc_stack_operate(ELF32_R_TYPE(rel[i].r_info), mod);
+                       break;
+               default:
+                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+                              mod->name, ELF32_R_TYPE(rel[i].r_info));
+                       return -ENOEXEC;
+               }
+       }
+       return 0;
+}
+
+int
+module_finalize(const Elf_Ehdr * hdr,
+               const Elf_Shdr * sechdrs, struct module *mod)
+{
+       unsigned int i, strindex = 0, symindex = 0;
+       char *secstrings;
+
+       secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+       for (i = 1; i < hdr->e_shnum; i++) {
+               /* Internal symbols and strings. */
+               if (sechdrs[i].sh_type == SHT_SYMTAB) {
+                       symindex = i;
+                       strindex = sechdrs[i].sh_link;
+               }
+       }
+
+       for (i = 1; i < hdr->e_shnum; i++) {
+               const char *strtab = (char *)sechdrs[strindex].sh_addr;
+               unsigned int info = sechdrs[i].sh_info;
+
+               /* Not a valid relocation section? */
+               if (info >= hdr->e_shnum)
+                       continue;
+
+               if ((sechdrs[i].sh_type == SHT_RELA) &&
+                   ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0)||
+                       ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
+                        (hdr->e_flags & FLG_CODE_IN_L1)))) {
+                       apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
+                                          symindex, i, mod);
+               }
+       }
+       return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+       if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr))
+               l1_inst_sram_free((void*)mod->arch.text_l1->sh_addr);
+       if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr))
+               l1_data_sram_free((void*)mod->arch.data_a_l1->sh_addr);
+       if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr))
+               l1_data_sram_free((void*)mod->arch.bss_a_l1->sh_addr);
+       if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr))
+               l1_data_B_sram_free((void*)mod->arch.data_b_l1->sh_addr);
+       if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr))
+               l1_data_B_sram_free((void*)mod->arch.bss_b_l1->sh_addr);
+}
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
new file mode 100644 (file)
index 0000000..3eff743
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * File:         arch/blackfin/kernel/process.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  Blackfin architecture-dependent process handling.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/unistd.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+
+#define        LED_ON  0
+#define        LED_OFF 1
+
+asmlinkage void ret_from_fork(void);
+
+/* Points to the SDRAM backup memory for the stack that is currently in
+ * L1 scratchpad memory.
+ */
+void *current_l1_stack_save;
+
+/* The number of tasks currently using a L1 stack area.  The SRAM is
+ * allocated/deallocated whenever this changes from/to zero.
+ */
+int nr_l1stack_tasks;
+
+/* Start and length of the area in L1 scratchpad memory which we've allocated
+ * for process stacks.
+ */
+void *l1_stack_base;
+unsigned long l1_stack_len;
+
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*pm_idle)(void) = NULL;
+EXPORT_SYMBOL(pm_idle);
+
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * We are using a different LED from the one used to indicate timer interrupt.
+ */
+#if defined(CONFIG_BFIN_IDLE_LED)
+static inline void leds_switch(int flag)
+{
+       unsigned short tmp = 0;
+
+       tmp = bfin_read_CONFIG_BFIN_IDLE_LED_PORT();
+       SSYNC();
+
+       if (flag == LED_ON)
+               tmp &= ~CONFIG_BFIN_IDLE_LED_PIN;       /* light on */
+       else
+               tmp |= CONFIG_BFIN_IDLE_LED_PIN;        /* light off */
+
+       bfin_write_CONFIG_BFIN_IDLE_LED_PORT(tmp);
+       SSYNC();
+
+}
+#else
+static inline void leds_switch(int flag)
+{
+}
+#endif
+
+/*
+ * The idle loop on BFIN
+ */
+#ifdef CONFIG_IDLE_L1
+void default_idle(void)__attribute__((l1_text));
+void cpu_idle(void)__attribute__((l1_text));
+#endif
+
+void default_idle(void)
+{
+       while (!need_resched()) {
+               leds_switch(LED_OFF);
+               local_irq_disable();
+               if (likely(!need_resched()))
+                       idle_with_irq_disabled();
+               local_irq_enable();
+               leds_switch(LED_ON);
+       }
+}
+
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+       /* endless idle loop with no priority at all */
+       while (1) {
+               idle();
+               preempt_enable_no_resched();
+               schedule();
+               preempt_disable();
+       }
+}
+
+void machine_restart(char *__unused)
+{
+#if defined(CONFIG_BLKFIN_CACHE)
+       bfin_write_IMEM_CONTROL(0x01);
+       SSYNC();
+#endif
+       bfin_reset();
+       /* Dont do anything till the reset occurs */
+       while (1) {
+               SSYNC();
+       }
+}
+
+void machine_halt(void)
+{
+       for (;;)
+               asm volatile ("idle");
+}
+
+void machine_power_off(void)
+{
+       for (;;)
+               asm volatile ("idle");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+       printk(KERN_NOTICE "\n");
+       printk(KERN_NOTICE
+              "PC: %08lu  Status: %04lu  SysStatus: %04lu  RETS: %08lu\n",
+              regs->pc, regs->astat, regs->seqstat, regs->rets);
+       printk(KERN_NOTICE
+              "A0.x: %08lx  A0.w: %08lx  A1.x: %08lx  A1.w: %08lx\n",
+              regs->a0x, regs->a0w, regs->a1x, regs->a1w);
+       printk(KERN_NOTICE "P0: %08lx  P1: %08lx  P2: %08lx  P3: %08lx\n",
+              regs->p0, regs->p1, regs->p2, regs->p3);
+       printk(KERN_NOTICE "P4: %08lx  P5: %08lx\n", regs->p4, regs->p5);
+       printk(KERN_NOTICE "R0: %08lx  R1: %08lx  R2: %08lx  R3: %08lx\n",
+              regs->r0, regs->r1, regs->r2, regs->r3);
+       printk(KERN_NOTICE "R4: %08lx  R5: %08lx  R6: %08lx  R7: %08lx\n",
+              regs->r4, regs->r5, regs->r6, regs->r7);
+
+       if (!(regs->ipend))
+               printk("USP: %08lx\n", rdusp());
+}
+
+/* Fill in the fpu structure for a core dump.  */
+
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
+{
+       return 1;
+}
+
+/*
+ * This gets run with P1 containing the
+ * function to call, and R1 containing
+ * the "args".  Note P0 is clobbered on the way here.
+ */
+void kernel_thread_helper(void);
+__asm__(".section .text\n"
+       ".align 4\n"
+       "_kernel_thread_helper:\n\t"
+       "\tsp += -12;\n\t"
+       "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");
+
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
+{
+       struct pt_regs regs;
+
+       memset(&regs, 0, sizeof(regs));
+
+       regs.r1 = (unsigned long)arg;
+       regs.p1 = (unsigned long)fn;
+       regs.pc = (unsigned long)kernel_thread_helper;
+       regs.orig_p0 = -1;
+       /* Set bit 2 to tell ret_from_fork we should be returning to kernel
+          mode.  */
+       regs.ipend = 0x8002;
+       __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
+       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
+                      NULL);
+}
+
+void flush_thread(void)
+{
+}
+
+asmlinkage int bfin_vfork(struct pt_regs *regs)
+{
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL,
+                      NULL);
+}
+
+asmlinkage int bfin_clone(struct pt_regs *regs)
+{
+       unsigned long clone_flags;
+       unsigned long newsp;
+
+       /* syscall2 puts clone_flags in r0 and usp in r1 */
+       clone_flags = regs->r0;
+       newsp = regs->r1;
+       if (!newsp)
+               newsp = rdusp();
+       else
+               newsp -= 12;
+       return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+}
+
+int
+copy_thread(int nr, unsigned long clone_flags,
+           unsigned long usp, unsigned long topstk,
+           struct task_struct *p, struct pt_regs *regs)
+{
+       struct pt_regs *childregs;
+
+       childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
+       *childregs = *regs;
+       childregs->r0 = 0;
+
+       p->thread.usp = usp;
+       p->thread.ksp = (unsigned long)childregs;
+       p->thread.pc = (unsigned long)ret_from_fork;
+
+       return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs *regs, struct user *dump)
+{
+       dump->magic = CMAGIC;
+       dump->start_code = 0;
+       dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
+       dump->u_tsize = ((unsigned long)current->mm->end_code) >> PAGE_SHIFT;
+       dump->u_dsize = ((unsigned long)(current->mm->brk +
+                                        (PAGE_SIZE - 1))) >> PAGE_SHIFT;
+       dump->u_dsize -= dump->u_tsize;
+       dump->u_ssize = 0;
+
+       if (dump->start_stack < TASK_SIZE)
+               dump->u_ssize =
+                   ((unsigned long)(TASK_SIZE -
+                                    dump->start_stack)) >> PAGE_SHIFT;
+
+       dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
+
+       dump->regs.r0 = regs->r0;
+       dump->regs.r1 = regs->r1;
+       dump->regs.r2 = regs->r2;
+       dump->regs.r3 = regs->r3;
+       dump->regs.r4 = regs->r4;
+       dump->regs.r5 = regs->r5;
+       dump->regs.r6 = regs->r6;
+       dump->regs.r7 = regs->r7;
+       dump->regs.p0 = regs->p0;
+       dump->regs.p1 = regs->p1;
+       dump->regs.p2 = regs->p2;
+       dump->regs.p3 = regs->p3;
+       dump->regs.p4 = regs->p4;
+       dump->regs.p5 = regs->p5;
+       dump->regs.orig_p0 = regs->orig_p0;
+       dump->regs.a0w = regs->a0w;
+       dump->regs.a1w = regs->a1w;
+       dump->regs.a0x = regs->a0x;
+       dump->regs.a1x = regs->a1x;
+       dump->regs.rets = regs->rets;
+       dump->regs.astat = regs->astat;
+       dump->regs.pc = regs->pc;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+asmlinkage int sys_execve(char *name, char **argv, char **envp)
+{
+       int error;
+       char *filename;
+       struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
+
+       lock_kernel();
+       filename = getname(name);
+       error = PTR_ERR(filename);
+       if (IS_ERR(filename))
+               goto out;
+       error = do_execve(filename, argv, envp, regs);
+       putname(filename);
+      out:
+       unlock_kernel();
+       return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+       unsigned long fp, pc;
+       unsigned long stack_page;
+       int count = 0;
+       if (!p || p == current || p->state == TASK_RUNNING)
+               return 0;
+
+       stack_page = (unsigned long)p;
+       fp = p->thread.usp;
+       do {
+               if (fp < stack_page + sizeof(struct thread_info) ||
+                   fp >= 8184 + stack_page)
+                       return 0;
+               pc = ((unsigned long *)fp)[1];
+               if (!in_sched_functions(pc))
+                       return pc;
+               fp = *(unsigned long *)fp;
+       }
+       while (count++ < 16);
+       return 0;
+}
+
+#if defined(CONFIG_ACCESS_CHECK)
+int _access_ok(unsigned long addr, unsigned long size)
+{
+
+       if (addr > (addr + size))
+               return 0;
+       if (segment_eq(get_fs(),KERNEL_DS))
+               return 1;
+#ifdef CONFIG_MTD_UCLINUX
+       if (addr >= memory_start && (addr + size) <= memory_end)
+               return 1;
+       if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
+               return 1;
+#else
+       if (addr >= memory_start && (addr + size) <= physical_mem_end)
+               return 1;
+#endif
+       if (addr >= (unsigned long)__init_begin &&
+           addr + size <= (unsigned long)__init_end)
+               return 1;
+       if (addr >= L1_SCRATCH_START
+           && addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH)
+               return 1;
+#if L1_CODE_LENGTH != 0
+       if (addr >= L1_CODE_START + (_etext_l1 - _stext_l1)
+           && addr + size <= L1_CODE_START + L1_CODE_LENGTH)
+               return 1;
+#endif
+#if L1_DATA_A_LENGTH != 0
+       if (addr >= L1_DATA_A_START + (_ebss_l1 - _sdata_l1)
+           && addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH)
+               return 1;
+#endif
+#if L1_DATA_B_LENGTH != 0
+       if (addr >= L1_DATA_B_START
+           && addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)
+               return 1;
+#endif
+       return 0;
+}
+EXPORT_SYMBOL(_access_ok);
+#endif /* CONFIG_ACCESS_CHECK */
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
new file mode 100644 (file)
index 0000000..d7c8e51
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * File:         arch/blackfin/kernel/ptrace.c
+ * Based on:     Taken from linux/kernel/ptrace.c
+ * Author:       linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+ *
+ * Created:      1/23/92
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/signal.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/asm-offsets.h>
+#include <asm/dma.h>
+
+#define MAX_SHARED_LIBS 3
+#define TEXT_OFFSET 0
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which bits in the SYSCFG reg the user has access to. */
+/* 1 = access 0 = no access */
+#define SYSCFG_MASK 0x0007     /* SYSCFG reg */
+/* sets the trace bits. */
+#define TRACE_BITS 0x0001
+
+/* Find the stack offset for a register, relative to thread.esp0. */
+#define PT_REG(reg)    ((long)&((struct pt_regs *)0)->reg)
+
+/*
+ * Get the address of the live pt_regs for the specified task.
+ * These are saved onto the top kernel stack when the process
+ * is not running.
+ *
+ * Note: if a user thread is execve'd from kernel space, the
+ * kernel stack will not be empty on entry to the kernel, so
+ * ptracing these tasks will fail.
+ */
+static inline struct pt_regs *get_user_regs(struct task_struct *task)
+{
+       return (struct pt_regs *)
+           ((unsigned long)task->thread_info +
+            (THREAD_SIZE - sizeof(struct pt_regs)));
+}
+
+/*
+ * Get all user integer registers.
+ */
+static inline int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
+{
+       struct pt_regs *regs = get_user_regs(tsk);
+       return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
+}
+
+/* Mapping from PT_xxx to the stack offset at which the register is
+ * saved.  Notice that usp has no stack-slot and needs to be treated
+ * specially (see get_reg/put_reg below).
+ */
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+       unsigned char *reg_ptr;
+
+       struct pt_regs *regs =
+           (struct pt_regs *)((unsigned long)task->thread_info +
+                              (THREAD_SIZE - sizeof(struct pt_regs)));
+       reg_ptr = (char *)regs;
+
+       switch (regno) {
+       case PT_USP:
+               return task->thread.usp;
+       default:
+               if (regno <= 216)
+                       return *(long *)(reg_ptr + regno);
+       }
+       /* slight mystery ... never seems to come here but kernel misbehaves without this code! */
+
+       printk(KERN_WARNING "Request to get for unknown register %d\n", regno);
+       return 0;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int
+put_reg(struct task_struct *task, int regno, unsigned long data)
+{
+       char * reg_ptr;
+
+       struct pt_regs *regs =
+           (struct pt_regs *)((unsigned long)task->thread_info +
+                              (THREAD_SIZE - sizeof(struct pt_regs)));
+       reg_ptr = (char *)regs;
+
+       switch (regno) {
+       case PT_PC:
+               /*********************************************************************/
+               /* At this point the kernel is most likely in exception.             */
+               /* The RETX register will be used to populate the pc of the process. */
+               /*********************************************************************/
+               regs->retx = data;
+               regs->pc = data;
+               break;
+       case PT_RETX:
+               break;          /* regs->retx = data; break; */
+       case PT_USP:
+               regs->usp = data;
+               task->thread.usp = data;
+               break;
+       default:
+               if (regno <= 216)
+                       *(long *)(reg_ptr + regno) = data;
+       }
+       return 0;
+}
+
+/*
+ * check that an address falls within the bounds of the target process's memory mappings
+ */
+static inline int is_user_addr_valid(struct task_struct *child,
+                                    unsigned long start, unsigned long len)
+{
+       struct vm_list_struct *vml;
+       struct sram_list_struct *sraml;
+
+       for (vml = child->mm->context.vmlist; vml; vml = vml->next)
+               if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end)
+                       return 0;
+
+       for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
+               if (start >= (unsigned long)sraml->addr
+                   && start + len <= (unsigned long)sraml->addr + sraml->length)
+                       return 0;
+
+       return -EIO;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+       unsigned long tmp;
+       /* make sure the single step bit is not set. */
+       tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+       put_reg(child, PT_SR, tmp);
+}
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+       int ret;
+       int add = 0;
+
+       switch (request) {
+               /* when I and D space are separate, these will need to be fixed. */
+       case PTRACE_PEEKDATA:
+               pr_debug("ptrace: PEEKDATA\n");
+               add = MAX_SHARED_LIBS * 4;      /* space between text and data */
+               /* fall through */
+       case PTRACE_PEEKTEXT:   /* read word at location addr. */
+               {
+                       unsigned long tmp = 0;
+                       int copied;
+
+                       ret = -EIO;
+                       pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + add %d %ld\n", addr, add,
+                                sizeof(data));
+                       if (is_user_addr_valid(child, addr + add, sizeof(tmp)) < 0)
+                               break;
+                       pr_debug("ptrace: user address is valid\n");
+
+#if L1_CODE_LENGTH != 0
+                       if (addr + add >= L1_CODE_START
+                           && addr + add + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) {
+                               safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp));
+                               copied = sizeof(tmp);
+                       } else
+#endif
+                       copied =
+                           access_process_vm(child, addr + add, &tmp,
+                                             sizeof(tmp), 0);
+                       pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
+                       if (copied != sizeof(tmp))
+                               break;
+                       ret = put_user(tmp, (unsigned long *)data);
+                       break;
+               }
+
+               /* read the word at location addr in the USER area. */
+       case PTRACE_PEEKUSR:
+               {
+                       unsigned long tmp;
+                       ret = -EIO;
+                       tmp = 0;
+                       if ((addr & 3) || (addr > (sizeof(struct pt_regs) + 16))) {
+                               printk(KERN_WARNING "ptrace error : PEEKUSR : temporarily returning "
+                                                   "0 - %x sizeof(pt_regs) is %lx\n",
+                                    (int)addr, sizeof(struct pt_regs));
+                               break;
+                       }
+                       if (addr == sizeof(struct pt_regs)) {
+                               /* PT_TEXT_ADDR */
+                               tmp = child->mm->start_code + TEXT_OFFSET;
+                       } else if (addr == (sizeof(struct pt_regs) + 4)) {
+                               /* PT_TEXT_END_ADDR */
+                               tmp = child->mm->end_code;
+                       } else if (addr == (sizeof(struct pt_regs) + 8)) {
+                               /* PT_DATA_ADDR */
+                               tmp = child->mm->start_data;
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+                       } else if (addr == (sizeof(struct pt_regs) + 12)) {
+                               tmp = child->mm->context.exec_fdpic_loadmap;
+                       } else if (addr == (sizeof(struct pt_regs) + 16)) {
+                               tmp = child->mm->context.interp_fdpic_loadmap;
+#endif
+                       } else {
+                               tmp = get_reg(child, addr);
+                       }
+                       ret = put_user(tmp, (unsigned long *)data);
+                       break;
+               }
+
+               /* when I and D space are separate, this will have to be fixed. */
+       case PTRACE_POKEDATA:
+               printk(KERN_NOTICE "ptrace: PTRACE_PEEKDATA\n");
+               /* fall through */
+       case PTRACE_POKETEXT:   /* write the word at location addr. */
+               {
+                       int copied;
+
+                       ret = -EIO;
+                       pr_debug("ptrace: POKETEXT at addr 0x%08lx + add %d %ld bytes %lx\n",
+                                addr, add, sizeof(data), data);
+                       if (is_user_addr_valid(child, addr + add, sizeof(data)) < 0)
+                               break;
+                       pr_debug("ptrace: user address is valid\n");
+
+#if L1_CODE_LENGTH != 0
+                       if (addr + add >= L1_CODE_START
+                           && addr + add + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) {
+                               safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data));
+                               copied = sizeof(data);
+                       } else
+#endif
+                       copied =
+                           access_process_vm(child, addr + add, &data,
+                                             sizeof(data), 1);
+                       pr_debug("ptrace: copied size %d\n", copied);
+                       if (copied != sizeof(data))
+                               break;
+                       ret = 0;
+                       break;
+               }
+
+       case PTRACE_POKEUSR:    /* write the word at location addr in the USER area */
+               ret = -EIO;
+               if ((addr & 3) || (addr > (sizeof(struct pt_regs) + 16))) {
+                       printk(KERN_WARNING "ptrace error : POKEUSR: temporarily returning 0\n");
+                       break;
+               }
+
+               if (addr >= (sizeof(struct pt_regs))) {
+                       ret = 0;
+                       break;
+               }
+               if (addr == PT_SYSCFG) {
+                       data &= SYSCFG_MASK;
+                       data |= get_reg(child, PT_SYSCFG);
+               }
+               ret = put_reg(child, addr, data);
+               break;
+
+       case PTRACE_SYSCALL:    /* continue and stop at next (return from) syscall */
+       case PTRACE_CONT:
+               {               /* restart after signal. */
+                       long tmp;
+
+                       pr_debug("ptrace_cont\n");
+
+                       ret = -EIO;
+                       if (!valid_signal(data))
+                               break;
+                       if (request == PTRACE_SYSCALL)
+                               set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+                       else
+                               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+                       child->exit_code = data;
+                       /* make sure the single step bit is not set. */
+                       tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS);
+                       put_reg(child, PT_SYSCFG, tmp);
+                       pr_debug("before wake_up_process\n");
+                       wake_up_process(child);
+                       ret = 0;
+                       break;
+               }
+
+       /*
+        * make the child exit.  Best I can do is send it a sigkill.
+        * perhaps it should be put in the status that it wants to
+        * exit.
+        */
+       case PTRACE_KILL:
+               {
+                       long tmp;
+                       ret = 0;
+                       if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
+                               break;
+                       child->exit_code = SIGKILL;
+                       /* make sure the single step bit is not set. */
+                       tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS);
+                       put_reg(child, PT_SYSCFG, tmp);
+                       wake_up_process(child);
+                       break;
+               }
+
+       case PTRACE_SINGLESTEP:
+               {               /* set the trap flag. */
+                       long tmp;
+
+                       pr_debug("single step\n");
+                       ret = -EIO;
+                       if (!valid_signal(data))
+                               break;
+                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+                       tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS);
+                       put_reg(child, PT_SYSCFG, tmp);
+
+                       child->exit_code = data;
+                       /* give it a chance to run. */
+                       wake_up_process(child);
+                       ret = 0;
+                       break;
+               }
+
+       case PTRACE_DETACH:
+               {               /* detach a process that was attached. */
+                       ret = ptrace_detach(child, data);
+                       break;
+               }
+
+       case PTRACE_GETREGS:
+               {
+
+                       /* Get all gp regs from the child. */
+                       ret = ptrace_getregs(child, (void __user *)data);
+                       break;
+               }
+
+       case PTRACE_SETREGS:
+               {
+                       printk(KERN_NOTICE
+                              "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n");
+                       /* Set all gp regs in the child. */
+                       ret = 0;
+                       break;
+               }
+       default:
+               ret = ptrace_request(child, request, addr, data);
+               break;
+       }
+
+       return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+
+       if (!test_thread_flag(TIF_SYSCALL_TRACE))
+               return;
+
+       if (!(current->ptrace & PT_PTRACED))
+               return;
+
+       /* the 0x80 provides a way for the tracing parent to distinguish
+        * between a syscall stop and SIGTRAP delivery
+        */
+       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+                                ? 0x80 : 0));
+
+       /*
+        * this isn't the same as continuing with a signal, but it will do
+        * for normal use.  strace only continues with a signal if the
+        * stopping signal is not SIGTRAP.  -brl
+        */
+       if (current->exit_code) {
+               send_sig(current->exit_code, current, 1);
+               current->exit_code = 0;
+       }
+}
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
new file mode 100644 (file)
index 0000000..342bb8d
--- /dev/null
@@ -0,0 +1,902 @@
+/*
+ * File:         arch/blackfin/kernel/setup.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+
+#include <linux/ext2_fs.h>
+#include <linux/cramfs_fs.h>
+#include <linux/romfs_fs.h>
+
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+unsigned long memory_start, memory_end, physical_mem_end;
+unsigned long reserved_mem_dcache_on;
+unsigned long reserved_mem_icache_on;
+EXPORT_SYMBOL(memory_start);
+EXPORT_SYMBOL(memory_end);
+EXPORT_SYMBOL(physical_mem_end);
+EXPORT_SYMBOL(_ramend);
+
+#ifdef CONFIG_MTD_UCLINUX
+unsigned long memory_mtd_end, memory_mtd_start, mtd_size;
+unsigned long _ebss;
+EXPORT_SYMBOL(memory_mtd_end);
+EXPORT_SYMBOL(memory_mtd_start);
+EXPORT_SYMBOL(mtd_size);
+#endif
+
+char command_line[COMMAND_LINE_SIZE];
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+static void generate_cpl_tables(void);
+#endif
+
+void __init bf53x_cache_init(void)
+{
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+       generate_cpl_tables();
+#endif
+
+#ifdef CONFIG_BLKFIN_CACHE
+       bfin_icache_init();
+       printk(KERN_INFO "Instruction Cache Enabled\n");
+#endif
+
+#ifdef CONFIG_BLKFIN_DCACHE
+       bfin_dcache_init();
+       printk(KERN_INFO "Data Cache Enabled"
+# if defined CONFIG_BLKFIN_WB
+               " (write-back)"
+# elif defined CONFIG_BLKFIN_WT
+               " (write-through)"
+# endif
+               "\n");
+#endif
+}
+
+void bf53x_relocate_l1_mem(void)
+{
+       unsigned long l1_code_length;
+       unsigned long l1_data_a_length;
+       unsigned long l1_data_b_length;
+
+       l1_code_length = _etext_l1 - _stext_l1;
+       if (l1_code_length > L1_CODE_LENGTH)
+               l1_code_length = L1_CODE_LENGTH;
+       /* cannot complain as printk is not available as yet.
+        * But we can continue booting and complain later!
+        */
+
+       /* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
+       dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
+
+       l1_data_a_length = _ebss_l1 - _sdata_l1;
+       if (l1_data_a_length > L1_DATA_A_LENGTH)
+               l1_data_a_length = L1_DATA_A_LENGTH;
+
+       /* Copy _sdata_l1 to _ebss_l1 to L1 data bank A SRAM */
+       dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
+
+       l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
+       if (l1_data_b_length > L1_DATA_B_LENGTH)
+               l1_data_b_length = L1_DATA_B_LENGTH;
+
+       /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
+       dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
+                       l1_data_a_length, l1_data_b_length);
+
+}
+
+/*
+ * Initial parsing of the command line.  Currently, we support:
+ *  - Controlling the linux memory size: mem=xxx[KMG]
+ *  - Controlling the physical memory size: max_mem=xxx[KMG][$][#]
+ *       $ -> reserved memory is dcacheable
+ *       # -> reserved memory is icacheable
+ */
+static __init void parse_cmdline_early(char *cmdline_p)
+{
+       char c = ' ', *to = cmdline_p;
+       unsigned int memsize;
+       for (;;) {
+               if (c == ' ') {
+
+                       if (!memcmp(to, "mem=", 4)) {
+                               to += 4;
+                               memsize = memparse(to, &to);
+                               if (memsize)
+                                       _ramend = memsize;
+
+                       } else if (!memcmp(to, "max_mem=", 8)) {
+                               to += 8;
+                               memsize = memparse(to, &to);
+                               if (memsize) {
+                                       physical_mem_end = memsize;
+                                       if (*to != ' ') {
+                                               if (*to == '$'
+                                                   || *(to + 1) == '$')
+                                                       reserved_mem_dcache_on =
+                                                           1;
+                                               if (*to == '#'
+                                                   || *(to + 1) == '#')
+                                                       reserved_mem_icache_on =
+                                                           1;
+                                       }
+                               }
+                       }
+
+               }
+               c = *(to++);
+               if (!c)
+                       break;
+       }
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+       int bootmap_size;
+       unsigned long l1_length, sclk, cclk;
+#ifdef CONFIG_MTD_UCLINUX
+       unsigned long mtd_phys = 0;
+#endif
+
+       cclk = get_cclk();
+       sclk = get_sclk();
+
+#if !defined(CONFIG_BFIN_KERNEL_CLOCK) && defined(ANOMALY_05000273)
+       if (cclk == sclk)
+               panic("ANOMALY 05000273, SCLK can not be same as CCLK");
+#endif
+
+#if defined(ANOMALY_05000266)
+       bfin_read_IMDMA_D0_IRQ_STATUS();
+       bfin_read_IMDMA_D1_IRQ_STATUS();
+#endif
+
+#ifdef DEBUG_SERIAL_EARLY_INIT
+       bfin_console_init();    /* early console registration */
+       /* this give a chance to get printk() working before crash. */
+#endif
+
+#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
+       /* we need to initialize the Flashrom device here since we might
+        * do things with flash early on in the boot
+        */
+       flash_probe();
+#endif
+
+#if defined(CONFIG_CMDLINE_BOOL)
+       memset(command_line, 0, sizeof(command_line));
+       strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
+       command_line[sizeof(command_line) - 1] = 0;
+#endif
+
+       /* Keep a copy of command line */
+       *cmdline_p = &command_line[0];
+       memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+       boot_command_line[COMMAND_LINE_SIZE - 1] = 0;
+
+       /* setup memory defaults from the user config */
+       physical_mem_end = 0;
+       _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
+
+       parse_cmdline_early(&command_line[0]);
+
+       if (physical_mem_end == 0)
+               physical_mem_end = _ramend;
+
+       /* by now the stack is part of the init task */
+       memory_end = _ramend - DMA_UNCACHED_REGION;
+
+       _ramstart = (unsigned long)__bss_stop;
+       memory_start = PAGE_ALIGN(_ramstart);
+
+#if defined(CONFIG_MTD_UCLINUX)
+       /* generic memory mapped MTD driver */
+       memory_mtd_end = memory_end;
+
+       mtd_phys = _ramstart;
+       mtd_size = PAGE_ALIGN(*((unsigned long *)(mtd_phys + 8)));
+
+# if defined(CONFIG_EXT2_FS) || defined(CONFIG_EXT3_FS)
+       if (*((unsigned short *)(mtd_phys + 0x438)) == EXT2_SUPER_MAGIC)
+               mtd_size =
+                   PAGE_ALIGN(*((unsigned long *)(mtd_phys + 0x404)) << 10);
+# endif
+
+# if defined(CONFIG_CRAMFS)
+       if (*((unsigned long *)(mtd_phys)) == CRAMFS_MAGIC)
+               mtd_size = PAGE_ALIGN(*((unsigned long *)(mtd_phys + 0x4)));
+# endif
+
+# if defined(CONFIG_ROMFS_FS)
+       if (((unsigned long *)mtd_phys)[0] == ROMSB_WORD0
+           && ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1)
+               mtd_size =
+                   PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2]));
+#  if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+       /* Due to a Hardware Anomaly we need to limit the size of usable
+        * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
+        * 05000263 - Hardware loop corrupted when taking an ICPLB exception
+        */
+#   if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
+       if (memory_end >= 56 * 1024 * 1024)
+               memory_end = 56 * 1024 * 1024;
+#   else
+       if (memory_end >= 60 * 1024 * 1024)
+               memory_end = 60 * 1024 * 1024;
+#   endif                              /* CONFIG_DEBUG_HUNT_FOR_ZERO */
+#  endif                               /* ANOMALY_05000263 */
+# endif                                /* CONFIG_ROMFS_FS */
+
+       memory_end -= mtd_size;
+
+       if (mtd_size == 0) {
+               console_init();
+               panic("Don't boot kernel without rootfs attached.\n");
+       }
+
+       /* Relocate MTD image to the top of memory after the uncached memory area */
+       dma_memcpy((char *)memory_end, __bss_stop, mtd_size);
+
+       memory_mtd_start = memory_end;
+       _ebss = memory_mtd_start;       /* define _ebss for compatible */
+#endif                         /* CONFIG_MTD_UCLINUX */
+
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+       /* Due to a Hardware Anomaly we need to limit the size of usable
+        * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
+        * 05000263 - Hardware loop corrupted when taking an ICPLB exception
+        */
+#if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
+       if (memory_end >= 56 * 1024 * 1024)
+               memory_end = 56 * 1024 * 1024;
+#else
+       if (memory_end >= 60 * 1024 * 1024)
+               memory_end = 60 * 1024 * 1024;
+#endif                         /* CONFIG_DEBUG_HUNT_FOR_ZERO */
+       printk(KERN_NOTICE "Warning: limiting memory to %liMB due to hardware anomaly 05000263\n", memory_end >> 20);
+#endif                         /* ANOMALY_05000263 */
+
+#if !defined(CONFIG_MTD_UCLINUX)
+       memory_end -= SIZE_4K; /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
+#endif
+       init_mm.start_code = (unsigned long)_stext;
+       init_mm.end_code = (unsigned long)_etext;
+       init_mm.end_data = (unsigned long)_edata;
+       init_mm.brk = (unsigned long)0;
+
+       init_leds();
+
+       printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
+       printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
+       if (bfin_revid() != bfin_compiled_revid())
+               printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
+                      bfin_compiled_revid(), bfin_revid());
+       if (bfin_revid() < SUPPORTED_REVID)
+               printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
+                      CPU, bfin_revid());
+       printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
+
+       printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu Mhz System Clock\n",
+              cclk / 1000000,  sclk / 1000000);
+
+#if defined(ANOMALY_05000273)
+       if ((cclk >> 1) <= sclk)
+               printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
+#endif
+
+       printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20);
+       printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
+
+       printk(KERN_INFO "Memory map:\n"
+              KERN_INFO "  text      = 0x%p-0x%p\n"
+              KERN_INFO "  init      = 0x%p-0x%p\n"
+              KERN_INFO "  data      = 0x%p-0x%p\n"
+              KERN_INFO "  stack     = 0x%p-0x%p\n"
+              KERN_INFO "  bss       = 0x%p-0x%p\n"
+              KERN_INFO "  available = 0x%p-0x%p\n"
+#ifdef CONFIG_MTD_UCLINUX
+              KERN_INFO "  rootfs    = 0x%p-0x%p\n"
+#endif
+#if DMA_UNCACHED_REGION > 0
+              KERN_INFO "  DMA Zone  = 0x%p-0x%p\n"
+#endif
+              , _stext, _etext,
+              __init_begin, __init_end,
+              _sdata, _edata,
+              (void*)&init_thread_union, (void*)((int)(&init_thread_union) + 0x2000),
+              __bss_start, __bss_stop,
+              (void*)_ramstart, (void*)memory_end
+#ifdef CONFIG_MTD_UCLINUX
+              , (void*)memory_mtd_start, (void*)(memory_mtd_start + mtd_size)
+#endif
+#if DMA_UNCACHED_REGION > 0
+              , (void*)(_ramend - DMA_UNCACHED_REGION), (void*)(_ramend)
+#endif
+              );
+
+       /*
+        * give all the memory to the bootmap allocator,  tell it to put the
+        * boot mem_map at the start of memory
+        */
+       bootmap_size = init_bootmem_node(NODE_DATA(0), memory_start >> PAGE_SHIFT,      /* map goes here */
+                                        PAGE_OFFSET >> PAGE_SHIFT,
+                                        memory_end >> PAGE_SHIFT);
+       /*
+        * free the usable memory,  we have to make sure we do not free
+        * the bootmem bitmap so we then reserve it after freeing it :-)
+        */
+       free_bootmem(memory_start, memory_end - memory_start);
+
+       reserve_bootmem(memory_start, bootmap_size);
+       /*
+        * get kmalloc into gear
+        */
+       paging_init();
+
+       /* check the size of the l1 area */
+       l1_length = _etext_l1 - _stext_l1;
+       if (l1_length > L1_CODE_LENGTH)
+               panic("L1 memory overflow\n");
+
+       l1_length = _ebss_l1 - _sdata_l1;
+       if (l1_length > L1_DATA_A_LENGTH)
+               panic("L1 memory overflow\n");
+
+       bf53x_cache_init();
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+# if defined(CONFIG_BFIN_SHARED_FLASH_ENET) && defined(CONFIG_BFIN533_STAMP)
+       /* setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC */
+       bfin_write_FIO_DIR(bfin_read_FIO_DIR() | (1 << CONFIG_ENET_FLASH_PIN));
+       bfin_write_FIO_FLAG_S(1 << CONFIG_ENET_FLASH_PIN);
+       SSYNC();
+# endif
+# if defined (CONFIG_BFIN561_EZKIT)
+       bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | (1 << 12));
+       SSYNC();
+# endif /* defined (CONFIG_BFIN561_EZKIT) */
+#endif
+
+       printk(KERN_INFO "Hardware Trace Enabled\n");
+       bfin_write_TBUFCTL(0x03);
+}
+
+#if defined(CONFIG_BF561)
+static struct cpu cpu[2];
+#else
+static struct cpu cpu[1];
+#endif
+static int __init topology_init(void)
+{
+#if defined (CONFIG_BF561)
+       register_cpu(&cpu[0], 0);
+       register_cpu(&cpu[1], 1);
+       return 0;
+#else
+       return register_cpu(cpu, 0);
+#endif
+}
+
+subsys_initcall(topology_init);
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+u16 lock_kernel_check(u32 start, u32 end)
+{
+       if ((start <= (u32) _stext && end >= (u32) _end)
+           || (start >= (u32) _stext && end <= (u32) _end))
+               return IN_KERNEL;
+       return 0;
+}
+
+static unsigned short __init
+fill_cplbtab(struct cplb_tab *table,
+            unsigned long start, unsigned long end,
+            unsigned long block_size, unsigned long cplb_data)
+{
+       int i;
+
+       switch (block_size) {
+       case SIZE_4M:
+               i = 3;
+               break;
+       case SIZE_1M:
+               i = 2;
+               break;
+       case SIZE_4K:
+               i = 1;
+               break;
+       case SIZE_1K:
+       default:
+               i = 0;
+               break;
+       }
+
+       cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
+
+       while ((start < end) && (table->pos < table->size)) {
+
+               table->tab[table->pos++] = start;
+
+               if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
+                       table->tab[table->pos++] =
+                           cplb_data | CPLB_LOCK | CPLB_DIRTY;
+               else
+                       table->tab[table->pos++] = cplb_data;
+
+               start += block_size;
+       }
+       return 0;
+}
+
+static unsigned short __init
+close_cplbtab(struct cplb_tab *table)
+{
+
+       while (table->pos < table->size) {
+
+               table->tab[table->pos++] = 0;
+               table->tab[table->pos++] = 0; /* !CPLB_VALID */
+       }
+       return 0;
+}
+
+static void __init generate_cpl_tables(void)
+{
+
+       u16 i, j, process;
+       u32 a_start, a_end, as, ae, as_1m;
+
+       struct cplb_tab *t_i = NULL;
+       struct cplb_tab *t_d = NULL;
+       struct s_cplb cplb;
+
+       cplb.init_i.size = MAX_CPLBS;
+       cplb.init_d.size = MAX_CPLBS;
+       cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+       cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
+
+       cplb.init_i.pos = 0;
+       cplb.init_d.pos = 0;
+       cplb.switch_i.pos = 0;
+       cplb.switch_d.pos = 0;
+
+       cplb.init_i.tab = icplb_table;
+       cplb.init_d.tab = dcplb_table;
+       cplb.switch_i.tab = ipdt_table;
+       cplb.switch_d.tab = dpdt_table;
+
+       cplb_data[SDRAM_KERN].end = memory_end;
+
+#ifdef CONFIG_MTD_UCLINUX
+       cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
+       cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
+       cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
+# if defined(CONFIG_ROMFS_FS)
+       cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
+
+       /*
+        * The ROMFS_FS size is often not multiple of 1MB.
+        * This can cause multiple CPLB sets covering the same memory area.
+        * This will then cause multiple CPLB hit exceptions.
+        * Workaround: We ensure a contiguous memory area by extending the kernel
+        * memory section over the mtd section.
+        * For ROMFS_FS memory must be covered with ICPLBs anyways.
+        * So there is no difference between kernel and mtd memory setup.
+        */
+
+       cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
+       cplb_data[SDRAM_RAM_MTD].valid = 0;
+
+# endif
+#else
+       cplb_data[SDRAM_RAM_MTD].valid = 0;
+#endif
+
+       cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
+       cplb_data[SDRAM_DMAZ].end = _ramend;
+
+       cplb_data[RES_MEM].start = _ramend;
+       cplb_data[RES_MEM].end = physical_mem_end;
+
+       if (reserved_mem_dcache_on)
+               cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
+       else
+               cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
+
+       if (reserved_mem_icache_on)
+               cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
+       else
+               cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
+
+       for (i = ZERO_P; i <= L2_MEM; i++) {
+
+               if (cplb_data[i].valid) {
+
+                       as_1m = cplb_data[i].start % SIZE_1M;
+
+                       /* We need to make sure all sections are properly 1M aligned
+                        * However between Kernel Memory and the Kernel mtd section, depending on the
+                        * rootfs size, there can be overlapping memory areas.
+                        */
+
+                       if (as_1m &&  i!=L1I_MEM && i!=L1D_MEM) {
+#ifdef CONFIG_MTD_UCLINUX
+                               if (i == SDRAM_RAM_MTD) {
+                                       if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
+                                               cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
+                                       else
+                                               cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
+                               } else
+#endif
+                                       printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
+                                              cplb_data[i].name, cplb_data[i].start);
+                       }
+
+                       as = cplb_data[i].start % SIZE_4M;
+                       ae = cplb_data[i].end % SIZE_4M;
+
+                       if (as)
+                               a_start = cplb_data[i].start + (SIZE_4M - (as));
+                       else
+                               a_start = cplb_data[i].start;
+
+                       a_end = cplb_data[i].end - ae;
+
+                       for (j = INITIAL_T; j <= SWITCH_T; j++) {
+
+                               switch (j) {
+                               case INITIAL_T:
+                                       if (cplb_data[i].attr & INITIAL_T) {
+                                               t_i = &cplb.init_i;
+                                               t_d = &cplb.init_d;
+                                               process = 1;
+                                       } else
+                                               process = 0;
+                                       break;
+                               case SWITCH_T:
+                                       if (cplb_data[i].attr & SWITCH_T) {
+                                               t_i = &cplb.switch_i;
+                                               t_d = &cplb.switch_d;
+                                               process = 1;
+                                       } else
+                                               process = 0;
+                                       break;
+                               default:
+                                               process = 0;
+                                       break;
+                               }
+
+       if (process) {
+                               if (cplb_data[i].attr & I_CPLB) {
+
+                                       if (cplb_data[i].psize) {
+                                               fill_cplbtab(t_i,
+                                                            cplb_data[i].start,
+                                                            cplb_data[i].end,
+                                                            cplb_data[i].psize,
+                                                            cplb_data[i].i_conf);
+                                       } else {
+                                               /*icplb_table */
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+                                               if (i == SDRAM_KERN) {
+                                                       fill_cplbtab(t_i,
+                                                                    cplb_data[i].start,
+                                                                    cplb_data[i].end,
+                                                                    SIZE_4M,
+                                                                    cplb_data[i].i_conf);
+                                               } else
+#endif
+                                               {
+                                                       fill_cplbtab(t_i,
+                                                                    cplb_data[i].start,
+                                                                    a_start,
+                                                                    SIZE_1M,
+                                                                    cplb_data[i].i_conf);
+                                                       fill_cplbtab(t_i,
+                                                                    a_start,
+                                                                    a_end,
+                                                                    SIZE_4M,
+                                                                    cplb_data[i].i_conf);
+                                                       fill_cplbtab(t_i, a_end,
+                                                                    cplb_data[i].end,
+                                                                    SIZE_1M,
+                                                                    cplb_data[i].i_conf);
+                                               }
+                                       }
+
+                               }
+                               if (cplb_data[i].attr & D_CPLB) {
+
+                                       if (cplb_data[i].psize) {
+                                               fill_cplbtab(t_d,
+                                                            cplb_data[i].start,
+                                                            cplb_data[i].end,
+                                                            cplb_data[i].psize,
+                                                            cplb_data[i].d_conf);
+                                       } else {
+/*dcplb_table*/
+                                               fill_cplbtab(t_d,
+                                                            cplb_data[i].start,
+                                                            a_start, SIZE_1M,
+                                                            cplb_data[i].d_conf);
+                                               fill_cplbtab(t_d, a_start,
+                                                            a_end, SIZE_4M,
+                                                            cplb_data[i].d_conf);
+                                               fill_cplbtab(t_d, a_end,
+                                                            cplb_data[i].end,
+                                                            SIZE_1M,
+                                                            cplb_data[i].d_conf);
+
+                                       }
+
+                               }
+                       }
+                       }
+
+               }
+       }
+
+/* close tables */
+
+       close_cplbtab(&cplb.init_i);
+       close_cplbtab(&cplb.init_d);
+
+       cplb.init_i.tab[cplb.init_i.pos] = -1;
+       cplb.init_d.tab[cplb.init_d.pos] = -1;
+       cplb.switch_i.tab[cplb.switch_i.pos] = -1;
+       cplb.switch_d.tab[cplb.switch_d.pos] = -1;
+
+}
+
+#endif
+
+static inline u_long get_vco(void)
+{
+       u_long msel;
+       u_long vco;
+
+       msel = (bfin_read_PLL_CTL() >> 9) & 0x3F;
+       if (0 == msel)
+               msel = 64;
+
+       vco = CONFIG_CLKIN_HZ;
+       vco >>= (1 & bfin_read_PLL_CTL());      /* DF bit */
+       vco = msel * vco;
+       return vco;
+}
+
+/*Get the Core clock*/
+u_long get_cclk(void)
+{
+       u_long csel, ssel;
+       if (bfin_read_PLL_STAT() & 0x1)
+               return CONFIG_CLKIN_HZ;
+
+       ssel = bfin_read_PLL_DIV();
+       csel = ((ssel >> 4) & 0x03);
+       ssel &= 0xf;
+       if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */
+               return get_vco() / ssel;
+       return get_vco() >> csel;
+}
+
+EXPORT_SYMBOL(get_cclk);
+
+/* Get the System clock */
+u_long get_sclk(void)
+{
+       u_long ssel;
+
+       if (bfin_read_PLL_STAT() & 0x1)
+               return CONFIG_CLKIN_HZ;
+
+       ssel = (bfin_read_PLL_DIV() & 0xf);
+       if (0 == ssel) {
+               printk(KERN_WARNING "Invalid System Clock\n");
+               ssel = 1;
+       }
+
+       return get_vco() / ssel;
+}
+
+EXPORT_SYMBOL(get_sclk);
+
+/*
+ *     Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+       char *cpu, *mmu, *fpu, *name;
+       uint32_t revid;
+
+       u_long cclk = 0, sclk = 0;
+       u_int dcache_size = 0, dsup_banks = 0;
+
+       cpu = CPU;
+       mmu = "none";
+       fpu = "none";
+       revid = bfin_revid();
+       name = bfin_board_name;
+
+       cclk = get_cclk();
+       sclk = get_sclk();
+
+       seq_printf(m, "CPU:\t\tADSP-%s Rev. 0.%d\n"
+                  "MMU:\t\t%s\n"
+                  "FPU:\t\t%s\n"
+                  "Core Clock:\t%9lu Hz\n"
+                  "System Clock:\t%9lu Hz\n"
+                  "BogoMips:\t%lu.%02lu\n"
+                  "Calibration:\t%lu loops\n",
+                  cpu, revid, mmu, fpu,
+                  cclk,
+                  sclk,
+                  (loops_per_jiffy * HZ) / 500000,
+                  ((loops_per_jiffy * HZ) / 5000) % 100,
+                  (loops_per_jiffy * HZ));
+       seq_printf(m, "Board Name:\t%s\n", name);
+       seq_printf(m, "Board Memory:\t%ld MB\n", physical_mem_end >> 20);
+       seq_printf(m, "Kernel Memory:\t%ld MB\n", (unsigned long)_ramend >> 20);
+       if (bfin_read_IMEM_CONTROL() & (ENICPLB | IMC))
+               seq_printf(m, "I-CACHE:\tON\n");
+       else
+               seq_printf(m, "I-CACHE:\tOFF\n");
+       if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE))
+               seq_printf(m, "D-CACHE:\tON"
+#if defined CONFIG_BLKFIN_WB
+                          " (write-back)"
+#elif defined CONFIG_BLKFIN_WT
+                          " (write-through)"
+#endif
+                          "\n");
+       else
+               seq_printf(m, "D-CACHE:\tOFF\n");
+
+
+       switch(bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
+               case ACACHE_BSRAM:
+                       seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
+                       dcache_size = 16;
+                       dsup_banks = 1;
+                       break;
+               case ACACHE_BCACHE:
+                       seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
+                       dcache_size = 32;
+                       dsup_banks = 2;
+                       break;
+               case ASRAM_BSRAM:
+                       seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
+                       dcache_size = 0;
+                       dsup_banks = 0;
+                       break;
+               default:
+               break;
+       }
+
+
+       seq_printf(m, "I-CACHE Size:\t%dKB\n", BLKFIN_ICACHESIZE / 1024);
+       seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size);
+       seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n",
+                  BLKFIN_ISUBBANKS, BLKFIN_IWAYS, BLKFIN_ILINES);
+       seq_printf(m,
+                  "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
+                  dsup_banks, BLKFIN_DSUBBANKS, BLKFIN_DWAYS,
+                  BLKFIN_DLINES);
+#ifdef CONFIG_BLKFIN_CACHE_LOCK
+       switch (read_iloc()) {
+       case WAY0_L:
+               seq_printf(m, "Way0 Locked-Down\n");
+               break;
+       case WAY1_L:
+               seq_printf(m, "Way1 Locked-Down\n");
+               break;
+       case WAY01_L:
+               seq_printf(m, "Way0,Way1 Locked-Down\n");
+               break;
+       case WAY2_L:
+               seq_printf(m, "Way2 Locked-Down\n");
+               break;
+       case WAY02_L:
+               seq_printf(m, "Way0,Way2 Locked-Down\n");
+               break;
+       case WAY12_L:
+               seq_printf(m, "Way1,Way2 Locked-Down\n");
+               break;
+       case WAY012_L:
+               seq_printf(m, "Way0,Way1 & Way2 Locked-Down\n");
+               break;
+       case WAY3_L:
+               seq_printf(m, "Way3 Locked-Down\n");
+               break;
+       case WAY03_L:
+               seq_printf(m, "Way0,Way3 Locked-Down\n");
+               break;
+       case WAY13_L:
+               seq_printf(m, "Way1,Way3 Locked-Down\n");
+               break;
+       case WAY013_L:
+               seq_printf(m, "Way 0,Way1,Way3 Locked-Down\n");
+               break;
+       case WAY32_L:
+               seq_printf(m, "Way3,Way2 Locked-Down\n");
+               break;
+       case WAY320_L:
+               seq_printf(m, "Way3,Way2,Way0 Locked-Down\n");
+               break;
+       case WAY321_L:
+               seq_printf(m, "Way3,Way2,Way1 Locked-Down\n");
+               break;
+       case WAYALL_L:
+               seq_printf(m, "All Ways are locked\n");
+               break;
+       default:
+               seq_printf(m, "No Ways are locked\n");
+       }
+#endif
+       return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos < NR_CPUS ? ((void *)0x12345678) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return c_start(m, pos);
+}
+
+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,
+};
+
+void cmdline_init(unsigned long r0)
+{
+       if (r0)
+               strncpy(command_line, (char *)r0, COMMAND_LINE_SIZE);
+}
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
new file mode 100644 (file)
index 0000000..316e65c
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * File:         arch/blackfin/kernel/signal.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ptrace.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+#include <linux/freezer.h>
+
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct fdpic_func_descriptor {
+       unsigned long   text;
+       unsigned long   GOT;
+};
+
+struct rt_sigframe {
+       int sig;
+       struct siginfo *pinfo;
+       void *puc;
+       char retcode[8];
+       struct siginfo info;
+       struct ucontext uc;
+};
+
+asmlinkage int sys_sigaltstack(const stack_t * uss, stack_t * uoss)
+{
+       return do_sigaltstack(uss, uoss, rdusp());
+}
+
+static inline int
+rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *pr0)
+{
+       unsigned long usp = 0;
+       int err = 0;
+
+#define RESTORE(x) err |= __get_user(regs->x, &sc->sc_##x)
+
+       /* restore passed registers */
+       RESTORE(r0); RESTORE(r1); RESTORE(r2); RESTORE(r3);
+       RESTORE(r4); RESTORE(r5); RESTORE(r6); RESTORE(r7);
+       RESTORE(p0); RESTORE(p1); RESTORE(p2); RESTORE(p3);
+       RESTORE(p4); RESTORE(p5);
+       err |= __get_user(usp, &sc->sc_usp);
+       wrusp(usp);
+       RESTORE(a0w); RESTORE(a1w);
+       RESTORE(a0x); RESTORE(a1x);
+       RESTORE(astat);
+       RESTORE(rets);
+       RESTORE(pc);
+       RESTORE(retx);
+       RESTORE(fp);
+       RESTORE(i0); RESTORE(i1); RESTORE(i2); RESTORE(i3);
+       RESTORE(m0); RESTORE(m1); RESTORE(m2); RESTORE(m3);
+       RESTORE(l0); RESTORE(l1); RESTORE(l2); RESTORE(l3);
+       RESTORE(b0); RESTORE(b1); RESTORE(b2); RESTORE(b3);
+       RESTORE(lc0); RESTORE(lc1);
+       RESTORE(lt0); RESTORE(lt1);
+       RESTORE(lb0); RESTORE(lb1);
+       RESTORE(seqstat);
+
+       regs->orig_p0 = -1;     /* disable syscall checks */
+
+       *pr0 = regs->r0;
+       return err;
+}
+
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
+{
+       struct pt_regs *regs = (struct pt_regs *)__unused;
+       unsigned long usp = rdusp();
+       struct rt_sigframe *frame = (struct rt_sigframe *)(usp);
+       sigset_t set;
+       int r0;
+
+       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+               goto badframe;
+
+       sigdelsetmask(&set, ~_BLOCKABLE);
+       spin_lock_irq(&current->sighand->siglock);
+       current->blocked = set;
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+
+       if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+               goto badframe;
+
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->usp) == -EFAULT)
+               goto badframe;
+
+       return r0;
+
+      badframe:
+       force_sig(SIGSEGV, current);
+       return 0;
+}
+
+static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
+{
+       int err = 0;
+
+#define SETUP(x) err |= __put_user(regs->x, &sc->sc_##x)
+
+       SETUP(r0); SETUP(r1); SETUP(r2); SETUP(r3);
+       SETUP(r4); SETUP(r5); SETUP(r6); SETUP(r7);
+       SETUP(p0); SETUP(p1); SETUP(p2); SETUP(p3);
+       SETUP(p4); SETUP(p5);
+       err |= __put_user(rdusp(), &sc->sc_usp);
+       SETUP(a0w); SETUP(a1w);
+       SETUP(a0x); SETUP(a1x);
+       SETUP(astat);
+       SETUP(rets);
+       SETUP(pc);
+       SETUP(retx);
+       SETUP(fp);
+       SETUP(i0); SETUP(i1); SETUP(i2); SETUP(i3);
+       SETUP(m0); SETUP(m1); SETUP(m2); SETUP(m3);
+       SETUP(l0); SETUP(l1); SETUP(l2); SETUP(l3);
+       SETUP(b0); SETUP(b1); SETUP(b2); SETUP(b3);
+       SETUP(lc0); SETUP(lc1);
+       SETUP(lt0); SETUP(lt1);
+       SETUP(lb0); SETUP(lb1);
+       SETUP(seqstat);
+
+       return err;
+}
+
+static inline void push_cache(unsigned long vaddr, unsigned int len)
+{
+       flush_icache_range(vaddr, vaddr + len);
+}
+
+static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+                                size_t frame_size)
+{
+       unsigned long usp;
+
+       /* Default to using normal stack.  */
+       usp = rdusp();
+
+       /* This is the X/Open sanctioned signal stack switching.  */
+       if (ka->sa.sa_flags & SA_ONSTACK) {
+               if (!on_sig_stack(usp))
+                       usp = current->sas_ss_sp + current->sas_ss_size;
+       }
+       return (void *)((usp - frame_size) & -8UL);
+}
+
+static int
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+              sigset_t * set, struct pt_regs *regs)
+{
+       struct rt_sigframe *frame;
+       int err = 0;
+
+       frame = get_sigframe(ka, regs, sizeof(*frame));
+
+       err |= __put_user((current_thread_info()->exec_domain
+                          && current_thread_info()->exec_domain->signal_invmap
+                          && sig < 32
+                          ? current_thread_info()->exec_domain->
+                          signal_invmap[sig] : sig), &frame->sig);
+
+       err |= __put_user(&frame->info, &frame->pinfo);
+       err |= __put_user(&frame->uc, &frame->puc);
+       err |= copy_siginfo_to_user(&frame->info, info);
+
+       /* Create the ucontext.  */
+       err |= __put_user(0, &frame->uc.uc_flags);
+       err |= __put_user(0, &frame->uc.uc_link);
+       err |=
+           __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+       err |= __put_user(sas_ss_flags(rdusp()), &frame->uc.uc_stack.ss_flags);
+       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+       err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
+       err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+       /* Set up to return from userspace.  */
+       err |= __put_user(0x28, &(frame->retcode[0]));
+       err |= __put_user(0xe1, &(frame->retcode[1]));
+       err |= __put_user(0xad, &(frame->retcode[2]));
+       err |= __put_user(0x00, &(frame->retcode[3]));
+       err |= __put_user(0xa0, &(frame->retcode[4]));
+       err |= __put_user(0x00, &(frame->retcode[5]));
+
+       if (err)
+               goto give_sigsegv;
+
+       push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode));
+
+       /* Set up registers for signal handler */
+       wrusp((unsigned long)frame);
+       if (get_personality & FDPIC_FUNCPTRS) {
+               struct fdpic_func_descriptor __user *funcptr =
+                       (struct fdpic_func_descriptor *) ka->sa.sa_handler;
+               __get_user(regs->pc, &funcptr->text);
+               __get_user(regs->p3, &funcptr->GOT);
+       } else
+               regs->pc = (unsigned long)ka->sa.sa_handler;
+       regs->rets = (unsigned long)(frame->retcode);
+
+       regs->r0 = frame->sig;
+       regs->r1 = (unsigned long)(&frame->info);
+       regs->r2 = (unsigned long)(&frame->uc);
+
+       return 0;
+
+      give_sigsegv:
+       if (sig == SIGSEGV)
+               ka->sa.sa_handler = SIG_DFL;
+       force_sig(SIGSEGV, current);
+       return -EFAULT;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+       switch (regs->r0) {
+       case -ERESTARTNOHAND:
+               if (!has_handler)
+                       goto do_restart;
+               regs->r0 = -EINTR;
+               break;
+
+       case -ERESTARTSYS:
+               if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+                       regs->r0 = -EINTR;
+                       break;
+               }
+               /* fallthrough */
+       case -ERESTARTNOINTR:
+             do_restart:
+               regs->p0 = regs->orig_p0;
+               regs->r0 = regs->orig_r0;
+               regs->pc -= 2;
+               break;
+       }
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static int
+handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+             sigset_t *oldset, struct pt_regs *regs)
+{
+       int ret;
+
+       /* are we from a system call? to see pt_regs->orig_p0 */
+       if (regs->orig_p0 >= 0)
+               /* If so, check system call restarting.. */
+               handle_restart(regs, ka, 1);
+
+       /* set up the stack frame */
+       ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+       if (ret == 0) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked, &current->blocked,
+                         &ka->sa.sa_mask);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked, sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
+       return ret;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals
+ * that the kernel can handle, and then we build all the user-level signal
+ * handling stack-frames in one go after that.
+ */
+asmlinkage void do_signal(struct pt_regs *regs)
+{
+       siginfo_t info;
+       int signr;
+       struct k_sigaction ka;
+       sigset_t *oldset;
+
+       current->thread.esp0 = (unsigned long)regs;
+
+       if (try_to_freeze())
+               goto no_signal;
+
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
+               oldset = &current->blocked;
+
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+       if (signr > 0) {
+               /* Whee!  Actually deliver the signal.  */
+               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
+
+               return;
+       }
+
+no_signal:
+       /* Did we come from a system call? */
+       if (regs->orig_p0 >= 0)
+               /* Restart the system call - no handlers present */
+               handle_restart(regs, NULL, 0);
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+}
diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
new file mode 100644 (file)
index 0000000..f436e67
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * File:         arch/blackfin/kernel/sys_bfin.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains various random system calls that
+ *               have a non-standard calling sequence on the Linux/bfin
+ *               platform.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+#include <asm/dma.h>
+#include <asm/unistd.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+asmlinkage int sys_pipe(unsigned long *fildes)
+{
+       int fd[2];
+       int error;
+
+       error = do_pipe(fd);
+       if (!error) {
+               if (copy_to_user(fildes, fd, 2 * sizeof(int)))
+                       error = -EFAULT;
+       }
+       return error;
+}
+
+/* common code for old and new mmaps */
+static inline long
+do_mmap2(unsigned long addr, unsigned long len,
+        unsigned long prot, unsigned long flags,
+        unsigned long fd, unsigned long pgoff)
+{
+       int error = -EBADF;
+       struct file *file = NULL;
+
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+       if (!(flags & MAP_ANONYMOUS)) {
+               file = fget(fd);
+               if (!file)
+                       goto out;
+       }
+
+       down_write(&current->mm->mmap_sem);
+       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+       up_write(&current->mm->mmap_sem);
+
+       if (file)
+               fput(file);
+      out:
+       return error;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+                         unsigned long prot, unsigned long flags,
+                         unsigned long fd, unsigned long pgoff)
+{
+       return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+asmlinkage int sys_getpagesize(void)
+{
+       return PAGE_SIZE;
+}
+
+asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
+{
+       return sram_alloc_with_lsl(size, flags);
+}
+
+asmlinkage int sys_sram_free(const void *addr)
+{
+       return sram_free_with_lsl(addr);
+}
+
+asmlinkage void *sys_dma_memcpy(void *dest, const void *src, size_t len)
+{
+       return safe_dma_memcpy(dest, src, len);
+}
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
new file mode 100644 (file)
index 0000000..f578176
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * File:         arch/blackfin/kernel/time.c
+ * Based on:     none - original work
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the bfin-specific time handling details.
+ *               Most of the stuff is located in the machine specific files.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/profile.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+
+#include <asm/blackfin.h>
+
+/* This is an NTP setting */
+#define        TICK_SIZE (tick_nsec / 1000)
+
+static void time_sched_init(irqreturn_t(*timer_routine)
+                       (int, void *));
+static unsigned long gettimeoffset(void);
+static inline void do_leds(void);
+
+#if (defined(CONFIG_BFIN_ALIVE_LED) || defined(CONFIG_BFIN_IDLE_LED))
+void __init init_leds(void)
+{
+       unsigned int tmp = 0;
+
+#if defined(CONFIG_BFIN_ALIVE_LED)
+       /* config pins as output. */
+       tmp = bfin_read_CONFIG_BFIN_ALIVE_LED_DPORT();
+       SSYNC();
+       bfin_write_CONFIG_BFIN_ALIVE_LED_DPORT(tmp | CONFIG_BFIN_ALIVE_LED_PIN);
+       SSYNC();
+
+       /*      First set led be off */
+       tmp = bfin_read_CONFIG_BFIN_ALIVE_LED_PORT();
+       SSYNC();
+       bfin_write_CONFIG_BFIN_ALIVE_LED_PORT(tmp | CONFIG_BFIN_ALIVE_LED_PIN); /* light off */
+       SSYNC();
+#endif
+
+#if defined(CONFIG_BFIN_IDLE_LED)
+       /* config pins as output. */
+       tmp = bfin_read_CONFIG_BFIN_IDLE_LED_DPORT();
+       SSYNC();
+       bfin_write_CONFIG_BFIN_IDLE_LED_DPORT(tmp | CONFIG_BFIN_IDLE_LED_PIN);
+       SSYNC();
+
+       /*      First set led be off */
+       tmp = bfin_read_CONFIG_BFIN_IDLE_LED_PORT();
+       SSYNC();
+       bfin_write_CONFIG_BFIN_IDLE_LED_PORT(tmp | CONFIG_BFIN_IDLE_LED_PIN);   /* light off */
+       SSYNC();
+#endif
+}
+#else
+void __init init_leds(void)
+{
+}
+#endif
+
+#if defined(CONFIG_BFIN_ALIVE_LED)
+static inline void do_leds(void)
+{
+       static unsigned int count = 50;
+       static int flag = 0;
+       unsigned short tmp = 0;
+
+       if (--count == 0) {
+               count = 50;
+               flag = ~flag;
+       }
+       tmp = bfin_read_CONFIG_BFIN_ALIVE_LED_PORT();
+       SSYNC();
+
+       if (flag)
+               tmp &= ~CONFIG_BFIN_ALIVE_LED_PIN;      /* light on */
+       else
+               tmp |= CONFIG_BFIN_ALIVE_LED_PIN;       /* light off */
+
+       bfin_write_CONFIG_BFIN_ALIVE_LED_PORT(tmp);
+       SSYNC();
+
+}
+#else
+static inline void do_leds(void)
+{
+}
+#endif
+
+static struct irqaction bfin_timer_irq = {
+       .name = "BFIN Timer Tick",
+       .flags = IRQF_DISABLED
+};
+
+/*
+ * The way that the Blackfin core timer works is:
+ *  - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
+ *  - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
+ *
+ * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
+ *    10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
+ *    (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
+ *    to use TSCALE, and program it to zero (which is pass CCLK through).
+ *    If you feel like using it, try to keep HZ * TIMESCALE to some
+ *    value that divides easy (like power of 2).
+ */
+
+#define TIME_SCALE 1
+
+static void
+time_sched_init(irqreturn_t(*timer_routine) (int, void *))
+{
+       u32 tcount;
+
+       /* power up the timer, but don't enable it just yet */
+       bfin_write_TCNTL(1);
+       CSYNC();
+
+       /*
+        * the TSCALE prescaler counter.
+        */
+       bfin_write_TSCALE((TIME_SCALE - 1));
+
+       tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
+       bfin_write_TPERIOD(tcount);
+       bfin_write_TCOUNT(tcount);
+
+       /* now enable the timer */
+       CSYNC();
+
+       bfin_write_TCNTL(7);
+
+       bfin_timer_irq.handler = (irq_handler_t)timer_routine;
+       /* call setup_irq instead of request_irq because request_irq calls
+        * kmalloc which has not been initialized yet
+        */
+       setup_irq(IRQ_CORETMR, &bfin_timer_irq);
+}
+
+/*
+ * Should return useconds since last timer tick
+ */
+static unsigned long gettimeoffset(void)
+{
+       unsigned long offset;
+       unsigned long clocks_per_jiffy;
+
+       clocks_per_jiffy = bfin_read_TPERIOD();
+       offset =
+           (clocks_per_jiffy -
+            bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) /
+                                   USEC_PER_SEC);
+
+       /* Check if we just wrapped the counters and maybe missed a tick */
+       if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
+           && (offset < (100000 / HZ / 2)))
+               offset += (USEC_PER_SEC / HZ);
+
+       return offset;
+}
+
+static inline int set_rtc_mmss(unsigned long nowtime)
+{
+       return 0;
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+#ifdef CONFIG_CORE_TIMER_IRQ_L1
+irqreturn_t timer_interrupt(int irq, void *dummy)__attribute__((l1_text));
+#endif
+
+irqreturn_t timer_interrupt(int irq, void *dummy)
+{
+       /* last time the cmos clock got updated */
+       static long last_rtc_update = 0;
+
+       write_seqlock(&xtime_lock);
+
+       do_timer(1);
+       do_leds();
+
+#ifndef CONFIG_SMP
+       update_process_times(user_mode(get_irq_regs()));
+#endif
+       profile_tick(CPU_PROFILING);
+
+       /*
+        * If we have an externally synchronized Linux clock, then update
+        * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+        * called as close as possible to 500 ms before the new second starts.
+        */
+
+       if (ntp_synced() &&
+           xtime.tv_sec > last_rtc_update + 660 &&
+           (xtime.tv_nsec / NSEC_PER_USEC) >=
+           500000 - ((unsigned)TICK_SIZE) / 2
+           && (xtime.tv_nsec / NSEC_PER_USEC) <=
+           500000 + ((unsigned)TICK_SIZE) / 2) {
+               if (set_rtc_mmss(xtime.tv_sec) == 0)
+                       last_rtc_update = xtime.tv_sec;
+               else
+                       /* Do it again in 60s. */
+                       last_rtc_update = xtime.tv_sec - 600;
+       }
+       write_sequnlock(&xtime_lock);
+       return IRQ_HANDLED;
+}
+
+void __init time_init(void)
+{
+       time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
+
+#ifdef CONFIG_RTC_DRV_BFIN
+       /* [#2663] hack to filter junk RTC values that would cause
+        * userspace to have to deal with time values greater than
+        * 2^31 seconds (which uClibc cannot cope with yet)
+        */
+       if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
+               printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
+               bfin_write_RTC_STAT(0);
+       }
+#endif
+
+       /* Initialize xtime. From now on, xtime is updated with timer interrupts */
+       xtime.tv_sec = secs_since_1970;
+       xtime.tv_nsec = 0;
+
+       wall_to_monotonic.tv_sec = -xtime.tv_sec;
+
+       time_sched_init(timer_interrupt);
+}
+
+#ifndef CONFIG_GENERIC_TIME
+void do_gettimeofday(struct timeval *tv)
+{
+       unsigned long flags;
+       unsigned long seq;
+       unsigned long usec, sec;
+
+       do {
+               seq = read_seqbegin_irqsave(&xtime_lock, flags);
+               usec = gettimeoffset();
+               sec = xtime.tv_sec;
+               usec += (xtime.tv_nsec / NSEC_PER_USEC);
+       }
+       while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+       while (usec >= USEC_PER_SEC) {
+               usec -= USEC_PER_SEC;
+               sec++;
+       }
+
+       tv->tv_sec = sec;
+       tv->tv_usec = usec;
+}
+EXPORT_SYMBOL(do_gettimeofday);
+
+int do_settimeofday(struct timespec *tv)
+{
+       time_t wtm_sec, sec = tv->tv_sec;
+       long wtm_nsec, nsec = tv->tv_nsec;
+
+       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+               return -EINVAL;
+
+       write_seqlock_irq(&xtime_lock);
+       /*
+        * This is revolting. We need to set the xtime.tv_usec
+        * correctly. However, the value in this location is
+        * is value at the last tick.
+        * Discover what correction gettimeofday
+        * would have done, and then undo it!
+        */
+       nsec -= (gettimeoffset() * NSEC_PER_USEC);
+
+       wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+       set_normalized_timespec(&xtime, sec, nsec);
+       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+       ntp_clear();
+
+       write_sequnlock_irq(&xtime_lock);
+       clock_was_set();
+
+       return 0;
+}
+EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+       return (unsigned long long)jiffies *(NSEC_PER_SEC / HZ);
+}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
new file mode 100644 (file)
index 0000000..9556b73
--- /dev/null
@@ -0,0 +1,649 @@
+/*
+ * File:         arch/blackfin/kernel/traps.c
+ * Based on:
+ * Author:       Hamish Macdonald
+ *
+ * Created:
+ * Description:  uses S/W interrupt 15 for the system calls
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+#include <asm/irq_handler.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+#ifdef CONFIG_KGDB
+# include <linux/debugger.h>
+# include <linux/kgdb.h>
+#endif
+
+/* Initiate the event table handler */
+void __init trap_init(void)
+{
+       CSYNC();
+       bfin_write_EVT3(trap);
+       CSYNC();
+}
+
+asmlinkage void trap_c(struct pt_regs *fp);
+
+int kstack_depth_to_print = 48;
+
+static int printk_address(unsigned long address)
+{
+       struct vm_list_struct *vml;
+       struct task_struct *p;
+       struct mm_struct *mm;
+
+#ifdef CONFIG_KALLSYMS
+       unsigned long offset = 0, symsize;
+       const char *symname;
+       char *modname;
+       char *delim = ":";
+       char namebuf[128];
+
+       /* look up the address and see if we are in kernel space */
+       symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
+
+       if (symname) {
+               /* yeah! kernel space! */
+               if (!modname)
+                       modname = delim = "";
+               return printk("<0x%p> { %s%s%s%s + 0x%lx }",
+                             (void*)address, delim, modname, delim, symname,
+                             (unsigned long)offset);
+
+       }
+#endif
+
+       /* looks like we're off in user-land, so let's walk all the
+        * mappings of all our processes and see if we can't be a whee
+        * bit more specific
+        */
+       write_lock_irq(&tasklist_lock);
+       for_each_process(p) {
+               mm = get_task_mm(p);
+               if (!mm)
+                       continue;
+
+               vml = mm->context.vmlist;
+               while (vml) {
+                       struct vm_area_struct *vma = vml->vma;
+
+                       if (address >= vma->vm_start && address < vma->vm_end) {
+                               char *name = p->comm;
+                               struct file *file = vma->vm_file;
+                               if (file) {
+                                       char _tmpbuf[256];
+                                       name = d_path(file->f_dentry,
+                                                     file->f_vfsmnt,
+                                                     _tmpbuf,
+                                                     sizeof(_tmpbuf));
+                               }
+
+                               write_unlock_irq(&tasklist_lock);
+                               return printk("<0x%p> [ %s + 0x%lx ]",
+                                             (void*)address, name,
+                                             (unsigned long)
+                                               ((address - vma->vm_start) +
+                                                (vma->vm_pgoff << PAGE_SHIFT)));
+                       }
+
+                       vml = vml->next;
+               }
+       }
+       write_unlock_irq(&tasklist_lock);
+
+       /* we were unable to find this address anywhere */
+       return printk("[<0x%p>]", (void*)address);
+}
+
+#define trace_buffer_save(x) \
+       do { \
+               (x) = bfin_read_TBUFCTL(); \
+               bfin_write_TBUFCTL((x) & ~TBUFEN); \
+       } while (0)
+#define trace_buffer_restore(x) \
+       do { \
+               bfin_write_TBUFCTL((x));        \
+       } while (0)
+
+asmlinkage void trap_c(struct pt_regs *fp)
+{
+       int j, sig = 0;
+       siginfo_t info;
+       unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
+
+#ifdef CONFIG_KGDB
+# define CHK_DEBUGGER_TRAP() do { CHK_DEBUGGER(trapnr, sig, info.si_code, fp,); } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() do { if (kgdb_connected) CHK_DEBUGGER_TRAP(); } while (0)
+#else
+# define CHK_DEBUGGER_TRAP() do { } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
+#endif
+
+       trace_buffer_save(j);
+
+       /* trap_c() will be called for exceptions. During exceptions
+        * processing, the pc value should be set with retx value.
+        * With this change we can cleanup some code in signal.c- TODO
+        */
+       fp->orig_pc = fp->retx;
+       /* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
+               trapnr, fp->ipend, fp->pc, fp->retx); */
+
+       /* send the appropriate signal to the user program */
+       switch (trapnr) {
+
+       /* This table works in conjuction with the one in ./mach-common/entry.S
+        * Some exceptions are handled there (in assembly, in exception space)
+        * Some are handled here, (in C, in interrupt space)
+        * Some, like CPLB, are handled in both, where the normal path is
+        * handled in assembly/exception space, and the error path is handled
+        * here
+        */
+
+       /* 0x00 - Linux Syscall, getting here is an error */
+       /* 0x01 - userspace gdb breakpoint, handled here */
+       case VEC_EXCPT01:
+               info.si_code = TRAP_ILLTRAP;
+               sig = SIGTRAP;
+               CHK_DEBUGGER_TRAP_MAYBE();
+               /* Check if this is a breakpoint in kernel space */
+               if (fp->ipend & 0xffc0)
+                       return;
+               else
+                       break;
+#ifdef CONFIG_KGDB
+       case VEC_EXCPT02 :               /* gdb connection */
+               info.si_code = TRAP_ILLTRAP;
+               sig = SIGTRAP;
+               CHK_DEBUGGER_TRAP();
+               return;
+#else
+       /* 0x02 - User Defined, Caught by default */
+#endif
+       /* 0x03  - Atomic test and set */
+       case VEC_EXCPT03:
+               info.si_code = SEGV_STACKFLOW;
+               sig = SIGSEGV;
+               printk(KERN_EMERG EXC_0x03);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x04 - spinlock - handled by _ex_spinlock,
+               getting here is an error */
+       /* 0x05 - User Defined, Caught by default */
+       /* 0x06 - User Defined, Caught by default */
+       /* 0x07 - User Defined, Caught by default */
+       /* 0x08 - User Defined, Caught by default */
+       /* 0x09 - User Defined, Caught by default */
+       /* 0x0A - User Defined, Caught by default */
+       /* 0x0B - User Defined, Caught by default */
+       /* 0x0C - User Defined, Caught by default */
+       /* 0x0D - User Defined, Caught by default */
+       /* 0x0E - User Defined, Caught by default */
+       /* 0x0F - User Defined, Caught by default */
+       /* 0x10 HW Single step, handled here */
+       case VEC_STEP:
+               info.si_code = TRAP_STEP;
+               sig = SIGTRAP;
+               CHK_DEBUGGER_TRAP_MAYBE();
+               /* Check if this is a single step in kernel space */
+               if (fp->ipend & 0xffc0)
+                       return;
+               else
+                       break;
+       /* 0x11 - Trace Buffer Full, handled here */
+       case VEC_OVFLOW:
+               info.si_code = TRAP_TRACEFLOW;
+               sig = SIGTRAP;
+               printk(KERN_EMERG EXC_0x11);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x12 - Reserved, Caught by default */
+       /* 0x13 - Reserved, Caught by default */
+       /* 0x14 - Reserved, Caught by default */
+       /* 0x15 - Reserved, Caught by default */
+       /* 0x16 - Reserved, Caught by default */
+       /* 0x17 - Reserved, Caught by default */
+       /* 0x18 - Reserved, Caught by default */
+       /* 0x19 - Reserved, Caught by default */
+       /* 0x1A - Reserved, Caught by default */
+       /* 0x1B - Reserved, Caught by default */
+       /* 0x1C - Reserved, Caught by default */
+       /* 0x1D - Reserved, Caught by default */
+       /* 0x1E - Reserved, Caught by default */
+       /* 0x1F - Reserved, Caught by default */
+       /* 0x20 - Reserved, Caught by default */
+       /* 0x21 - Undefined Instruction, handled here */
+       case VEC_UNDEF_I:
+               info.si_code = ILL_ILLOPC;
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x21);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x22 - Illegal Instruction Combination, handled here */
+       case VEC_ILGAL_I:
+               info.si_code = ILL_ILLPARAOP;
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x22);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x23 - Data CPLB Protection Violation,
+                normal case is handled in _cplb_hdr */
+       case VEC_CPLB_VL:
+               info.si_code = ILL_CPLB_VI;
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x23);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x24 - Data access misaligned, handled here */
+       case VEC_MISALI_D:
+               info.si_code = BUS_ADRALN;
+               sig = SIGBUS;
+               printk(KERN_EMERG EXC_0x24);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x25 - Unrecoverable Event, handled here */
+       case VEC_UNCOV:
+               info.si_code = ILL_ILLEXCPT;
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x25);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
+               error case is handled here */
+       case VEC_CPLB_M:
+               info.si_code = BUS_ADRALN;
+               sig = SIGBUS;
+               printk(KERN_EMERG EXC_0x26);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
+       case VEC_CPLB_MHIT:
+               info.si_code = ILL_CPLB_MULHIT;
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
+               sig = SIGSEGV;
+               printk(KERN_EMERG "\n\nNULL pointer access (probably)\n");
+#else
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x27);
+#endif
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x28 - Emulation Watchpoint, handled here */
+       case VEC_WATCH:
+               info.si_code = TRAP_WATCHPT;
+               sig = SIGTRAP;
+               pr_debug(EXC_0x28);
+               CHK_DEBUGGER_TRAP_MAYBE();
+               /* Check if this is a watchpoint in kernel space */
+               if (fp->ipend & 0xffc0)
+                       return;
+               else
+                       break;
+#ifdef CONFIG_BF535
+       /* 0x29 - Instruction fetch access error (535 only) */
+       case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
+               info.si_code = BUS_OPFETCH;
+               sig = SIGBUS;
+               printk(KERN_EMERG "BF535: VEC_ISTRU_VL\n");
+               CHK_DEBUGGER_TRAP();
+               break;
+#else
+       /* 0x29 - Reserved, Caught by default */
+#endif
+       /* 0x2A - Instruction fetch misaligned, handled here */
+       case VEC_MISALI_I:
+               info.si_code = BUS_ADRALN;
+               sig = SIGBUS;
+               printk(KERN_EMERG EXC_0x2A);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x2B - Instruction CPLB protection Violation,
+               handled in _cplb_hdr */
+       case VEC_CPLB_I_VL:
+               info.si_code = ILL_CPLB_VI;
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x2B);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
+       case VEC_CPLB_I_M:
+               info.si_code = ILL_CPLB_MISS;
+               sig = SIGBUS;
+               printk(KERN_EMERG EXC_0x2C);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x2D - Instruction CPLB Multiple Hits, handled here */
+       case VEC_CPLB_I_MHIT:
+               info.si_code = ILL_CPLB_MULHIT;
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
+               sig = SIGSEGV;
+               printk(KERN_EMERG "\n\nJump to address 0 - 0x0fff\n");
+#else
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x2D);
+#endif
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x2E - Illegal use of Supervisor Resource, handled here */
+       case VEC_ILL_RES:
+               info.si_code = ILL_PRVOPC;
+               sig = SIGILL;
+               printk(KERN_EMERG EXC_0x2E);
+               CHK_DEBUGGER_TRAP();
+               break;
+       /* 0x2F - Reserved, Caught by default */
+       /* 0x30 - Reserved, Caught by default */
+       /* 0x31 - Reserved, Caught by default */
+       /* 0x32 - Reserved, Caught by default */
+       /* 0x33 - Reserved, Caught by default */
+       /* 0x34 - Reserved, Caught by default */
+       /* 0x35 - Reserved, Caught by default */
+       /* 0x36 - Reserved, Caught by default */
+       /* 0x37 - Reserved, Caught by default */
+       /* 0x38 - Reserved, Caught by default */
+       /* 0x39 - Reserved, Caught by default */
+       /* 0x3A - Reserved, Caught by default */
+       /* 0x3B - Reserved, Caught by default */
+       /* 0x3C - Reserved, Caught by default */
+       /* 0x3D - Reserved, Caught by default */
+       /* 0x3E - Reserved, Caught by default */
+       /* 0x3F - Reserved, Caught by default */
+       default:
+               info.si_code = TRAP_ILLTRAP;
+               sig = SIGTRAP;
+               printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
+                       (fp->seqstat & SEQSTAT_EXCAUSE));
+               CHK_DEBUGGER_TRAP();
+               break;
+       }
+
+       info.si_signo = sig;
+       info.si_errno = 0;
+       info.si_addr = (void *)fp->pc;
+       force_sig_info(sig, &info, current);
+       if (sig != 0 && sig != SIGTRAP) {
+               unsigned long stack;
+               dump_bfin_regs(fp, (void *)fp->retx);
+               dump_bfin_trace_buffer();
+               show_stack(current, &stack);
+               if (current->mm == NULL)
+                       panic("Kernel exception");
+       }
+
+       /* if the address that we are about to return to is not valid, set it
+        * to a valid address, if we have a current application or panic
+        */
+       if (!(fp->pc <= physical_mem_end
+#if L1_CODE_LENGTH != 0
+           || (fp->pc >= L1_CODE_START &&
+               fp->pc <= (L1_CODE_START + L1_CODE_LENGTH))
+#endif
+       )) {
+               if (current->mm) {
+                       fp->pc = current->mm->start_code;
+               } else {
+                       printk(KERN_EMERG "I can't return to memory that doesn't exist - bad things happen\n");
+                       panic("Help - I've fallen and can't get up\n");
+               }
+       }
+
+       trace_buffer_restore(j);
+       return;
+}
+
+/* Typical exception handling routines */
+
+void dump_bfin_trace_buffer(void)
+{
+       int tflags;
+       trace_buffer_save(tflags);
+
+       if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
+               int i;
+               printk(KERN_EMERG "Hardware Trace:\n");
+               for (i = 0; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
+                       printk(KERN_EMERG "%2i Target : ", i);
+                       printk_address((unsigned long)bfin_read_TBUF());
+                       printk("\n" KERN_EMERG "   Source : ");
+                       printk_address((unsigned long)bfin_read_TBUF());
+                       printk("\n");
+               }
+       }
+
+       trace_buffer_restore(tflags);
+}
+EXPORT_SYMBOL(dump_bfin_trace_buffer);
+
+static void show_trace(struct task_struct *tsk, unsigned long *sp)
+{
+       unsigned long addr;
+
+       printk("\nCall Trace:");
+#ifdef CONFIG_KALLSYMS
+       printk("\n");
+#endif
+
+       while (!kstack_end(sp)) {
+               addr = *sp++;
+               /*
+                * If the address is either in the text segment of the
+                * kernel, or in the region which contains vmalloc'ed
+                * memory, it *may* be the address of a calling
+                * routine; if so, print it so that someone tracing
+                * down the cause of the crash will be able to figure
+                * out the call path that was taken.
+                */
+               if (kernel_text_address(addr))
+                       print_ip_sym(addr);
+       }
+
+       printk("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+       unsigned long *endstack, addr;
+       int i;
+
+       /* Cannot call dump_bfin_trace_buffer() here as show_stack() is
+        * called externally in some places in the kernel.
+        */
+
+       if (!stack) {
+               if (task)
+                       stack = (unsigned long *)task->thread.ksp;
+               else
+                       stack = (unsigned long *)&stack;
+       }
+
+       addr = (unsigned long)stack;
+       endstack = (unsigned long *)PAGE_ALIGN(addr);
+
+       printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
+       for (i = 0; i < kstack_depth_to_print; i++) {
+               if (stack + 1 > endstack)
+                       break;
+               if (i % 8 == 0)
+                       printk("\n" KERN_EMERG "       ");
+               printk(" %08lx", *stack++);
+       }
+
+       show_trace(task, stack);
+}
+
+void dump_stack(void)
+{
+       unsigned long stack;
+       int tflags;
+       trace_buffer_save(tflags);
+       dump_bfin_trace_buffer();
+       show_stack(current, &stack);
+       trace_buffer_restore(tflags);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
+{
+       if (current->pid) {
+               printk("\nCURRENT PROCESS:\n\n");
+               printk("COMM=%s PID=%d\n", current->comm, current->pid);
+       } else {
+               printk
+                   ("\nNo Valid pid - Either things are really messed up, or you are in the kernel\n");
+       }
+
+       if (current->mm) {
+               printk("TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"
+                      "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n\n",
+                      (void*)current->mm->start_code,
+                      (void*)current->mm->end_code,
+                      (void*)current->mm->start_data,
+                      (void*)current->mm->end_data,
+                      (void*)current->mm->end_data,
+                      (void*)current->mm->brk,
+                      (void*)current->mm->start_stack);
+       }
+
+       printk("return address: 0x%p; contents of [PC-16...PC+8]:\n", retaddr);
+       if (retaddr != 0 && retaddr <= (void*)physical_mem_end
+#if L1_CODE_LENGTH != 0
+           /* FIXME: Copy the code out of L1 Instruction SRAM through dma
+              memcpy.  */
+           && !(retaddr >= (void*)L1_CODE_START
+                && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH))
+#endif
+       ) {
+               int i = 0;
+               unsigned short x = 0;
+               for (i = -16; i < 8; i++) {
+                       if (get_user(x, (unsigned short *)retaddr + i))
+                               break;
+#ifndef CONFIG_DEBUG_HWERR
+                       /* If one of the last few instructions was a STI
+                        * it is likily that the error occured awhile ago
+                        * and we just noticed
+                        */
+                       if (x >= 0x0040 && x <= 0x0047 && i <= 0)
+                               panic("\n\nWARNING : You should reconfigure the kernel to turn on\n"
+                                       " 'Hardware error interrupt debugging'\n"
+                                       " The rest of this error is meanless\n");
+#endif
+
+                       if (i == -8)
+                               printk("\n");
+                       if (i == 0)
+                               printk("X\n");
+                       printk("%04x ", x);
+               }
+       } else
+               printk("Cannot look at the [PC] for it is in unreadable L1 SRAM - sorry\n");
+
+       printk("\n\n");
+
+       printk("RETE:  %08lx  RETN: %08lx  RETX: %08lx  RETS: %08lx\n",
+              fp->rete, fp->retn, fp->retx, fp->rets);
+       printk("IPEND: %04lx  SYSCFG: %04lx\n", fp->ipend, fp->syscfg);
+       printk("SEQSTAT: %08lx    SP: %08lx\n", (long)fp->seqstat, (long)fp);
+       printk("R0: %08lx    R1: %08lx    R2: %08lx    R3: %08lx\n",
+              fp->r0, fp->r1, fp->r2, fp->r3);
+       printk("R4: %08lx    R5: %08lx    R6: %08lx    R7: %08lx\n",
+              fp->r4, fp->r5, fp->r6, fp->r7);
+       printk("P0: %08lx    P1: %08lx    P2: %08lx    P3: %08lx\n",
+              fp->p0, fp->p1, fp->p2, fp->p3);
+       printk("P4: %08lx    P5: %08lx    FP: %08lx\n", fp->p4, fp->p5, fp->fp);
+       printk("A0.w: %08lx    A0.x: %08lx    A1.w: %08lx    A1.x: %08lx\n",
+              fp->a0w, fp->a0x, fp->a1w, fp->a1x);
+
+       printk("LB0: %08lx  LT0: %08lx  LC0: %08lx\n", fp->lb0, fp->lt0,
+              fp->lc0);
+       printk("LB1: %08lx  LT1: %08lx  LC1: %08lx\n", fp->lb1, fp->lt1,
+              fp->lc1);
+       printk("B0: %08lx  L0: %08lx  M0: %08lx  I0: %08lx\n", fp->b0, fp->l0,
+              fp->m0, fp->i0);
+       printk("B1: %08lx  L1: %08lx  M1: %08lx  I1: %08lx\n", fp->b1, fp->l1,
+              fp->m1, fp->i1);
+       printk("B2: %08lx  L2: %08lx  M2: %08lx  I2: %08lx\n", fp->b2, fp->l2,
+              fp->m2, fp->i2);
+       printk("B3: %08lx  L3: %08lx  M3: %08lx  I3: %08lx\n", fp->b3, fp->l3,
+              fp->m3, fp->i3);
+
+       printk("\nUSP: %08lx   ASTAT: %08lx\n", rdusp(), fp->astat);
+       if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
+               printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
+               printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+       }
+
+       printk("\n\n");
+}
+
+#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
+asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
+#endif
+
+asmlinkage int sys_bfin_spinlock(int *spinlock)
+{
+       int ret = 0;
+       int tmp = 0;
+
+       local_irq_disable();
+       ret = get_user(tmp, spinlock);
+       if (ret == 0) {
+               if (tmp)
+                       ret = 1;
+               tmp = 1;
+               put_user(tmp, spinlock);
+       }
+       local_irq_enable();
+       return ret;
+}
+
+void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
+{
+       switch (cplb_panic) {
+       case CPLB_NO_UNLOCKED:
+               printk(KERN_EMERG "All CPLBs are locked\n");
+               break;
+       case CPLB_PROT_VIOL:
+               return;
+       case CPLB_NO_ADDR_MATCH:
+               return;
+       case CPLB_UNKNOWN_ERR:
+               printk(KERN_EMERG "Unknown CPLB Exception\n");
+               break;
+       }
+
+       printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
+       printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+       dump_bfin_regs(fp, (void *)fp->retx);
+       dump_stack();
+       panic("Unrecoverable event\n");
+}
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
new file mode 100644 (file)
index 0000000..6ae9ebb
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * File:         arch/blackfin/kernel/vmlinux.lds.S
+ * Based on:     none - original work
+ * Author:
+ *
+ * Created:      Tue Sep 21 2004
+ * Description:  Master linker script for blackfin architecture
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#define VMLINUX_SYMBOL(_sym_) _##_sym_
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/mem_map.h>
+
+
+OUTPUT_FORMAT("elf32-bfin")
+ENTRY(__start)
+_jiffies = _jiffies_64;
+
+MEMORY
+{
+       ram         : ORIGIN = CONFIG_BOOT_LOAD, LENGTH = (CONFIG_MEM_SIZE * 1024 * 1024) - (CONFIG_BOOT_LOAD)
+       l1_data_a   : ORIGIN = L1_DATA_A_START,  LENGTH = L1_DATA_A_LENGTH
+       l1_data_b   : ORIGIN = L1_DATA_B_START,  LENGTH = L1_DATA_B_LENGTH
+       l1_code     : ORIGIN = L1_CODE_START,    LENGTH = L1_CODE_LENGTH
+       l1_scratch  : ORIGIN = L1_SCRATCH_START, LENGTH = L1_SCRATCH_LENGTH
+}
+
+SECTIONS
+{
+       . = CONFIG_BOOT_LOAD;
+
+       .text :
+       {
+                _text = .;
+                __stext = .;
+               *(.text)
+               SCHED_TEXT
+               *(.text.lock)
+               . = ALIGN(16);
+                 ___start___ex_table = .;
+               *(__ex_table)
+                ___stop___ex_table = .;
+
+               *($code)
+               *(.rodata)
+               *(.rodata.*)
+               *(__vermagic)           /* Kernel version magic */
+               *(.rodata1)
+               *(.fixup)
+               *(.spinlock.text)
+
+               /* Kernel symbol table: Normal symbols */
+               . = ALIGN(4);
+               ___start___ksymtab = .;
+               *(__ksymtab)
+               ___stop___ksymtab = .;
+
+               /* Kernel symbol table: GPL-only symbols */
+               ___start___ksymtab_gpl = .;
+               *(__ksymtab_gpl)
+               ___stop___ksymtab_gpl = .;
+
+               /* Kernel symbol table: Normal unused symbols */                \
+               ___start___ksymtab_unused = .;
+               *(__ksymtab_unused)
+               ___stop___ksymtab_unused = .;
+
+               /* Kernel symbol table: GPL-only unused symbols */
+               ___start___ksymtab_unused_gpl = .;
+               *(__ksymtab_unused_gpl)
+               ___stop___ksymtab_unused_gpl = .;
+
+
+               /* Kernel symbol table: GPL-future symbols */
+               ___start___ksymtab_gpl_future = .;
+               *(__ksymtab_gpl_future)
+               ___stop___ksymtab_gpl_future = .;
+
+               /* Kernel symbol table: Normal symbols */
+               ___start___kcrctab = .;
+               *(__kcrctab)
+               ___stop___kcrctab = .;
+
+               /* Kernel symbol table: GPL-only symbols */
+               ___start___kcrctab_gpl = .;
+               *(__kcrctab_gpl)
+               ___stop___kcrctab_gpl = .;
+
+               /* Kernel symbol table: GPL-future symbols */
+               ___start___kcrctab_gpl_future = .;
+               *(__kcrctab_gpl_future)
+               ___stop___kcrctab_gpl_future = .;
+
+               /* Kernel symbol table: strings */
+               *(__ksymtab_strings)
+
+                . = ALIGN(4);
+               __etext = .;
+       } > ram
+
+       .init :
+       {
+               . = ALIGN(4096);
+               ___init_begin = .;
+               __sinittext = .;
+               *(.init.text)
+               __einittext = .;
+               *(.init.data)
+               . = ALIGN(16);
+               ___setup_start = .;
+               *(.init.setup)
+               ___setup_end = .;
+               ___start___param = .;
+               *(__param)
+               ___stop___param = .;
+               ___initcall_start = .;
+               INITCALLS
+               ___initcall_end = .;
+               ___con_initcall_start = .;
+               *(.con_initcall.init)
+               ___con_initcall_end = .;
+               ___security_initcall_start = .;
+               *(.security_initcall.init)
+               ___security_initcall_end = .;
+               . = ALIGN(4);
+               ___initramfs_start = .;
+               *(.init.ramfs)
+               ___initramfs_end = .;
+               . = ALIGN(4);
+               ___init_end = .;
+       } > ram
+
+        __l1_lma_start = .;
+
+       .text_l1 :
+       {
+               . = ALIGN(4);
+                __stext_l1 = .;
+               *(.l1.text)
+
+               . = ALIGN(4);
+                __etext_l1 = .;
+       } > l1_code AT > ram
+
+       .data_l1 :
+       {
+               . = ALIGN(4);
+                __sdata_l1 = .;
+               *(.l1.data)
+                __edata_l1 = .;
+
+               . = ALIGN(4);
+                __sbss_l1 = .;
+               *(.l1.bss)
+
+               . = ALIGN(32);
+               *(.data_l1.cacheline_aligned)
+
+               . = ALIGN(4);
+                __ebss_l1 = .;
+       } > l1_data_a AT > ram
+       .data_b_l1 :
+       {
+               . = ALIGN(4);
+               __sdata_b_l1 = .;
+               *(.l1.data.B)
+               __edata_b_l1 = .;
+
+               . = ALIGN(4);
+               __sbss_b_l1 = .;
+               *(.l1.bss.B)
+
+               . = ALIGN(4);
+               __ebss_b_l1 = .;
+       } > l1_data_b AT > ram
+
+       .data :
+       {
+                __sdata = .;
+               . = ALIGN(0x2000);
+               *(.data.init_task)
+               *(.data)
+
+               . = ALIGN(32);
+               *(.data.cacheline_aligned)
+
+               . = ALIGN(0x2000);
+               __edata = .;
+       } > ram
+
+       /DISCARD/ : {                   /* Exit code and data*/
+               *(.exit.text)
+               *(.exit.data)
+               *(.exitcall.exit)
+       } > ram
+
+       .bss :
+       {
+               . = ALIGN(4);
+                ___bss_start = .;
+               *(.bss)
+               *(COMMON)
+               . = ALIGN(4);
+                ___bss_stop = .;
+                __end = .      ;
+       } > ram
+}
diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile
new file mode 100644 (file)
index 0000000..635288f
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# arch/blackfin/lib/Makefile
+#
+
+lib-y := \
+       ashldi3.o ashrdi3.o lshrdi3.o \
+       muldi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
+       checksum.o memcpy.o memset.o memcmp.o memchr.o memmove.o \
+       strcmp.o strcpy.o strncmp.o strncpy.o \
+       umulsi3_highpart.o smulsi3_highpart.o \
+       ins.o outs.o
diff --git a/arch/blackfin/lib/ashldi3.c b/arch/blackfin/lib/ashldi3.c
new file mode 100644 (file)
index 0000000..a8c279e
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * File:         arch/blackfin/lib/ashldi3.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "gcclib.h"
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+DItype __ashldi3(DItype u, word_type b)__attribute__((l1_text));
+#endif
+
+DItype __ashldi3(DItype u, word_type b)
+{
+       DIunion w;
+       word_type bm;
+       DIunion uu;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+
+       bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (USItype) uu.s.low << -bm;
+       } else {
+               USItype carries = (USItype) uu.s.low >> bm;
+               w.s.low = (USItype) uu.s.low << b;
+               w.s.high = ((USItype) uu.s.high << b) | carries;
+       }
+
+       return w.ll;
+}
diff --git a/arch/blackfin/lib/ashrdi3.c b/arch/blackfin/lib/ashrdi3.c
new file mode 100644 (file)
index 0000000..a0d3419
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * File:         arch/blackfin/lib/ashrdi3.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "gcclib.h"
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+DItype __ashrdi3(DItype u, word_type b)__attribute__((l1_text));
+#endif
+
+DItype __ashrdi3(DItype u, word_type b)
+{
+       DIunion w;
+       word_type bm;
+       DIunion uu;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+
+       bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high = uu.s.high >> (sizeof(SItype) * BITS_PER_UNIT - 1);
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               USItype carries = (USItype) uu.s.high << bm;
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((USItype) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
diff --git a/arch/blackfin/lib/checksum.c b/arch/blackfin/lib/checksum.c
new file mode 100644 (file)
index 0000000..42768e0
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * File:         arch/blackfin/lib/checksum.c
+ * Based on:     none - original work
+ * Author:
+ *
+ * Created:
+ * Description:  An implementation of the TCP/IP protocol suite for the LINUX
+ *               operating system.  INET is implemented using the  BSD Socket
+ *               interface as the means of communication with the user level.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <net/checksum.h>
+#include <asm/checksum.h>
+
+#ifdef CONFIG_IP_CHECKSUM_L1
+static unsigned short do_csum(const unsigned char *buff, int len)__attribute__((l1_text));
+#endif
+
+static unsigned short do_csum(const unsigned char *buff, int len)
+{
+       register unsigned long sum = 0;
+       int swappem = 0;
+
+       if (1 & (unsigned long)buff) {
+               sum = *buff << 8;
+               buff++;
+               len--;
+               ++swappem;
+       }
+
+       while (len > 1) {
+               sum += *(unsigned short *)buff;
+               buff += 2;
+               len -= 2;
+       }
+
+       if (len > 0)
+               sum += *buff;
+
+       /*  Fold 32-bit sum to 16 bits */
+       while (sum >> 16)
+               sum = (sum & 0xffff) + (sum >> 16);
+
+       if (swappem)
+               sum = ((sum & 0xff00) >> 8) + ((sum & 0x00ff) << 8);
+
+       return sum;
+
+}
+
+/*
+ *     This is a version of ip_compute_csum() optimized for IP headers,
+ *     which always checksum on 4 octet boundaries.
+ */
+unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+{
+       return ~do_csum(iph, ihl * 4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+{
+       /*
+        * Just in case we get nasty checksum data...
+        * Like 0xffff6ec3 in the case of our IPv6 multicast header.
+        * We fold to begin with, as well as at the end.
+        */
+       sum = (sum & 0xffff) + (sum >> 16);
+
+       sum += do_csum(buff, len);
+
+       sum = (sum & 0xffff) + (sum >> 16);
+
+       return sum;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+unsigned short ip_compute_csum(const unsigned char *buff, int len)
+{
+       return ~do_csum(buff, len);
+}
+
+/*
+ * copy from fs while checksumming, otherwise like csum_partial
+ */
+
+unsigned int
+csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
+                           int len, int sum, int *csum_err)
+{
+       if (csum_err)
+               *csum_err = 0;
+       memcpy(dst, src, len);
+       return csum_partial(dst, len, sum);
+}
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
+                              int len, int sum)
+{
+       memcpy(dst, src, len);
+       return csum_partial(dst, len, sum);
+}
diff --git a/arch/blackfin/lib/divsi3.S b/arch/blackfin/lib/divsi3.S
new file mode 100644 (file)
index 0000000..3e29861
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * File:         arch/blackfin/lib/divsi3.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  16 / 32 bit signed division.
+ *                 Special cases :
+ *                      1)  If(numerator == 0)
+ *                             return 0
+ *                      2)  If(denominator ==0)
+ *                             return positive max = 0x7fffffff
+ *                      3)  If(numerator == denominator)
+ *                             return 1
+ *                      4)  If(denominator ==1)
+ *                             return numerator
+ *                      5)  If(denominator == -1)
+ *                             return -numerator
+ *
+ *                 Operand         : R0 - Numerator   (i)
+ *                                   R1 - Denominator (i)
+ *                                   R0 - Quotient    (o)
+ *                 Registers Used : R2-R7,P0-P2
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.global   ___divsi3;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2;
+___divsi3 :
+
+
+  R3 = R0 ^ R1;
+  R0 = ABS R0;
+
+  CC = V;
+
+  r3 = rot r3 by -1;
+  r1 = abs r1;      /* now both positive, r3.30 means "negate result",
+                    ** r3.31 means overflow, add one to result
+                    */
+  cc = r0 < r1;
+  if cc jump .Lret_zero;
+  r2 = r1 >> 15;
+  cc = r2;
+  if cc jump .Lidents;
+  r2 = r1 << 16;
+  cc = r2 <= r0;
+  if cc jump .Lidents;
+
+  DIVS(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+  DIVQ(R0, R1);
+
+  R0 = R0.L (Z);
+  r1 = r3 >> 31;    /* add overflow issue back in */
+  r0 = r0 + r1;
+  r1 = -r0;
+  cc = bittst(r3, 30);
+  if cc r0 = r1;
+  RTS;
+
+/* Can't use the primitives. Test common identities.
+** If the identity is true, return the value in R2.
+*/
+
+.Lidents:
+  CC = R1 == 0;                   /* check for divide by zero */
+  IF CC JUMP .Lident_return;
+
+  CC = R0 == 0;                   /* check for division of zero */
+  IF CC JUMP .Lzero_return;
+
+  CC = R0 == R1;                  /* check for identical operands */
+  IF CC JUMP .Lident_return;
+
+  CC = R1 == 1;                   /* check for divide by 1 */
+  IF CC JUMP .Lident_return;
+
+  R2.L = ONES R1;
+  R2 = R2.L (Z);
+  CC = R2 == 1;
+  IF CC JUMP .Lpower_of_two;
+
+  /* Identities haven't helped either.
+  ** Perform the full division process.
+  */
+
+  P1 = 31;                        /* Set loop counter   */
+
+  [--SP] = (R7:5);                /* Push registers R5-R7 */
+  R2 = -R1;
+  [--SP] = R2;
+  R2 = R0 << 1;                   /* R2 lsw of dividend  */
+  R6 = R0 ^ R1;                   /* Get sign */
+  R5 = R6 >> 31;                  /* Shift sign to LSB */
+
+  R0 = 0 ;                        /* Clear msw partial remainder */
+  R2 = R2 | R5;                   /* Shift quotient bit */
+  R6 = R0 ^ R1;                   /* Get new quotient bit */
+
+  LSETUP(.Llst,.Llend)  LC0 = P1;   /* Setup loop */
+.Llst:   R7 = R2 >> 31;            /* record copy of carry from R2 */
+        R2 = R2 << 1;             /* Shift 64 bit dividend up by 1 bit */
+        R0 = R0 << 1 || R5 = [SP];
+        R0 = R0 | R7;             /* and add carry */
+        CC = R6 < 0;              /* Check quotient(AQ) */
+                                  /* we might be subtracting divisor (AQ==0) */
+        IF CC R5 = R1;            /* or we might be adding divisor  (AQ==1)*/
+        R0 = R0 + R5;             /* do add or subtract, as indicated by AQ */
+        R6 = R0 ^ R1;             /* Generate next quotient bit */
+        R5 = R6 >> 31;
+                                  /* Assume AQ==1, shift in zero */
+        BITTGL(R5,0);             /* tweak AQ to be what we want to shift in */
+.Llend:  R2 = R2 + R5;             /* and then set shifted-in value to
+                                  ** tweaked AQ.
+                                  */
+  r1 = r3 >> 31;
+  r2 = r2 + r1;
+  cc = bittst(r3,30);
+  r0 = -r2;
+  if !cc r0 = r2;
+  SP += 4;
+  (R7:5)= [SP++];                 /* Pop registers R6-R7 */
+  RTS;
+
+.Lident_return:
+  CC = R1 == 0;                   /* check for divide by zero  => 0x7fffffff */
+  R2 = -1 (X);
+  R2 >>= 1;
+  IF CC JUMP .Ltrue_ident_return;
+
+  CC = R0 == R1;                  /* check for identical operands => 1 */
+  R2 = 1 (Z);
+  IF CC JUMP .Ltrue_ident_return;
+
+  R2 = R0;                        /* assume divide by 1 => numerator */
+  /*FALLTHRU*/
+
+.Ltrue_ident_return:
+  R0 = R2;                        /* Return an identity value */
+  R2 = -R2;
+  CC = bittst(R3,30);
+  IF CC R0 = R2;
+.Lzero_return:
+  RTS;                            /* ...including zero */
+
+.Lpower_of_two:
+  /* Y has a single bit set, which means it's a power of two.
+  ** That means we can perform the division just by shifting
+  ** X to the right the appropriate number of bits
+  */
+
+  /* signbits returns the number of sign bits, minus one.
+  ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
+  ** to shift right n-signbits spaces. It also means 0x80000000
+  ** is a special case, because that *also* gives a signbits of 0
+  */
+
+  R2 = R0 >> 31;
+  CC = R1 < 0;
+  IF CC JUMP .Ltrue_ident_return;
+
+  R1.l = SIGNBITS R1;
+  R1 = R1.L (Z);
+  R1 += -30;
+  R0 = LSHIFT R0 by R1.L;
+  r1 = r3 >> 31;
+  r0 = r0 + r1;
+  R2 = -R0;                       // negate result if necessary
+  CC = bittst(R3,30);
+  IF CC R0 = R2;
+  RTS;
+
+.Lret_zero:
+  R0 = 0;
+  RTS;
diff --git a/arch/blackfin/lib/gcclib.h b/arch/blackfin/lib/gcclib.h
new file mode 100644 (file)
index 0000000..9ccd39a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * File:         arch/blackfin/lib/gcclib.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#define BITS_PER_UNIT  8
+#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+
+typedef unsigned int UQItype __attribute__ ((mode(QI)));
+typedef int SItype __attribute__ ((mode(SI)));
+typedef unsigned int USItype __attribute__ ((mode(SI)));
+typedef int DItype __attribute__ ((mode(DI)));
+typedef int word_type __attribute__ ((mode(__word__)));
+typedef unsigned int UDItype __attribute__ ((mode(DI)));
+
+struct DIstruct {
+       SItype low, high;
+};
+
+typedef union {
+       struct DIstruct s;
+       DItype ll;
+} DIunion;
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
new file mode 100644 (file)
index 0000000..730d2b4
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * File:         arch/blackfin/lib/ins.S
+ * Based on:
+ * Author:       Bas Vermeulen <bas@buyways.nl>
+ *
+ * Created:      Tue Mar 22 15:27:24 CEST 2005
+ * Description:  Implementation of ins{bwl} for BlackFin processors using zero overhead loops.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+.align 2
+
+ENTRY(_insl)
+       P0 = R0;        /* P0 = port */
+       cli R3;
+       P1 = R1;        /* P1 = address */
+       P2 = R2;        /* P2 = count */
+       SSYNC;
+       LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
+.Llong_loop_s: R0 = [P0];
+.Llong_loop_e: [P1++] = R0;
+       sti R3;
+       RTS;
+
+ENTRY(_insw)
+       P0 = R0;        /* P0 = port */
+       cli R3;
+       P1 = R1;        /* P1 = address */
+       P2 = R2;        /* P2 = count */
+       SSYNC;
+       LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
+.Lword_loop_s: R0 = W[P0];
+.Lword_loop_e: W[P1++] = R0;
+       sti R3;
+       RTS;
+
+ENTRY(_insb)
+       P0 = R0;        /* P0 = port */
+       cli R3;
+       P1 = R1;        /* P1 = address */
+       P2 = R2;        /* P2 = count */
+       SSYNC;
+       LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
+.Lbyte_loop_s: R0 = B[P0];
+.Lbyte_loop_e: B[P1++] = R0;
+       sti R3;
+       RTS;
diff --git a/arch/blackfin/lib/lshrdi3.c b/arch/blackfin/lib/lshrdi3.c
new file mode 100644 (file)
index 0000000..84b9c55
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * File:         arch/blackfin/lib/lshrdi3.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#define BITS_PER_UNIT 8
+
+typedef int SItype __attribute__ ((mode(SI)));
+typedef unsigned int USItype __attribute__ ((mode(SI)));
+typedef int DItype __attribute__ ((mode(DI)));
+typedef int word_type __attribute__ ((mode(__word__)));
+
+struct DIstruct {
+       SItype high, low;
+};
+
+typedef union {
+       struct DIstruct s;
+       DItype ll;
+} DIunion;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+DItype __lshrdi3(DItype u, word_type b)__attribute__((l1_text));
+#endif
+
+DItype __lshrdi3(DItype u, word_type b)
+{
+       DIunion w;
+       word_type bm;
+       DIunion uu;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+
+       bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (USItype) uu.s.high >> -bm;
+       } else {
+               USItype carries = (USItype) uu.s.high << bm;
+               w.s.high = (USItype) uu.s.high >> b;
+               w.s.low = ((USItype) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
diff --git a/arch/blackfin/lib/memchr.S b/arch/blackfin/lib/memchr.S
new file mode 100644 (file)
index 0000000..4981222
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * File:         arch/blackfin/lib/memchr.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+/* void *memchr(const void *s, int c, size_t n);
+ * R0 = address (s)
+ * R1 = sought byte (c)
+ * R2 = count (n)
+ *
+ * Returns pointer to located character.
+ */
+
+.text
+
+.align 2
+
+ENTRY(_memchr)
+       P0 = R0;                /* P0 = address */
+       P2 = R2;                /* P2 = count */
+       R1 = R1.B(Z);
+       CC = R2 == 0;
+       IF CC JUMP .Lfailed;
+
+.Lbytes:
+       LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2;
+
+.Lbyte_loop_s:
+       R3 = B[P0++](Z);
+       CC = R3 == R1;
+       IF CC JUMP .Lfound;
+.Lbyte_loop_e:
+       NOP;
+
+.Lfailed:
+       R0=0;
+       RTS;
+
+.Lfound:
+       R0 = P0;
+       R0 += -1;
+       RTS;
+
+.size _memchr,.-_memchr
diff --git a/arch/blackfin/lib/memcmp.S b/arch/blackfin/lib/memcmp.S
new file mode 100644 (file)
index 0000000..5b95023
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * File:         arch/blackfin/lib/memcmp.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+/* int memcmp(const void *s1, const void *s2, size_t n);
+ * R0 = First Address (s1)
+ * R1 = Second Address (s2)
+ * R2 = count (n)
+ *
+ * Favours word aligned data.
+ */
+
+.text
+
+.align 2
+
+ENTRY(_memcmp)
+       I1 = P3;
+       P0 = R0;                        /* P0 = s1 address */
+       P3 = R1;                        /* P3 = s2 Address  */
+       P2 = R2 ;                       /* P2 = count */
+       CC = R2 <= 7(IU);
+       IF CC JUMP .Ltoo_small;
+       I0 = R1;                        /* s2 */
+       R1 = R1 | R0;           /* OR addresses together */
+       R1 <<= 30;              /* check bottom two bits */
+       CC =  AZ;                       /* AZ set if zero. */
+       IF !CC JUMP .Lbytes ;   /* Jump if addrs not aligned. */
+
+       P1 = P2 >> 2;           /* count = n/4 */
+       R3 =  3;
+       R2 = R2 & R3;           /* remainder */
+       P2 = R2;                        /* set remainder */
+
+       LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1;
+.Lquad_loop_s:
+       MNOP || R0 = [P0++] || R1 = [I0++];
+       CC = R0 == R1;
+       IF !CC JUMP .Lquad_different;
+.Lquad_loop_e:
+       NOP;
+
+       P3 = I0;                        /* s2 */
+.Ltoo_small:
+       CC = P2 == 0;           /* Check zero count*/
+       IF CC JUMP .Lfinished;  /* very unlikely*/
+
+.Lbytes:
+       LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2;
+.Lbyte_loop_s:
+       R1 = B[P3++](Z);        /* *s2 */
+       R0 = B[P0++](Z);        /* *s1 */
+       CC = R0 == R1;
+       IF !CC JUMP .Ldifferent;
+.Lbyte_loop_e:
+       NOP;
+
+.Ldifferent:
+       R0 = R0 - R1;
+       P3 = I1;
+       RTS;
+
+.Lquad_different:
+       /* We've read two quads which don't match.
+        * Can't just compare them, because we're
+        * a little-endian machine, so the MSBs of
+        * the regs occur at later addresses in the
+        * string.
+        * Arrange to re-read those two quads again,
+        * byte-by-byte.
+        */
+       P0 += -4;               /* back up to the start of the */
+       P3 = I0;                /* quads, and increase the*/
+       P2 += 4;                /* remainder count*/
+       P3 += -4;
+       JUMP .Lbytes;
+
+.Lfinished:
+       R0 = 0;
+       P3 = I1;
+       RTS;
+
+.size _memcmp,.-_memcmp
diff --git a/arch/blackfin/lib/memcpy.S b/arch/blackfin/lib/memcpy.S
new file mode 100644 (file)
index 0000000..c1e00ef
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * File:         arch/blackfin/lib/memcpy.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  internal version of memcpy(), issued by the compiler
+ *               to copy blocks of data around.
+ *               This is really memmove() - it has to be able to deal with
+ *               possible overlaps, because that ambiguity is when the compiler
+ *               gives up and calls a function. We have our own, internal version
+ *               so that we get something we trust, even if the user has redefined
+ *               the normal symbol.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+/* void *memcpy(void *dest, const void *src, size_t n);
+ * R0 = To Address (dest) (leave unchanged to form result)
+ * R1 = From Address (src)
+ * R2 = count
+ *
+ * Note: Favours word alignment
+ */
+
+#ifdef CONFIG_MEMCPY_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2
+
+ENTRY(_memcpy)
+       CC = R2 <=  0;  /* length not positive? */
+       IF CC JUMP .L_P1L2147483647;    /* Nothing to do */
+
+       P0 = R0 ;       /* dst*/
+       P1 = R1 ;       /* src*/
+       P2 = R2 ;       /* length */
+
+       /* check for overlapping data */
+       CC = R1 < R0;   /* src < dst */
+       IF !CC JUMP .Lno_overlap;
+       R3 = R1 + R2;
+       CC = R0 < R3;   /* and dst < src+len */
+       IF CC JUMP .Lhas_overlap;
+
+.Lno_overlap:
+       /* Check for aligned data.*/
+
+       R3 = R1 | R0;
+       R0 = 0x3;
+       R3 = R3 & R0;
+       CC = R3;        /* low bits set on either address? */
+       IF CC JUMP .Lnot_aligned;
+
+       /* Both addresses are word-aligned, so we can copy
+       at least part of the data using word copies.*/
+       P2 = P2 >> 2;
+       CC = P2 <= 2;
+       IF !CC JUMP .Lmore_than_seven;
+       /* less than eight bytes... */
+       P2 = R2;
+       LSETUP(.Lthree_start, .Lthree_end) LC0=P2;
+       R0 = R1;        /* setup src address for return */
+.Lthree_start:
+       R3 = B[P1++] (X);
+.Lthree_end:
+       B[P0++] = R3;
+
+       RTS;
+
+.Lmore_than_seven:
+       /* There's at least eight bytes to copy. */
+       P2 += -1;       /* because we unroll one iteration */
+       LSETUP(.Lword_loop, .Lword_loop) LC0=P2;
+       R0 = R1;
+       I1 = P1;
+       R3 = [I1++];
+.Lword_loop:
+       MNOP || [P0++] = R3 || R3 = [I1++];
+
+       [P0++] = R3;
+       /* Any remaining bytes to copy? */
+       R3 = 0x3;
+       R3 = R2 & R3;
+       CC = R3 == 0;
+       P1 = I1;        /* in case there's something left, */
+       IF !CC JUMP .Lbytes_left;
+       RTS;
+.Lbytes_left:  P2 = R3;
+.Lnot_aligned:
+       /* From here, we're copying byte-by-byte. */
+       LSETUP (.Lbyte_start, .Lbyte_end) LC0=P2;
+       R0 = R1;        /* Save src address for return */
+.Lbyte_start:
+       R1 = B[P1++] (X);
+.Lbyte_end:
+       B[P0++] = R1;
+
+.L_P1L2147483647:
+       RTS;
+
+.Lhas_overlap:
+       /* Need to reverse the copying, because the
+        * dst would clobber the src.
+        * Don't bother to work out alignment for
+        * the reverse case.
+        */
+       R0 = R1;        /* save src for later. */
+       P0 = P0 + P2;
+       P0 += -1;
+       P1 = P1 + P2;
+       P1 += -1;
+       LSETUP(.Lover_start, .Lover_end) LC0=P2;
+.Lover_start:
+       R1 = B[P1--] (X);
+.Lover_end:
+       B[P0--] = R1;
+
+       RTS;
diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S
new file mode 100644 (file)
index 0000000..2e5fb7f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * File:         arch/blackfin/lib/memmove.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+.align 2
+
+/*
+ * C Library function MEMMOVE
+ * R0 = To Address (leave unchanged to form result)
+ * R1 = From Address
+ * R2 = count
+ * Data may overlap
+ */
+
+ENTRY(_memmove)
+       I1 = P3;
+       P0 = R0;                  /* P0 = To address */
+       P3 = R1;                  /* P3 = From Address */
+       P2 = R2;                  /* P2 = count */
+       CC = P2 == 0;             /* Check zero count*/
+       IF CC JUMP .Lfinished;    /* very unlikely */
+
+       CC = R1 < R0 (IU);        /* From < To */
+       IF !CC JUMP .Lno_overlap;
+       R3 = R1 + R2;
+       CC = R0 <= R3 (IU);       /* (From+len) >= To */
+       IF CC JUMP .Loverlap;
+.Lno_overlap:
+       R3 = 11;
+       CC = R2 <= R3;
+       IF CC JUMP .Lbytes;
+       R3 = R1 | R0;             /* OR addresses together */
+       R3 <<= 30;                /* check bottom two bits */
+       CC =  AZ;                 /* AZ set if zero.*/
+       IF !CC JUMP .Lbytes;      /* Jump if addrs not aligned.*/
+
+       I0 = P3;
+       P1 = P2 >> 2;             /* count = n/4 */
+       P1 += -1;
+       R3 =  3;
+       R2 = R2 & R3;             /* remainder */
+       P2 = R2;                  /* set remainder */
+       R1 = [I0++];
+
+       LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1;
+.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++];
+       [P0++] = R1;
+
+       CC = P2 == 0;             /* any remaining bytes? */
+       P3 = I0;                  /* Ammend P3 to updated ptr. */
+       IF !CC JUMP .Lbytes;
+       P3 = I1;
+       RTS;
+
+.Lbytes:     LSETUP (.Lbyte2_s, .Lbyte2_e) LC0=P2;
+.Lbyte2_s:   R1 = B[P3++](Z);
+.Lbyte2_e:   B[P0++] = R1;
+
+.Lfinished:  P3 = I1;
+       RTS;
+
+.Loverlap:
+       P2 += -1;
+       P0 = P0 + P2;
+       P3 = P3 + P2;
+       R1 = B[P3--] (Z);
+       CC = P2 == 0;
+       IF CC JUMP .Lno_loop;
+       LSETUP (.Lol_s, .Lol_e) LC0 = P2;
+.Lol_s:    B[P0--] = R1;
+.Lol_e:    R1 = B[P3--] (Z);
+.Lno_loop: B[P0] = R1;
+       P3 = I1;
+       RTS;
+
+.size _memmove,.-_memmove
diff --git a/arch/blackfin/lib/memset.S b/arch/blackfin/lib/memset.S
new file mode 100644 (file)
index 0000000..ba6d047
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * File:         arch/blackfin/lib/memset.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+.align 2
+
+#ifdef CONFIG_MEMSET_L1
+.section .l1.text
+#else
+.text
+#endif
+
+/*
+ * C Library function MEMSET
+ * R0 = address (leave unchanged to form result)
+ * R1 = filler byte
+ * R2 = count
+ * Favours word aligned data.
+ */
+
+ENTRY(_memset)
+       P0 = R0 ;              /* P0 = address */
+       P2 = R2 ;              /* P2 = count   */
+       R3 = R0 + R2;          /* end          */
+       CC = R2 <= 7(IU);
+       IF CC JUMP  .Ltoo_small;
+       R1 = R1.B (Z);         /* R1 = fill char */
+       R2 =  3;
+       R2 = R0 & R2;          /* addr bottom two bits */
+       CC =  R2 == 0;             /* AZ set if zero.   */
+       IF !CC JUMP  .Lforce_align ;  /* Jump if addr not aligned. */
+
+.Laligned:
+       P1 = P2 >> 2;          /* count = n/4        */
+       R2 = R1 <<  8;         /* create quad filler */
+       R2.L = R2.L + R1.L(NS);
+       R2.H = R2.L + R1.H(NS);
+       P2 = R3;
+
+       LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
+.Lquad_loop:
+       [P0++] = R2;
+
+       CC = P0 == P2;
+       IF !CC JUMP .Lbytes_left;
+       RTS;
+
+.Lbytes_left:
+       R2 = R3;                /* end point */
+       R3 = P0;                /* current position */
+       R2 = R2 - R3;           /* bytes left */
+       P2 = R2;
+
+.Ltoo_small:
+       CC = P2 == 0;           /* Check zero count */
+       IF CC JUMP .Lfinished;    /* Unusual */
+
+.Lbytes:
+       LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2;
+.Lbyte_loop:
+       B[P0++] = R1;
+
+.Lfinished:
+       RTS;
+
+.Lforce_align:
+       CC = BITTST (R0, 0);  /* odd byte */
+       R0 = 4;
+       R0 = R0 - R2;
+       P1 = R0;
+       R0 = P0;                    /* Recover return address */
+       IF !CC JUMP .Lskip1;
+       B[P0++] = R1;
+.Lskip1:
+       CC = R2 <= 2;          /* 2 bytes */
+       P2 -= P1;              /* reduce count */
+       IF !CC JUMP .Laligned;
+       B[P0++] = R1;
+       B[P0++] = R1;
+       JUMP .Laligned;
+
+.size _memset,.-_memset
diff --git a/arch/blackfin/lib/modsi3.S b/arch/blackfin/lib/modsi3.S
new file mode 100644 (file)
index 0000000..528b8b1
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * File:         arch/blackfin/lib/modsi3.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This program computes 32 bit signed remainder. It calls div32 function
+ *               for quotient estimation.
+ *
+ *               Registers used :
+ *               Numerator/ Denominator in  R0, R1
+ *                 R0  -  returns remainder.
+ *                 R2-R7
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.global ___modsi3;
+.type ___modsi3, STT_FUNC;
+.extern ___divsi3;
+.type ___divsi3, STT_FUNC;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+___modsi3:
+
+       CC=R0==0;
+       IF CC JUMP .LRETURN_R0;         /* Return 0, if numerator  == 0 */
+       CC=R1==0;
+       IF CC JUMP .LRETURN_ZERO;               /* Return 0, if denominator == 0 */
+       CC=R0==R1;
+       IF CC JUMP .LRETURN_ZERO;               /* Return 0, if numerator == denominator */
+       CC = R1 == 1;
+       IF CC JUMP .LRETURN_ZERO;               /* Return 0, if denominator ==  1 */
+       CC = R1 == -1;
+       IF CC JUMP .LRETURN_ZERO;               /* Return 0, if denominator == -1 */
+
+       /* Valid input. Use __divsi3() to compute the quotient, and then
+        * derive the remainder from that. */
+
+       [--SP] = (R7:6);                /* Push  R7 and R6 */
+       [--SP] = RETS;                  /* and return address */
+       R7 = R0;                        /* Copy of R0 */
+       R6 = R1;                        /* Save for later */
+       SP += -12;                      /* Should always provide this space */
+       CALL ___divsi3;                 /* Compute signed quotient using ___divsi3()*/
+       SP += 12;
+       R0 *= R6;                       /* Quotient * divisor */
+       R0 = R7 - R0;                   /* Dividend - (quotient * divisor) */
+       RETS = [SP++];                  /* Get back return address */
+       (R7:6) = [SP++];                /* Pop registers R7 and R4 */
+       RTS;                            /* Store remainder    */
+
+.LRETURN_ZERO:
+       R0 = 0;
+.LRETURN_R0:
+       RTS;
diff --git a/arch/blackfin/lib/muldi3.c b/arch/blackfin/lib/muldi3.c
new file mode 100644 (file)
index 0000000..303d0c6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * File:         arch/blackfin/lib/muldi3.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef SI_TYPE_SIZE
+#define SI_TYPE_SIZE 32
+#endif
+#define __ll_b (1L << (SI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((usitype) (t) % __ll_b)
+#define __ll_highpart(t) ((usitype) (t) / __ll_b)
+#define BITS_PER_UNIT 8
+
+#if !defined(umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)                                                \
+  do {                                                                 \
+    usitype __x0, __x1, __x2, __x3;                                    \
+    usitype __ul, __vl, __uh, __vh;                                    \
+                                                                       \
+    __ul = __ll_lowpart (u);                                           \
+    __uh = __ll_highpart (u);                                          \
+    __vl = __ll_lowpart (v);                                           \
+    __vh = __ll_highpart (v);                                          \
+                                                                       \
+    __x0 = (usitype) __ul * __vl;                                      \
+    __x1 = (usitype) __ul * __vh;                                      \
+    __x2 = (usitype) __uh * __vl;                                      \
+    __x3 = (usitype) __uh * __vh;                                      \
+                                                                       \
+    __x1 += __ll_highpart (__x0);/* this can't give carry */           \
+    __x1 += __x2;              /* but this indeed can */               \
+    if (__x1 < __x2)           /* did we get it? */                    \
+      __x3 += __ll_b;          /* yes, add it in the proper pos. */    \
+                                                                       \
+    (w1) = __x3 + __ll_highpart (__x1);                                        \
+    (w0) = __ll_lowpart (__x1) * __ll_b + __ll_lowpart (__x0);         \
+  } while (0)
+#endif
+
+#if !defined(__umulsidi3)
+#define __umulsidi3(u, v)                                              \
+  ({diunion __w;                                                        \
+       umul_ppmm (__w.s.high, __w.s.low, u, v);                         \
+           __w.ll; })
+#endif
+
+typedef unsigned int usitype __attribute__ ((mode(SI)));
+typedef int sitype __attribute__ ((mode(SI)));
+typedef int ditype __attribute__ ((mode(DI)));
+typedef int word_type __attribute__ ((mode(__word__)));
+
+struct distruct {
+       sitype low, high;
+};
+typedef union {
+       struct distruct s;
+       ditype ll;
+} diunion;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+ditype __muldi3(ditype u, ditype v)__attribute__((l1_text));
+#endif
+
+ditype __muldi3(ditype u, ditype v)
+{
+       diunion w;
+       diunion uu, vv;
+
+       uu.ll = u, vv.ll = v;
+       w.ll = __umulsidi3(uu.s.low, vv.s.low);
+       w.s.high += ((usitype) uu.s.low * (usitype) vv.s.high
+                    + (usitype) uu.s.high * (usitype) vv.s.low);
+
+       return w.ll;
+}
diff --git a/arch/blackfin/lib/outs.S b/arch/blackfin/lib/outs.S
new file mode 100644 (file)
index 0000000..f8c876f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * File:         arch/blackfin/lib/outs.S
+ * Based on:
+ * Author:       Bas Vermeulen <bas@buyways.nl>
+ *
+ * Created:      Tue Mar 22 15:27:24 CEST 2005
+ * Description:  Implementation of outs{bwl} for BlackFin processors using zero overhead loops.
+ *
+ * Modified:     Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+.align 2
+
+ENTRY(_outsl)
+       P0 = R0;        /* P0 = port */
+       P1 = R1;        /* P1 = address */
+       P2 = R2;        /* P2 = count */
+
+       LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
+.Llong_loop_s: R0 = [P1++];
+.Llong_loop_e: [P0] = R0;
+       RTS;
+
+ENTRY(_outsw)
+       P0 = R0;        /* P0 = port */
+       P1 = R1;        /* P1 = address */
+       P2 = R2;        /* P2 = count */
+
+       LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
+.Lword_loop_s: R0 = W[P1++];
+.Lword_loop_e: W[P0] = R0;
+       RTS;
+
+ENTRY(_outsb)
+       P0 = R0;        /* P0 = port */
+       P1 = R1;        /* P1 = address */
+       P2 = R2;        /* P2 = count */
+
+       LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
+.Lbyte_loop_s: R0 = B[P1++];
+.Lbyte_loop_e: B[P0] = R0;
+       RTS;
diff --git a/arch/blackfin/lib/smulsi3_highpart.S b/arch/blackfin/lib/smulsi3_highpart.S
new file mode 100644 (file)
index 0000000..10b8f8d
--- /dev/null
@@ -0,0 +1,30 @@
+.align 2
+.global ___smulsi3_highpart;
+.type ___smulsi3_highpart, STT_FUNC;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+___smulsi3_highpart:
+       R2 = R1.L * R0.L (FU);
+       R3 = R1.H * R0.L (IS,M);
+       R0 = R0.H * R1.H, R1 = R0.H * R1.L (IS,M);
+
+       R1.L = R2.H + R1.L;
+       cc = ac0;
+       R2 = cc;
+
+       R1.L = R1.L + R3.L;
+       cc = ac0;
+       R1 >>>= 16;
+       R3 >>>= 16;
+       R1 = R1 + R3;
+       R1 = R1 + R2;
+       R2 = cc;
+       R1 = R1 + R2;
+
+       R0 = R0 + R1;
+       RTS;
diff --git a/arch/blackfin/lib/strcmp.c b/arch/blackfin/lib/strcmp.c
new file mode 100644 (file)
index 0000000..2ad47c4
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/types.h>
+
+#define strcmp __inline_strcmp
+#include <asm/string.h>
+#undef strcmp
+
+int strcmp(const char *dest, const char *src)
+{
+               return __inline_strcmp(dest, src);
+}
+
diff --git a/arch/blackfin/lib/strcpy.c b/arch/blackfin/lib/strcpy.c
new file mode 100644 (file)
index 0000000..4dc835a
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/types.h>
+
+#define strcpy __inline_strcpy
+#include <asm/string.h>
+#undef strcpy
+
+char *strcpy(char *dest, const char *src)
+{
+               return __inline_strcpy(dest, src);
+}
+
diff --git a/arch/blackfin/lib/strncmp.c b/arch/blackfin/lib/strncmp.c
new file mode 100644 (file)
index 0000000..947bcfe
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/types.h>
+
+#define strncmp __inline_strncmp
+#include <asm/string.h>
+#undef strncmp
+
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+               return __inline_strncmp(cs, ct, count);
+}
+
diff --git a/arch/blackfin/lib/strncpy.c b/arch/blackfin/lib/strncpy.c
new file mode 100644 (file)
index 0000000..77a9b2e
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/types.h>
+
+#define strncpy __inline_strncpy
+#include <asm/string.h>
+#undef strncpy
+
+char *strncpy(char *dest, const char *src, size_t n)
+{
+               return __inline_strncpy(dest, src, n);
+}
+
diff --git a/arch/blackfin/lib/udivsi3.S b/arch/blackfin/lib/udivsi3.S
new file mode 100644 (file)
index 0000000..d39a129
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * File:         arch/blackfin/lib/udivsi3.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+
+#define CARRY AC0
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+
+ENTRY(___udivsi3)
+
+  CC = R0 < R1 (IU);    /* If X < Y, always return 0 */
+  IF CC JUMP .Lreturn_ident;
+
+  R2 = R1 << 16;
+  CC = R2 <= R0 (IU);
+  IF CC JUMP .Lidents;
+
+  R2 = R0 >> 31;       /* if X is a 31-bit number */
+  R3 = R1 >> 15;       /* and Y is a 15-bit number */
+  R2 = R2 | R3;        /* then it's okay to use the DIVQ builtins (fallthrough to fast)*/
+  CC = R2;
+  IF CC JUMP .Ly_16bit;
+
+/* METHOD 1: FAST DIVQ
+   We know we have a 31-bit dividend, and 15-bit divisor so we can use the
+   simple divq approach (first setting AQ to 0 - implying unsigned division,
+   then 16 DIVQ's).
+*/
+
+  AQ = CC;             /* Clear AQ (CC==0) */
+
+/* ISR States: When dividing two integers (32.0/16.0) using divide primitives,
+   we need to shift the dividend one bit to the left.
+   We have already checked that we have a 31-bit number so we are safe to do
+   that.
+*/
+  R0 <<= 1;
+  DIVQ(R0, R1); // 1
+  DIVQ(R0, R1); // 2
+  DIVQ(R0, R1); // 3
+  DIVQ(R0, R1); // 4
+  DIVQ(R0, R1); // 5
+  DIVQ(R0, R1); // 6
+  DIVQ(R0, R1); // 7
+  DIVQ(R0, R1); // 8
+  DIVQ(R0, R1); // 9
+  DIVQ(R0, R1); // 10
+  DIVQ(R0, R1); // 11
+  DIVQ(R0, R1); // 12
+  DIVQ(R0, R1); // 13
+  DIVQ(R0, R1); // 14
+  DIVQ(R0, R1); // 15
+  DIVQ(R0, R1); // 16
+  R0 = R0.L (Z);
+  RTS;
+
+.Ly_16bit:
+  /* We know that the upper 17 bits of Y might have bits set,
+  ** or that the sign bit of X might have a bit. If Y is a
+  ** 16-bit number, but not bigger, then we can use the builtins
+  ** with a post-divide correction.
+  ** R3 currently holds Y>>15, which means R3's LSB is the
+  ** bit we're interested in.
+  */
+
+  /* According to the ISR, to use the Divide primitives for
+  ** unsigned integer divide, the useable range is 31 bits
+  */
+  CC = ! BITTST(R0, 31);
+
+  /* IF condition is true we can scale our inputs and use the divide primitives,
+  ** with some post-adjustment
+  */
+  R3 += -1;            /* if so, Y is 0x00008nnn */
+  CC &= AZ;
+
+  /* If condition is true we can scale our inputs and use the divide primitives,
+  ** with some post-adjustment
+  */
+  R3 = R1 >> 1;                /* Pre-scaled divisor for primitive case */
+  R2 = R0 >> 16;
+
+  R2 = R3 - R2;                /* shifted divisor < upper 16 bits of dividend */
+  CC &= CARRY;
+  IF CC JUMP .Lshift_and_correct;
+
+  /* Fall through to the identities */
+
+/* METHOD 2: identities and manual calculation
+   We are not able to use the divide primites, but may still catch some special
+   cases.
+*/
+.Lidents:
+  /* Test for common identities. Value to be returned is placed in R2. */
+  CC = R0 == 0;        /* 0/Y => 0 */
+  IF CC JUMP .Lreturn_r0;
+  CC = R0 == R1;       /* X==Y => 1 */
+  IF CC JUMP .Lreturn_ident;
+  CC = R1 == 1;        /* X/1 => X */
+  IF CC JUMP .Lreturn_ident;
+
+  R2.L = ONES R1;
+  R2 = R2.L (Z);
+  CC = R2 == 1;
+  IF CC JUMP .Lpower_of_two;
+
+  [--SP] = (R7:5);                /* Push registers R5-R7 */
+
+  /* Idents don't match. Go for the full operation. */
+
+
+  R6 = 2;                         /* assume we'll shift two */
+  R3 = 1;
+
+  P2 = R1;
+                                  /* If either R0 or R1 have sign set, */
+                                  /* divide them by two, and note it's */
+                                  /* been done. */
+  CC = R1 < 0;
+  R2 = R1 >> 1;
+  IF CC R1 = R2;                  /* Possibly-shifted R1 */
+  IF !CC R6 = R3;                 /* R1 doesn't, so at most 1 shifted */
+
+  P0 = 0;
+  R3 = -R1;
+  [--SP] = R3;
+  R2 = R0 >> 1;
+  R2 = R0 >> 1;
+  CC = R0 < 0;
+  IF CC P0 = R6;                  /* Number of values divided */
+  IF !CC R2 = R0;                 /* Shifted R0 */
+
+                                  /* P0 is 0, 1 (NR/=2) or 2 (NR/=2, DR/=2) */
+
+                                  /* r2 holds Copy dividend  */
+  R3 = 0;                         /* Clear partial remainder */
+  R7 = 0;                         /* Initialise quotient bit */
+
+  P1 = 32;                        /* Set loop counter */
+  LSETUP(.Lulst, .Lulend) LC0 = P1; /* Set loop counter */
+.Lulst:  R6 = R2 >> 31;             /* R6 = sign bit of R2, for carry */
+       R2 = R2 << 1;              /* Shift 64 bit dividend up by 1 bit */
+       R3 = R3 << 1 || R5 = [SP];
+       R3 = R3 | R6;              /* Include any carry */
+       CC = R7 < 0;               /* Check quotient(AQ) */
+                                  /* If AQ==0, we'll sub divisor */
+       IF CC R5 = R1;             /* and if AQ==1, we'll add it. */
+       R3 = R3 + R5;              /* Add/sub divsor to partial remainder */
+       R7 = R3 ^ R1;              /* Generate next quotient bit */
+
+       R5 = R7 >> 31;             /* Get AQ */
+       BITTGL(R5, 0);             /* Invert it, to get what we'll shift */
+.Lulend: R2 = R2 + R5;              /* and "shift" it in. */
+
+  CC = P0 == 0;                   /* Check how many inputs we shifted */
+  IF CC JUMP .Lno_mult;            /* if none... */
+  R6 = R2 << 1;
+  CC = P0 == 1;
+  IF CC R2 = R6;                  /* if 1, Q = Q*2 */
+  IF !CC R1 = P2;                 /* if 2, restore stored divisor */
+
+  R3 = R2;                        /* Copy of R2 */
+  R3 *= R1;                       /* Q * divisor */
+  R5 = R0 - R3;                   /* Z = (dividend - Q * divisor) */
+  CC = R1 <= R5 (IU);             /* Check if divisor <= Z? */
+  R6 = CC;                        /* if yes, R6 = 1 */
+  R2 = R2 + R6;                   /* if yes, add one to quotient(Q) */
+.Lno_mult:
+  SP += 4;
+  (R7:5) = [SP++];                /* Pop registers R5-R7 */
+  R0 = R2;                        /* Store quotient */
+  RTS;
+
+.Lreturn_ident:
+  CC = R0 < R1 (IU);    /* If X < Y, always return 0 */
+  R2 = 0;
+  IF CC JUMP .Ltrue_return_ident;
+  R2 = -1 (X);         /* X/0 => 0xFFFFFFFF */
+  CC = R1 == 0;
+  IF CC JUMP .Ltrue_return_ident;
+  R2 = -R2;            /* R2 now 1 */
+  CC = R0 == R1;       /* X==Y => 1 */
+  IF CC JUMP .Ltrue_return_ident;
+  R2 = R0;             /* X/1 => X */
+  /*FALLTHRU*/
+
+.Ltrue_return_ident:
+  R0 = R2;
+.Lreturn_r0:
+  RTS;
+
+.Lpower_of_two:
+  /* Y has a single bit set, which means it's a power of two.
+  ** That means we can perform the division just by shifting
+  ** X to the right the appropriate number of bits
+  */
+
+  /* signbits returns the number of sign bits, minus one.
+  ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
+  ** to shift right n-signbits spaces. It also means 0x80000000
+  ** is a special case, because that *also* gives a signbits of 0
+  */
+
+  R2 = R0 >> 31;
+  CC = R1 < 0;
+  IF CC JUMP .Ltrue_return_ident;
+
+  R1.l = SIGNBITS R1;
+  R1 = R1.L (Z);
+  R1 += -30;
+  R0 = LSHIFT R0 by R1.L;
+  RTS;
+
+/* METHOD 3: PRESCALE AND USE THE DIVIDE PRIMITIVES WITH SOME POST-CORRECTION
+  Two scaling operations are required to use the divide primitives with a
+  divisor > 0x7FFFF.
+  Firstly (as in method 1) we need to shift the dividend 1 to the left for
+  integer division.
+  Secondly we need to shift both the divisor and dividend 1 to the right so
+  both are in range for the primitives.
+  The left/right shift of the dividend does nothing so we can skip it.
+*/
+.Lshift_and_correct:
+  R2 = R0;
+  // R3 is already R1 >> 1
+  CC=!CC;
+  AQ = CC;                        /* Clear AQ, got here with CC = 0 */
+  DIVQ(R2, R3); // 1
+  DIVQ(R2, R3); // 2
+  DIVQ(R2, R3); // 3
+  DIVQ(R2, R3); // 4
+  DIVQ(R2, R3); // 5
+  DIVQ(R2, R3); // 6
+  DIVQ(R2, R3); // 7
+  DIVQ(R2, R3); // 8
+  DIVQ(R2, R3); // 9
+  DIVQ(R2, R3); // 10
+  DIVQ(R2, R3); // 11
+  DIVQ(R2, R3); // 12
+  DIVQ(R2, R3); // 13
+  DIVQ(R2, R3); // 14
+  DIVQ(R2, R3); // 15
+  DIVQ(R2, R3); // 16
+
+  /* According to the Instruction Set Reference:
+     To divide by a divisor > 0x7FFF,
+     1. prescale and perform divide to obtain quotient (Q) (done above),
+     2. multiply quotient by unscaled divisor (result M)
+     3. subtract the product from the divident to get an error (E = X - M)
+     4. if E < divisor (Y) subtract 1, if E > divisor (Y) add 1, else return quotient (Q)
+   */
+  R3 = R2.L (Z);               /* Q = X' / Y' */
+  R2 = R3;             /* Preserve Q */
+  R2 *= R1;            /* M = Q * Y */
+  R2 = R0 - R2;                /* E = X - M */
+  R0 = R3;             /* Copy Q into result reg */
+
+/* Correction: If result of the multiply is negative, we overflowed
+   and need to correct the result by subtracting 1 from the result.*/
+  R3 = 0xFFFF (Z);
+  R2 = R2 >> 16;               /* E >> 16 */
+  CC = R2 == R3;
+  R3 = 1 ;
+  R1 = R0 - R3;
+  IF CC R0 = R1;
+  RTS;
diff --git a/arch/blackfin/lib/umodsi3.S b/arch/blackfin/lib/umodsi3.S
new file mode 100644 (file)
index 0000000..b55ce96
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * File:         arch/blackfin/lib/umodsi3.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  libgcc1 routines for Blackfin 5xx
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.extern ___udivsi3;
+.globl ___umodsi3
+___umodsi3:
+
+       CC=R0==0;
+       IF CC JUMP .LRETURN_R0;         /* Return 0, if NR == 0 */
+       CC= R1==0;
+       IF CC JUMP .LRETURN_ZERO_VAL;   /* Return 0, if DR == 0 */
+       CC=R0==R1;
+       IF CC JUMP .LRETURN_ZERO_VAL;   /* Return 0, if NR == DR */
+       CC = R1 == 1;
+       IF CC JUMP .LRETURN_ZERO_VAL;   /* Return 0, if  DR == 1 */
+       CC = R0<R1 (IU);
+       IF CC JUMP .LRETURN_R0;         /* Return dividend (R0),IF NR<DR */
+
+       [--SP] = (R7:6);                /* Push registers and */
+       [--SP] = RETS;                  /* Return address */
+       R7 = R0;                        /* Copy of R0 */
+       R6 = R1;
+       SP += -12;                      /* Should always provide this space */
+       CALL ___udivsi3;                /* Compute unsigned quotient using ___udiv32()*/
+       SP += 12;
+       R0 *= R6;                       /* Quotient * divisor */
+       R0 = R7 - R0;                   /* Dividend - (quotient * divisor) */
+       RETS = [SP++];                  /* Pop return address */
+       ( R7:6) = [SP++];               /* And registers */
+       RTS;                            /* Return remainder */
+.LRETURN_ZERO_VAL:
+       R0 = 0;
+.LRETURN_R0:
+       RTS;
diff --git a/arch/blackfin/lib/umulsi3_highpart.S b/arch/blackfin/lib/umulsi3_highpart.S
new file mode 100644 (file)
index 0000000..aac8218
--- /dev/null
@@ -0,0 +1,23 @@
+.align 2
+.global ___umulsi3_highpart;
+.type ___umulsi3_highpart, STT_FUNC;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+___umulsi3_highpart:
+       R2 = R1.H * R0.H, R3 = R1.L * R0.H (FU);
+       R0 = R1.L * R0.L, R1 = R1.H * R0.L (FU);
+       R0 >>= 16;
+       /* Unsigned multiplication has the nice property that we can
+          ignore carry on this first addition.  */
+       R0 = R0 + R3;
+       R0 = R0 + R1;
+       cc = ac0;
+       R1 = cc;
+       R1 = PACK(R1.l,R0.h);
+       R0 = R1 + R2;
+       RTS;
diff --git a/arch/blackfin/mach-bf533/Kconfig b/arch/blackfin/mach-bf533/Kconfig
new file mode 100644 (file)
index 0000000..14297b3
--- /dev/null
@@ -0,0 +1,92 @@
+if (BF533 || BF532 || BF531)
+
+menu "BF533/2/1 Specific Configuration"
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config UART_ERROR
+       int "UART ERROR"
+       default 7
+config SPORT0_ERROR
+       int "SPORT0 ERROR"
+       default 7
+config SPI_ERROR
+       int "SPI ERROR"
+       default 7
+config SPORT1_ERROR
+       int "SPORT1 ERROR"
+       default 7
+config PPI_ERROR
+       int "PPI ERROR"
+       default 7
+config DMA_ERROR
+       int "DMA ERROR"
+       default 7
+config PLLWAKE_ERROR
+       int "PLL WAKEUP ERROR"
+       default 7
+
+config RTC_ERROR
+       int "RTC ERROR"
+       default 8
+config DMA0_PPI
+       int "DMA0 PPI"
+       default 8
+
+config DMA1_SPORT0RX
+       int "DMA1 (SPORT0 RX)"
+       default 9
+config DMA2_SPORT0TX
+       int "DMA2 (SPORT0 TX)"
+       default 9
+config DMA3_SPORT1RX
+       int "DMA3 (SPORT1 RX)"
+       default 9
+config DMA4_SPORT1TX
+       int "DMA4 (SPORT1 TX)"
+       default 9
+config DMA5_SPI
+       int "DMA5 (SPI)"
+       default 10
+config DMA6_UARTRX
+       int "DMA6 (UART0 RX)"
+       default 10
+config DMA7_UARTTX
+       int "DMA7 (UART0 TX)"
+       default 10
+config TIMER0
+       int "TIMER0"
+       default 11
+config TIMER1
+       int "TIMER1"
+       default 11
+config TIMER2
+       int "TIMER2"
+       default 11
+config PFA
+       int "PF Interrupt A"
+       default 12
+config PFB
+       int "PF Interrupt B"
+       default 12
+config MEMDMA0
+       int "MEMORY DMA0"
+       default 13
+config MEMDMA1
+       int "MEMORY DMA1"
+       default 13
+config WDTIMER
+       int "WATCH DOG TIMER"
+       default 13
+
+       help
+         Enter the priority numbers between 7-13 ONLY.  Others are Reserved.
+         This applies to all the above.  It is not recommended to assign the
+         highest priority number 7 to UART or any other device.
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf533/Makefile b/arch/blackfin/mach-bf533/Makefile
new file mode 100644 (file)
index 0000000..76d2c2b
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf533/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o
+
+obj-$(CONFIG_CPU_FREQ_BF533) += cpu.o
diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile
new file mode 100644 (file)
index 0000000..12a631a
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# arch/blackfin/mach-bf533/boards/Makefile
+#
+
+obj-$(CONFIG_GENERIC_BOARD)            += generic_board.o
+obj-$(CONFIG_BFIN533_STAMP)            += stamp.o
+obj-$(CONFIG_BFIN533_EZKIT)            += ezkit.o
+obj-$(CONFIG_BFIN533_BLUETECHNIX_CM)   += cm_bf533.o
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
new file mode 100644 (file)
index 0000000..23a7f60
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * File:         arch/blackfin/mach-bf533/boards/cm_bf533.c
+ * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au> Copright 2005
+ *
+ * Created:      2005
+ * Description:  Board description file
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/usb_isp1362.h>
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "Bluetechnix CM BF533";
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80",       /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,               /* Framework bus number */
+               .chip_select = 1,           /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },{
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,               /* Framework bus number */
+               .chip_select = 2,           /* Framework chip select. */
+               .platform_data = NULL,      /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .start = 0x20200300,
+               .end = 0x20200300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF0,
+               .end = IRQ_PF0,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 1,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20308000,
+               .end = 0x20308000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20308004,
+               .end = 0x20308004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF4,
+               .end = IRQ_PF4,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+static struct platform_device *cm_bf533_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+       &bfin_sport0_uart_device,
+       &bfin_sport1_uart_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+};
+
+static int __init cm_bf533_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(cm_bf533_devices, ARRAY_SIZE(cm_bf533_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(cm_bf533_init);
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
new file mode 100644 (file)
index 0000000..747298e
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * File:         arch/blackfin/mach-bf533/ezkit.c
+ * Based on:     Orginal Work
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:      2005
+ * Description:
+ *
+ * Modified:     Robin Getz <rgetz@blackfin.uclinux.org> - Named the boards
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/usb_isp1362.h>
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADDS-BF533-EZKIT";
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+/*
+ *  USB-LAN EzExtender board
+ *  Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x20310300,
+               .end = 0x20310300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF9,
+               .end = IRQ_PF9,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 2, /* Framework chip select. On STAMP537 it is SPISSEL2*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+static struct platform_device *ezkit_devices[] __initdata = {
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+};
+
+static int __init ezkit_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(ezkit_init);
diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
new file mode 100644 (file)
index 0000000..c0f43cc
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * File:         arch/blackfin/mach-bf533/generic_board.c
+ * Based on:     arch/blackfin/mach-bf533/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:      2005
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/irq.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "UNKNOWN BOARD";
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .start = 0x20300300,
+               .end = 0x20300300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PROG_INTB,
+               .end = IRQ_PROG_INTB,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },{
+               /*
+                *  denotes the flag pin and is used directly if
+                *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
+                */
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+static struct platform_device *generic_board_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+};
+
+static int __init generic_board_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       return platform_add_devices(generic_board_devices, ARRAY_SIZE(generic_board_devices));
+}
+
+arch_initcall(generic_board_init);
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
new file mode 100644 (file)
index 0000000..d7b3a5d
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * File:         arch/blackfin/mach-bf533/stamp.c
+ * Based on:     arch/blackfin/mach-bf533/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:      2005
+ * Description:  Board Info File for the BF533-STAMP
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb_isp1362.h>
+#endif
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADDS-BF533-STAMP";
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x20300300,
+               .end = 0x20300300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+       {
+               .start = 0x20300000,
+               .end = 0x20300000 + 0x100,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF10,
+               .end = IRQ_PF10,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device net2272_bfin_device = {
+       .name = "net2272",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+       .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+       .ctl_reg        = 0x4, /* send zero */
+       .enable_dma     = 0,
+       .bits_per_word  = 8,
+       .cs_change_per_word = 1,
+};
+#endif
+
+#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE)
+static struct bfin5xx_spi_chip ad5304_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 2, /* Framework chip select. On STAMP537 it is SPISSEL2*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 31250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_PBX)
+       {
+               .modalias       = "fxs-spi",
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select    = 3,
+               .controller_data= &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias       = "fxo-spi",
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select    = 2,
+               .controller_data= &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE)
+       {
+               .modalias = "ad5304_spi",
+               .max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 2,
+               .platform_data = NULL,
+               .controller_data = &ad5304_chip_info,
+               .mode = SPI_MODE_2,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+static struct platform_device bfin_fb_device = {
+       .name = "bf537-fb",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 1,
+};
+#endif
+
+static struct platform_device *stamp_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+       &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+       &bfin_sport0_uart_device,
+       &bfin_sport1_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c
new file mode 100644 (file)
index 0000000..99547c4
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * File:         arch/blackfin/mach-bf533/cpu.c
+ * Based on:
+ * Author:       michael.kang@analog.com
+ *
+ * Created:
+ * Description:  clock scaling for the bf533
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/dpmc.h>
+#include <linux/fs.h>
+#include <asm/bfin-global.h>
+
+/* CONFIG_CLKIN_HZ=11059200 */
+#define VCO5 (CONFIG_CLKIN_HZ*45)      /*497664000 */
+#define VCO4 (CONFIG_CLKIN_HZ*36)      /*398131200 */
+#define VCO3 (CONFIG_CLKIN_HZ*27)      /*298598400 */
+#define VCO2 (CONFIG_CLKIN_HZ*18)      /*199065600 */
+#define VCO1 (CONFIG_CLKIN_HZ*9)       /*99532800 */
+#define VCO(x) VCO##x
+
+#define FREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+/* frequency */
+static struct cpufreq_frequency_table bf533_freq_table[] = {
+       FREQ(1),
+       FREQ(3),
+       {VCO4, VCO4 / 2}, {VCO4, VCO4},
+       FREQ(5),
+       {0, CPUFREQ_TABLE_END},
+};
+
+/*
+ * dpmc_fops->ioctl()
+ * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ */
+static int bf533_getfreq(unsigned int cpu)
+{
+       unsigned long cclk_mhz, vco_mhz;
+
+       /* The driver only support single cpu */
+       if (cpu == 0)
+               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+       else
+               cclk_mhz = -1;
+       return cclk_mhz;
+}
+
+static int bf533_target(struct cpufreq_policy *policy,
+                           unsigned int target_freq, unsigned int relation)
+{
+       unsigned long cclk_mhz;
+       unsigned long vco_mhz;
+       unsigned long flags;
+       unsigned int index, vco_index;
+       int i;
+
+       struct cpufreq_freqs freqs;
+       if (cpufreq_frequency_table_target
+           (policy, bf533_freq_table, target_freq, relation, &index))
+               return -EINVAL;
+       cclk_mhz = bf533_freq_table[index].frequency;
+       vco_mhz = bf533_freq_table[index].index;
+
+       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+       freqs.old = bf533_getfreq(0);
+       freqs.new = cclk_mhz;
+       freqs.cpu = 0;
+
+       pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+                cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       local_irq_save(flags);
+       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+       local_irq_restore(flags);
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       vco_mhz = get_vco();
+       cclk_mhz = get_cclk();
+       return 0;
+}
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
+ */
+static int bf533_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, &bf533_freq_table);
+}
+
+static int __init __bf533_cpu_init(struct cpufreq_policy *policy)
+{
+       int result;
+
+       if (policy->cpu != 0)
+               return -EINVAL;
+
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+       /*Now ,only support one cpu */
+       policy->cur = bf533_getfreq(0);
+       cpufreq_frequency_table_get_attr(bf533_freq_table, policy->cpu);
+       return cpufreq_frequency_table_cpuinfo(policy, bf533_freq_table);
+}
+
+static struct freq_attr *bf533_freq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver bf533_driver = {
+       .verify = bf533_verify_speed,
+       .target = bf533_target,
+       .get = bf533_getfreq,
+       .init = __bf533_cpu_init,
+       .name = "bf533",
+       .owner = THIS_MODULE,
+       .attr = bf533_freq_attr,
+};
+
+static int __init bf533_cpu_init(void)
+{
+       return cpufreq_register_driver(&bf533_driver);
+}
+
+static void __exit bf533_cpu_exit(void)
+{
+       cpufreq_unregister_driver(&bf533_driver);
+}
+
+MODULE_AUTHOR("Mickael Kang");
+MODULE_DESCRIPTION("cpufreq driver for BF533 CPU");
+MODULE_LICENSE("GPL");
+
+module_init(bf533_cpu_init);
+module_exit(bf533_cpu_exit);
diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S
new file mode 100644 (file)
index 0000000..4808edb
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ * File:         arch/blackfin/mach-bf533/head.S
+ * Based on:
+ * Author:       Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
+ *
+ * Created:      1998
+ * Description:  bf533 startup file
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach/mem_init.h>
+#endif
+#if CONFIG_DEBUG_KERNEL_START
+#include <asm/mach-common/def_LPBlackfin.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK  0xFFB01000
+
+.text
+
+ENTRY(__start)
+ENTRY(__stext)
+       /* R0: argument of command line string, passed from uboot, save it */
+       R7 = R0;
+       /* Set the SYSCFG register */
+       R0 = 0x36;
+       /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+       SYSCFG = R0;
+       R0 = 0;
+
+       /*Clear Out All the data and pointer  Registers*/
+       R1 = R0;
+       R2 = R0;
+       R3 = R0;
+       R4 = R0;
+       R5 = R0;
+       R6 = R0;
+
+       P0 = R0;
+       P1 = R0;
+       P2 = R0;
+       P3 = R0;
+       P4 = R0;
+       P5 = R0;
+
+       LC0 = r0;
+       LC1 = r0;
+       L0 = r0;
+       L1 = r0;
+       L2 = r0;
+       L3 = r0;
+
+       /* Clear Out All the DAG Registers*/
+       B0 = r0;
+       B1 = r0;
+       B2 = r0;
+       B3 = r0;
+
+       I0 = r0;
+       I1 = r0;
+       I2 = r0;
+       I3 = r0;
+
+       M0 = r0;
+       M1 = r0;
+       M2 = r0;
+       M3 = r0;
+
+#if CONFIG_DEBUG_KERNEL_START
+
+/*
+ * Set up a temporary Event Vector Table, so if something bad happens before
+ * the kernel is fully started, it doesn't vector off into the bootloaders
+ * table
+ */
+       P0.l = lo(EVT2);
+       P0.h = hi(EVT2);
+       P1.l = lo(EVT15);
+       P1.h = hi(EVT15);
+       P2.l = debug_kernel_start_trap;
+       P2.h = debug_kernel_start_trap;
+
+       RTS = P2;
+       RTI = P2;
+       RTX = P2;
+       RTN = P2;
+       RTE = P2;
+
+.Lfill_temp_vector_table:
+       [P0++] = P2;    /* Core Event Vector Table */
+       CC = P0 == P1;
+       if !CC JUMP .Lfill_temp_vector_table
+       P0 = r0;
+       P1 = r0;
+       P2 = r0;
+
+#endif
+
+       p0.h = hi(FIO_MASKA_C);
+       p0.l = lo(FIO_MASKA_C);
+       r0 = 0xFFFF(Z);
+       w[p0] = r0.L;   /* Disable all interrupts */
+       ssync;
+
+       p0.h = hi(FIO_MASKB_C);
+       p0.l = lo(FIO_MASKB_C);
+       r0 = 0xFFFF(Z);
+       w[p0] = r0.L;   /* Disable all interrupts */
+       ssync;
+
+       /* Turn off the icache */
+       p0.l = (IMEM_CONTROL & 0xFFFF);
+       p0.h = (IMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENICPLB;
+       R0 = R0 & R1;
+
+       /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+       CLI R2;
+       SSYNC;
+#endif
+       [p0] = R0;
+       SSYNC;
+#ifdef ANOMALY_05000125
+       STI R2;
+#endif
+
+       /* Turn off the dcache */
+       p0.l = (DMEM_CONTROL & 0xFFFF);
+       p0.h = (DMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENDCPLB;
+       R0 = R0 & R1;
+
+       /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+       CLI R2;
+       SSYNC;
+#endif
+       [p0] = R0;
+       SSYNC;
+#ifdef ANOMALY_05000125
+       STI R2;
+#endif
+
+       /* Initialise UART */
+       p0.h = hi(UART_LCR);
+       p0.l = lo(UART_LCR);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable DLL writes */
+       ssync;
+
+       p0.h = hi(UART_DLL);
+       p0.l = lo(UART_DLL);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_DLH);
+       p0.l = lo(UART_DLH);
+       r0 = 0x00(Z);
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_GCTL);
+       p0.l = lo(UART_GCTL);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable UART clock */
+       ssync;
+
+       /* Initialize stack pointer */
+       sp.l = lo(INITIAL_STACK);
+       sp.h = hi(INITIAL_STACK);
+       fp = sp;
+       usp = sp;
+
+       /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+       call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+       call _start_dma_code;
+#endif
+
+       /* Code for initializing Async memory banks */
+
+       p2.h = hi(EBIU_AMBCTL1);
+       p2.l = lo(EBIU_AMBCTL1);
+       r0.h = hi(AMBCTL1VAL);
+       r0.l = lo(AMBCTL1VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMBCTL0);
+       p2.l = lo(EBIU_AMBCTL0);
+       r0.h = hi(AMBCTL0VAL);
+       r0.l = lo(AMBCTL0VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMGCTL);
+       p2.l = lo(EBIU_AMGCTL);
+       r0 = AMGCTLVAL;
+       w[p2] = r0;
+       ssync;
+
+       /* This section keeps the processor in supervisor mode
+        * during kernel boot.  Switches to user mode at end of boot.
+        * See page 3-9 of Hardware Reference manual for documentation.
+        */
+
+       /* EVT15 = _real_start */
+
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _real_start;
+       p1.h = _real_start;
+       [p0] = p1;
+       csync;
+
+       p0.l = lo(IMASK);
+       p0.h = hi(IMASK);
+       p1.l = IMASK_IVG15;
+       p1.h = 0x0;
+       [p0] = p1;
+       csync;
+
+       raise 15;
+       p0.l = .LWAIT_HERE;
+       p0.h = .LWAIT_HERE;
+       reti = p0;
+#if defined(ANOMALY_05000281)
+       nop; nop; nop;
+#endif
+       rti;
+
+.LWAIT_HERE:
+       jump .LWAIT_HERE;
+
+ENTRY(_real_start)
+       [ -- sp ] = reti;
+       p0.l = lo(WDOG_CTL);
+       p0.h = hi(WDOG_CTL);
+       r0 = 0xAD6(z);
+       w[p0] = r0;     /* watchdog off for now */
+       ssync;
+
+       /* Code update for BSS size == 0
+        * Zero out the bss region.
+        */
+
+       p1.l = ___bss_start;
+       p1.h = ___bss_start;
+       p2.l = ___bss_stop;
+       p2.h = ___bss_stop;
+       r0 = 0;
+       p2 -= p1;
+       lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
+.L_clear_bss:
+       B[p1++] = r0;
+
+       /* In case there is a NULL pointer reference
+        * Zero out region before stext
+        */
+
+       p1.l = 0x0;
+       p1.h = 0x0;
+       r0.l = __stext;
+       r0.h = __stext;
+       r0 = r0 >> 1;
+       p2 = r0;
+       r0 = 0;
+       lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
+.L_clear_zero:
+       W[p1++] = r0;
+
+/* pass the uboot arguments to the global value command line */
+       R0 = R7;
+       call _cmdline_init;
+
+       p1.l = __rambase;
+       p1.h = __rambase;
+       r0.l = __sdata;
+       r0.h = __sdata;
+       [p1] = r0;
+
+       p1.l = __ramstart;
+       p1.h = __ramstart;
+       p3.l = ___bss_stop;
+       p3.h = ___bss_stop;
+
+       r1 = p3;
+       [p1] = r1;
+
+       /*
+        *  load the current thread pointer and stack
+        */
+       r1.l = _init_thread_union;
+       r1.h = _init_thread_union;
+
+       r2.l = 0x2000;
+       r2.h = 0x0000;
+       r1 = r1 + r2;
+       sp = r1;
+       usp = sp;
+       fp = sp;
+       call _start_kernel;
+.L_exit:
+       jump.s  .L_exit;
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+       p0.h = hi(SIC_IWR);
+       p0.l = lo(SIC_IWR);
+       r0.l = 0x1;
+       r0.h = 0x0;
+       [p0] = r0;
+       SSYNC;
+
+       /*
+        *  Set PLL_CTL
+        *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+        *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
+        *   - [7]     = output delay (add 200ps of delay to mem signals)
+        *   - [6]     = input delay (add 200ps of input delay to mem signals)
+        *   - [5]     = PDWN      : 1=All Clocks off
+        *   - [3]     = STOPCK    : 1=Core Clock off
+        *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
+        *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+        *   all other bits set to zero
+        */
+
+       p0.h = hi(PLL_LOCKCNT);
+       p0.l = lo(PLL_LOCKCNT);
+       r0 = 0x300(Z);
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITSET (R0, 24);
+       [P2] = R0;
+       SSYNC;
+
+       r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
+       r0 = r0 << 9;                    /* Shift it over,                  */
+       r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
+       r0 = r1 | r0;
+       r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
+       r1 = r1 << 8;                    /* Shift it over                   */
+       r0 = r1 | r0;                    /* add them all together           */
+
+       p0.h = hi(PLL_CTL);
+       p0.l = lo(PLL_CTL);              /* Load the address                */
+       cli r2;                          /* Disable interrupts              */
+       ssync;
+       w[p0] = r0.l;                    /* Set the value                   */
+       idle;                            /* Wait for the PLL to stablize    */
+       sti r2;                          /* Enable interrupts               */
+
+.Lcheck_again:
+       p0.h = hi(PLL_STAT);
+       p0.l = lo(PLL_STAT);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,5);
+       if ! CC jump .Lcheck_again;
+
+       /* Configure SCLK & CCLK Dividers */
+       r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+       p0.h = hi(PLL_DIV);
+       p0.l = lo(PLL_DIV);
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = lo(EBIU_SDRRC);
+       p0.h = hi(EBIU_SDRRC);
+       r0 = mem_SDRRC;
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = (EBIU_SDBCTL & 0xFFFF);
+       p0.h = (EBIU_SDBCTL >> 16);     /* SDRAM Memory Bank Control Register */
+       r0 = mem_SDBCTL;
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITCLR (R0, 24);
+       p0.h = hi(EBIU_SDSTAT);
+       p0.l = lo(EBIU_SDSTAT);
+       r2.l = w[p0];
+       cc = bittst(r2,3);
+       if !cc jump .Lskip;
+       NOP;
+       BITSET (R0, 23);
+.Lskip:
+       [P2] = R0;
+       SSYNC;
+
+       R0.L = lo(mem_SDGCTL);
+       R0.H = hi(mem_SDGCTL);
+       R1 = [p2];
+       R1 = R1 | R0;
+       [P2] = R1;
+       SSYNC;
+
+       p0.h = hi(SIC_IWR);
+       p0.l = lo(SIC_IWR);
+       r0.l = lo(IWR_ENABLE_ALL)
+       r0.h = hi(IWR_ENABLE_ALL)
+       [p0] = r0;
+       SSYNC;
+
+       RTS;
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+ENTRY(_bfin_reset)
+       /* No more interrupts to be handled*/
+       CLI R6;
+       SSYNC;
+
+#if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
+       p0.h = hi(FIO_INEN);
+       p0.l = lo(FIO_INEN);
+       r0.l = ~(1 << CONFIG_ENET_FLASH_PIN);
+       w[p0] = r0.l;
+
+       p0.h = hi(FIO_DIR);
+       p0.l = lo(FIO_DIR);
+       r0.l = (1 << CONFIG_ENET_FLASH_PIN);
+       w[p0] = r0.l;
+
+       p0.h = hi(FIO_FLAG_C);
+       p0.l = lo(FIO_FLAG_C);
+       r0.l = (1 << CONFIG_ENET_FLASH_PIN);
+       w[p0] = r0.l;
+#endif
+
+       /* Clear the bits 13-15 in SWRST if they werent cleared */
+       p0.h = hi(SWRST);
+       p0.l = lo(SWRST);
+       csync;
+       r0.l = w[p0];
+
+       /* Clear the IMASK register */
+       p0.h = hi(IMASK);
+       p0.l = lo(IMASK);
+       r0 = 0x0;
+       [p0] = r0;
+
+       /* Clear the ILAT register */
+       p0.h = hi(ILAT);
+       p0.l = lo(ILAT);
+       r0 = [p0];
+       [p0] = r0;
+       SSYNC;
+
+       /* Disable the WDOG TIMER */
+       p0.h = hi(WDOG_CTL);
+       p0.l = lo(WDOG_CTL);
+       r0.l = 0xAD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Clear the sticky bit incase it is already set */
+       p0.h = hi(WDOG_CTL);
+       p0.l = lo(WDOG_CTL);
+       r0.l = 0x8AD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Program the count value */
+       R0.l = 0x100;
+       R0.h = 0x0;
+       P0.h = hi(WDOG_CNT);
+       P0.l = lo(WDOG_CNT);
+       [P0] = R0;
+       SSYNC;
+
+       /* Program WDOG_STAT if necessary */
+       P0.h = hi(WDOG_CTL);
+       P0.l = lo(WDOG_CTL);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,1);
+       if !CC JUMP .LWRITESTAT;
+       CC = BITTST(R0,2);
+       if !CC JUMP .LWRITESTAT;
+       JUMP .LSKIP_WRITE;
+
+.LWRITESTAT:
+       /* When watch dog timer is enabled, a write to STAT will load the contents of CNT to STAT */
+       R0 = 0x0000(z);
+       P0.h = hi(WDOG_STAT);
+       P0.l = lo(WDOG_STAT)
+       [P0] = R0;
+       SSYNC;
+
+.LSKIP_WRITE:
+       /* Enable the reset event */
+       P0.h = hi(WDOG_CTL);
+       P0.l = lo(WDOG_CTL);
+       R0 = W[P0](Z);
+       BITCLR(R0,1);
+       BITCLR(R0,2);
+       W[P0] = R0.L;
+       SSYNC;
+       NOP;
+
+       /* Enable the wdog counter */
+       R0 = W[P0](Z);
+       BITCLR(R0,4);
+       W[P0] = R0.L;
+       SSYNC;
+
+       IDLE;
+
+       RTS;
+
+#if CONFIG_DEBUG_KERNEL_START
+debug_kernel_start_trap:
+       /* Set up a temp stack in L1 - SDRAM might not be working  */
+       P0.L = lo(L1_DATA_A_START + 0x100);
+       P0.H = hi(L1_DATA_A_START + 0x100);
+       SP = P0;
+
+       /* Make sure the Clocks are the way I think they should be */
+       r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
+       r0 = r0 << 9;                    /* Shift it over,                  */
+       r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
+       r0 = r1 | r0;
+       r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
+       r1 = r1 << 8;                    /* Shift it over                   */
+       r0 = r1 | r0;                    /* add them all together           */
+
+       p0.h = hi(PLL_CTL);
+       p0.l = lo(PLL_CTL);              /* Load the address                */
+       cli r2;                          /* Disable interrupts              */
+       ssync;
+       w[p0] = r0.l;                    /* Set the value                   */
+       idle;                            /* Wait for the PLL to stablize    */
+       sti r2;                          /* Enable interrupts               */
+
+.Lcheck_again1:
+       p0.h = hi(PLL_STAT);
+       p0.l = lo(PLL_STAT);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,5);
+       if ! CC jump .Lcheck_again1;
+
+       /* Configure SCLK & CCLK Dividers */
+       r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+       p0.h = hi(PLL_DIV);
+       p0.l = lo(PLL_DIV);
+       w[p0] = r0.l;
+       ssync;
+
+       /* Make sure UART is enabled - you can never be sure */
+
+/*
+ * Setup for console. Argument comes from the menuconfig
+ */
+
+#ifdef CONFIG_BAUD_9600
+#define CONSOLE_BAUD_RATE       9600
+#elif CONFIG_BAUD_19200
+#define CONSOLE_BAUD_RATE       19200
+#elif CONFIG_BAUD_38400
+#define CONSOLE_BAUD_RATE       38400
+#elif CONFIG_BAUD_57600
+#define CONSOLE_BAUD_RATE       57600
+#elif CONFIG_BAUD_115200
+#define CONSOLE_BAUD_RATE       115200
+#endif
+
+       p0.h = hi(UART_GCTL);
+       p0.l = lo(UART_GCTL);
+       r0 = 0x00(Z);
+       w[p0] = r0.L;   /* To Turn off UART clocks */
+       ssync;
+
+       p0.h = hi(UART_LCR);
+       p0.l = lo(UART_LCR);
+       r0 = 0x83(Z);
+       w[p0] = r0.L;   /* To enable DLL writes */
+       ssync;
+
+       R1 = (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_SCLK_DIV) / (CONSOLE_BAUD_RATE * 16));
+
+       p0.h = hi(UART_DLL);
+       p0.l = lo(UART_DLL);
+       r0 = 0xFF(Z);
+       r0 = R1 & R0;
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_DLH);
+       p0.l = lo(UART_DLH);
+       r1 >>= 8 ;
+       w[p0] = r1.L;
+       ssync;
+
+       p0.h = hi(UART_GCTL);
+       p0.l = lo(UART_GCTL);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable UART clock */
+       ssync;
+
+       p0.h = hi(UART_LCR);
+       p0.l = lo(UART_LCR);
+       r0 = 0x03(Z);
+       w[p0] = r0.L;   /* To Turn on UART */
+       ssync;
+
+       p0.h = hi(UART_GCTL);
+       p0.l = lo(UART_GCTL);
+       r0 = 0x01(Z);
+       w[p0] = r0.L;   /* To Turn on UART Clocks */
+       ssync;
+
+       P0.h = hi(UART_THR);
+       P0.l = lo(UART_THR);
+       P1.h = hi(UART_LSR);
+       P1.l = lo(UART_LSR);
+
+       R0.L = 'K';
+       call .Lwait_char;
+       R0.L='e';
+       call .Lwait_char;
+       R0.L='r';
+       call .Lwait_char;
+       R0.L='n'
+       call .Lwait_char;
+       R0.L='e'
+       call .Lwait_char;
+       R0.L='l';
+       call .Lwait_char;
+       R0.L=' ';
+       call .Lwait_char;
+       R0.L='c';
+       call .Lwait_char;
+       R0.L='r';
+       call .Lwait_char;
+       R0.L='a';
+       call .Lwait_char;
+       R0.L='s';
+       call .Lwait_char;
+       R0.L='h';
+       call .Lwait_char;
+       R0.L='\r';
+       call .Lwait_char;
+       R0.L='\n';
+       call .Lwait_char;
+
+       R0.L='S';
+       call .Lwait_char;
+       R0.L='E';
+       call .Lwait_char;
+       R0.L='Q'
+       call .Lwait_char;
+       R0.L='S'
+       call .Lwait_char;
+       R0.L='T';
+       call .Lwait_char;
+       R0.L='A';
+       call .Lwait_char;
+       R0.L='T';
+       call .Lwait_char;
+       R0.L='=';
+       call .Lwait_char;
+       R2 = SEQSTAT;
+       call .Ldump_reg;
+
+       R0.L=' ';
+       call .Lwait_char;
+       R0.L='R';
+       call .Lwait_char;
+       R0.L='E'
+       call .Lwait_char;
+       R0.L='T'
+       call .Lwait_char;
+       R0.L='X';
+       call .Lwait_char;
+       R0.L='=';
+       call .Lwait_char;
+       R2 = RETX;
+       call .Ldump_reg;
+
+       R0.L='\r';
+       call .Lwait_char;
+       R0.L='\n';
+       call .Lwait_char;
+
+.Ldebug_kernel_start_trap_done:
+       JUMP    .Ldebug_kernel_start_trap_done;
+.Ldump_reg:
+       R3 = 32;
+       R4 = 0x0F;
+       R5 = ':';  /* one past 9 */
+
+.Ldump_reg2:
+       R0 = R2;
+       R3 += -4;
+       R0 >>>= R3;
+       R0 = R0 & R4;
+       R0 += 0x30;
+       CC = R0 <= R5;
+       if CC JUMP .Ldump_reg1;
+       R0 += 7;
+
+.Ldump_reg1:
+       R1.l = W[P1];
+       CC = BITTST(R1, 5);
+       if !CC JUMP .Ldump_reg1;
+       W[P0] = r0;
+
+       CC = R3 == 0;
+       if !CC JUMP .Ldump_reg2
+       RTS;
+
+.Lwait_char:
+       R1.l = W[P1];
+       CC = BITTST(R1, 5);
+       if !CC JUMP .Lwait_char;
+       W[P0] = r0;
+       RTS;
+
+#endif  /* CONFIG_DEBUG_KERNEL_START  */
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long   0
+__ramstart:
+.long   0
+__ramend:
+.long   0
diff --git a/arch/blackfin/mach-bf533/ints-priority.c b/arch/blackfin/mach-bf533/ints-priority.c
new file mode 100644 (file)
index 0000000..36a6933
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * File:         arch/blackfin/mach-bf533/ints-priority.c
+ * Based on:
+ * Author:       Michael Hennerich
+ *
+ * Created:      ?
+ * Description:  Set up the interupt priorities
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+
+void program_IAR(void)
+{
+       /* Program the IAR0 Register with the configured priority */
+       bfin_write_SIC_IAR0(((CONFIG_PLLWAKE_ERROR - 7) << PLLWAKE_ERROR_POS) |
+                           ((CONFIG_DMA_ERROR - 7) << DMA_ERROR_POS) |
+                           ((CONFIG_PPI_ERROR - 7) << PPI_ERROR_POS) |
+                           ((CONFIG_SPORT0_ERROR - 7) << SPORT0_ERROR_POS) |
+                           ((CONFIG_SPI_ERROR - 7) << SPI_ERROR_POS) |
+                           ((CONFIG_SPORT1_ERROR - 7) << SPORT1_ERROR_POS) |
+                           ((CONFIG_UART_ERROR - 7) << UART_ERROR_POS) |
+                           ((CONFIG_RTC_ERROR - 7) << RTC_ERROR_POS));
+
+       bfin_write_SIC_IAR1(((CONFIG_DMA0_PPI - 7) << DMA0_PPI_POS) |
+                           ((CONFIG_DMA1_SPORT0RX - 7) << DMA1_SPORT0RX_POS) |
+                           ((CONFIG_DMA2_SPORT0TX - 7) << DMA2_SPORT0TX_POS) |
+                           ((CONFIG_DMA3_SPORT1RX - 7) << DMA3_SPORT1RX_POS) |
+                           ((CONFIG_DMA4_SPORT1TX - 7) << DMA4_SPORT1TX_POS) |
+                           ((CONFIG_DMA5_SPI - 7) << DMA5_SPI_POS) |
+                           ((CONFIG_DMA6_UARTRX - 7) << DMA6_UARTRX_POS) |
+                           ((CONFIG_DMA7_UARTTX - 7) << DMA7_UARTTX_POS));
+
+       bfin_write_SIC_IAR2(((CONFIG_TIMER0 - 7) << TIMER0_POS) |
+                           ((CONFIG_TIMER1 - 7) << TIMER1_POS) |
+                           ((CONFIG_TIMER2 - 7) << TIMER2_POS) |
+                           ((CONFIG_PFA - 7) << PFA_POS) |
+                           ((CONFIG_PFB - 7) << PFB_POS) |
+                           ((CONFIG_MEMDMA0 - 7) << MEMDMA0_POS) |
+                           ((CONFIG_MEMDMA1 - 7) << MEMDMA1_POS) |
+                           ((CONFIG_WDTIMER - 7) << WDTIMER_POS));
+
+       SSYNC();
+}
diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig
new file mode 100644 (file)
index 0000000..cc9ae38
--- /dev/null
@@ -0,0 +1,141 @@
+if (BF537 || BF534 || BF536)
+
+menu "BF537 Specific Configuration"
+
+comment "PORT F/G Selection"
+choice
+       prompt "Select BF537/6/4 default GPIO PFx PORTx"
+       help
+         Quick Hack for BF537/6/4 default GPIO PFx PORTF.
+
+config BF537_PORT_F
+       bool "Select BF537/6/4 default GPIO PFx PORTF"
+       depends on (BF537 || BF536 || BF534)
+       help
+         Quick Hack for BF537/6/4 default GPIO PFx PORTF.
+
+config BF537_PORT_G
+       bool "Select BF537/6/4 default GPIO PFx PORTG"
+       depends on (BF537 || BF536 || BF534)
+       help
+         Quick Hack for BF537/6/4 default GPIO PFx PORTG.
+
+config BF537_PORT_H
+       bool "Select BF537/6/4 default GPIO PFx PORTH"
+       depends on (BF537 || BF536 || BF534)
+       help
+         Quick Hack for BF537/6/4 default GPIO PFx PORTH
+         Use only when Blackfin EMAC support is not required.
+
+endchoice
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+       int "IRQ_PLL_WAKEUP"
+       default 7
+config IRQ_DMA_ERROR
+       int "IRQ_DMA_ERROR Generic"
+       default 7
+config IRQ_ERROR
+       int "IRQ_ERROR: CAN MAC SPORT0 SPORT1 SPI UART0 UART1"
+       default 7
+config IRQ_RTC
+       int "IRQ_RTC"
+       default 8
+config IRQ_PPI
+       int "IRQ_PPI"
+       default 8
+config IRQ_SPORT0_RX
+       int "IRQ_SPORT0_RX"
+       default 9
+config IRQ_SPORT0_TX
+       int "IRQ_SPORT0_TX"
+       default 9
+config IRQ_SPORT1_RX
+       int "IRQ_SPORT1_RX"
+       default 9
+config IRQ_SPORT1_TX
+       int "IRQ_SPORT1_TX"
+       default 9
+config IRQ_TWI
+       int "IRQ_TWI"
+       default 10
+config IRQ_SPI
+       int "IRQ_SPI"
+       default 10
+config IRQ_UART0_RX
+       int "IRQ_UART0_RX"
+       default 10
+config IRQ_UART0_TX
+       int "IRQ_UART0_TX"
+       default 10
+config IRQ_UART1_RX
+       int "IRQ_UART1_RX"
+       default 10
+config IRQ_UART1_TX
+       int "IRQ_UART1_TX"
+       default 10
+config IRQ_CAN_RX
+       int "IRQ_CAN_RX"
+       default 11
+config IRQ_CAN_TX
+       int "IRQ_CAN_TX"
+       default 11
+config IRQ_MAC_RX
+       int "IRQ_MAC_RX"
+       default 11
+config IRQ_MAC_TX
+       int "IRQ_MAC_TX"
+       default 11
+config IRQ_TMR0
+       int "IRQ_TMR0"
+       default 12
+config IRQ_TMR1
+       int "IRQ_TMR1"
+       default 12
+config IRQ_TMR2
+       int "IRQ_TMR2"
+       default 12
+config IRQ_TMR3
+       int "IRQ_TMR3"
+       default 12
+config IRQ_TMR4
+       int "IRQ_TMR4"
+       default 12
+config IRQ_TMR5
+       int "IRQ_TMR5"
+       default 12
+config IRQ_TMR6
+       int "IRQ_TMR6"
+       default 12
+config IRQ_TMR7
+       int "IRQ_TMR7"
+       default 12
+config IRQ_PROG_INTA
+       int "IRQ_PROG_INTA"
+       default 12
+config IRQ_PORTG_INTB
+       int "IRQ_PORTG_INTB"
+       default 12
+config IRQ_MEM_DMA0
+       int "IRQ_MEM_DMA0"
+       default 13
+config IRQ_MEM_DMA1
+       int "IRQ_MEM_DMA1"
+       default 13
+config IRQ_WATCH
+       int "IRQ_WATCH"
+       default 13
+
+       help
+         Enter the priority numbers between 7-13 ONLY.  Others are Reserved.
+         This applies to all the above.  It is not recommended to assign the
+         highest priority number 7 to UART or any other device.
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf537/Makefile b/arch/blackfin/mach-bf537/Makefile
new file mode 100644 (file)
index 0000000..f32d442
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf537/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o
+
+obj-$(CONFIG_CPU_FREQ)   += cpu.o
diff --git a/arch/blackfin/mach-bf537/boards/Makefile b/arch/blackfin/mach-bf537/boards/Makefile
new file mode 100644 (file)
index 0000000..23323ca
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf537/boards/Makefile
+#
+
+obj-y                                  += eth_mac.o
+obj-$(CONFIG_GENERIC_BOARD)            += generic_board.o
+obj-$(CONFIG_BFIN537_STAMP)            += stamp.o led.o
+obj-$(CONFIG_BFIN537_BLUETECHNIX_CM)   += cm_bf537.o
+obj-$(CONFIG_PNAV10)                   += pnav10.o
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
new file mode 100644 (file)
index 0000000..6a60618
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * File:         arch/blackfin/mach-bf537/boards/cm_bf537.c
+ * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:      2005
+ * Description:  Board description file
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/usb_isp1362.h>
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "Bluetechnix CM BF537";
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+       .enable_dma = 1,
+       .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+       {
+               .modalias = "ad9960-spi",
+               .max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 1,
+               .controller_data = &ad9960_spi_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc_dummy",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 7,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .start = 0x20200300,
+               .end = 0x20200300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF14,
+               .end = IRQ_PF14,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+               },
+};
+
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20308000,
+               .end = 0x20308000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20308004,
+               .end = 0x20308004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PG15,
+               .end = IRQ_PG15,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+       {
+               .start = 0x20200000,
+               .end = 0x20200000 + 0x100,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device net2272_bfin_device = {
+       .name = "net2272",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+       .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+       .name = "bfin_mac",
+};
+#endif
+
+static struct platform_device *cm_bf537_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+       &bfin_sport0_uart_device,
+       &bfin_sport1_uart_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+       &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+};
+
+static int __init cm_bf537_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(cm_bf537_init);
diff --git a/arch/blackfin/mach-bf537/boards/eth_mac.c b/arch/blackfin/mach-bf537/boards/eth_mac.c
new file mode 100644 (file)
index 0000000..e129a08
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  arch/blackfin/mach-bf537/board/eth_mac.c
+ *
+ *  Copyright (C) 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 <asm/blackfin.h>
+
+#if    defined(CONFIG_GENERIC_BOARD) \
+       || defined(CONFIG_BFIN537_STAMP)
+
+/*
+ * Currently the MAC address is saved in Flash by U-Boot
+ */
+#define FLASH_MAC      0x203f0000
+
+void get_bf537_ether_addr(char *addr)
+{
+       unsigned int flash_mac = (unsigned int) FLASH_MAC;
+       *(u32 *)(&(addr[0])) = bfin_read32(flash_mac);
+       flash_mac += 4;
+       *(u16 *)(&(addr[4])) = bfin_read16(flash_mac);
+}
+
+#else
+
+/*
+ * Provide MAC address function for other specific board setting
+ */
+void get_bf537_ether_addr(char *addr)
+{
+       printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n",__FILE__);
+}
+
+#endif
+
+EXPORT_SYMBOL(get_bf537_ether_addr);
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
new file mode 100644 (file)
index 0000000..9019c0e
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * File:         arch/blackfin/mach-bf537/boards/generic_board.c
+ * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/usb_isp1362.h>
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+#include <linux/usb_sl811.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "UNKNOWN BOARD";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+static struct resource bfin_pcmcia_cf_resources[] = {
+       {
+               .start = 0x20310000, /* IO PORT */
+               .end = 0x20312000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20311000, /* Attribute Memeory */
+               .end = 0x20311FFF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PROG_INTA,
+               .end = IRQ_PROG_INTA,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+       },{
+               .start = IRQ_PF4,
+               .end = IRQ_PF4,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+       },{
+               .start = 6, /* Card Detect PF6 */
+               .end = 6,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_pcmcia_cf_device = {
+       .name = "bfin_cf_pcmcia",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources),
+       .resource = bfin_pcmcia_cf_resources,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x20300300,
+               .end = 0x20300300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PROG_INTB,
+               .end = IRQ_PROG_INTB,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },{
+               /*
+                *  denotes the flag pin and is used directly if
+                *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
+                */
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+static struct resource sl811_hcd_resources[] = {
+       {
+               .start = 0x20340000,
+               .end = 0x20340000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20340004,
+               .end = 0x20340004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PROG_INTA,
+               .end = IRQ_PROG_INTA,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },{
+               .start = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
+               .end = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+void sl811_port_power(struct device *dev, int is_on)
+{
+       unsigned short mask = (1<<CONFIG_USB_SL811_BFIN_GPIO_VBUS);
+
+       bfin_write_PORT_FER(bfin_read_PORT_FER() & ~mask);
+       bfin_write_FIO_DIR(bfin_read_FIO_DIR() | mask);
+
+       if (is_on)
+               bfin_write_FIO_FLAG_S(mask);
+       else
+               bfin_write_FIO_FLAG_C(mask);
+}
+#endif
+
+static struct sl811_platform_data sl811_priv = {
+       .potpg = 10,
+       .power = 250,           /* == 500mA */
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+       .port_power = &sl811_port_power,
+#endif
+};
+
+static struct platform_device sl811_hcd_device = {
+       .name = "sl811-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &sl811_priv,
+       },
+       .num_resources = ARRAY_SIZE(sl811_hcd_resources),
+       .resource = sl811_hcd_resources,
+};
+
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20360000,
+               .end = 0x20360000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20360004,
+               .end = 0x20360004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PROG_INTA,
+               .end = IRQ_PROG_INTA,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },{
+               .start = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
+               .end = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+       .name = "bfin_mac",
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+       {
+               .start = 0x20300000,
+               .end = 0x20300000 + 0x100,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device net2272_bfin_device = {
+       .name = "net2272",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+       .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 2, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+       {
+               .modalias = "ad9960-spi",
+               .max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 1,
+               .controller_data = &ad9960_spi_chip_info,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+static struct platform_device bfin_fb_device = {
+       .name = "bf537-fb",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+static struct platform_device *stamp_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+       &bfin_pcmcia_cf_device,
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+       &sl811_hcd_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+       &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+       &bfin_fb_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf537/boards/led.S b/arch/blackfin/mach-bf537/boards/led.S
new file mode 100644 (file)
index 0000000..4e9ea42
--- /dev/null
@@ -0,0 +1,183 @@
+/****************************************************
+ * LED1 ---- PF6        LED2 ---- PF7               *
+ * LED3 ---- PF8        LED4 ---- PF9               *
+ * LED5 ---- PF10       LED6 ---- PF11              *
+ ****************************************************/
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+/* All functions in this file save the registers they uses.
+   So there is no need to save any registers before calling them.  */
+
+       .text;
+
+/* Initialize LEDs.  */
+
+ENTRY(_led_init)
+       LINK 12;
+       [--SP] = P0;
+       [--SP] = R0;
+       [--SP] = R1;
+       [--SP] = R2;
+       R1 = PF6|PF7|PF8|PF9|PF10|PF11 (Z);
+       R2 = ~R1;
+
+       P0.H = hi(PORTF_FER);
+       P0.L = lo(PORTF_FER);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 & R2;
+       W[P0] = R0.L;
+       SSYNC;
+
+       P0.H = hi(PORTFIO_DIR);
+       P0.L = lo(PORTFIO_DIR);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 | R1;
+       W[P0] = R0.L;
+       SSYNC;
+
+       P0.H = hi(PORTFIO_INEN);
+       P0.L = lo(PORTFIO_INEN);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 & R2;
+       W[P0] = R0.L;
+       SSYNC;
+
+       R2 = [SP++];
+       R1 = [SP++];
+       R0 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_init, .-_led_init
+
+/* Set one LED on. Leave other LEDs unchanged.
+   It expects the LED number passed through R0.  */
+
+ENTRY(_led_on)
+       LINK 12;
+       [--SP] = P0;
+       [--SP] = R1;
+       CALL _led_init;
+       R1 = 1;
+       R0 += 5;
+       R1 <<= R0;
+       P0.H = hi(PORTFIO);
+       P0.L = lo(PORTFIO);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 | R1;
+       W[P0] = R0.L;
+       SSYNC;
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_on, .-_led_on
+
+/* Set one LED off. Leave other LEDs unchanged.  */
+
+ENTRY(_led_off)
+       LINK 12;
+       [--SP] = P0;
+       [--SP] = R1;
+       CALL _led_init;
+       R1 = 1;
+       R0 += 5;
+       R1 <<= R0;
+       R1 = ~R1;
+       P0.H = hi(PORTFIO);
+       P0.L = lo(PORTFIO);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 & R1;
+       W[P0] = R0.L;
+       SSYNC;
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_off, .-_led_off
+
+/* Toggle one LED. Leave other LEDs unchanged.  */
+
+ENTRY(_led_toggle)
+       LINK 12;
+       [--SP] = P0;
+       [--SP] = R1;
+       CALL _led_init;
+       R1 = 1;
+       R0 += 5;
+       R1 <<= R0;
+       P0.H = hi(PORTFIO);
+       P0.L = lo(PORTFIO);
+       R0 = W[P0](Z);
+       SSYNC;
+       R0 = R0 ^ R1;
+       W[P0] = R0.L;
+       SSYNC;
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_toggle, .-_led_toggle
+
+/* Display the number using LEDs in binary format.  */
+
+ENTRY(_led_disp_num)
+       LINK 12;
+       [--SP] = P0;
+       [--SP] = R1;
+       [--SP] = R2;
+       CALL _led_init;
+       R1 = 0x3f(X);
+       R0 = R0 & R1;
+       R2 = 6(X);
+       R0 <<= R2;
+       R1 <<= R2;
+       P0.H = hi(PORTFIO);
+       P0.L = lo(PORTFIO);
+       R2 = W[P0](Z);
+       SSYNC;
+       R1 = ~R1;
+       R2 = R2 & R1;
+       R2 = R2 | R0;
+       W[P0] = R2.L;
+       SSYNC;
+       R2 = [SP++];
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_disp_num, .-_led_disp_num
+
+/* Toggle the number using LEDs in binary format.  */
+
+ENTRY(_led_toggle_num)
+       LINK 12;
+       [--SP] = P0;
+       [--SP] = R1;
+       [--SP] = R2;
+       CALL _led_init;
+       R1 = 0x3f(X);
+       R0 = R0 & R1;
+       R1 = 6(X);
+       R0 <<= R1;
+       P0.H = hi(PORTFIO);
+       P0.L = lo(PORTFIO);
+       R1 = W[P0](Z);
+       SSYNC;
+       R1 = R1 ^ R0;
+       W[P0] = R1.L;
+       SSYNC;
+       R2 = [SP++];
+       R1 = [SP++];
+       P0 = [SP++];
+       UNLINK;
+       RTS;
+       .size   _led_toggle_num, .-_led_toggle_num
+
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
new file mode 100644 (file)
index 0000000..40d3a1b
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * File:         arch/blackfin/mach-bf537/boards/stamp.c
+ * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb_isp1362.h>
+#endif
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+#include <linux/usb_sl811.h>
+
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "PNAV-1.0";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+static struct resource bfin_pcmcia_cf_resources[] = {
+       {
+               .start = 0x20310000, /* IO PORT */
+               .end = 0x20312000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20311000, /* Attribute Memeory */
+               .end = 0x20311FFF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF4,
+               .end = IRQ_PF4,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+       },{
+               .start = 6, /* Card Detect PF6 */
+               .end = 6,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_pcmcia_cf_device = {
+       .name = "bfin_cf_pcmcia",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources),
+       .resource = bfin_pcmcia_cf_resources,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x20300300,
+               .end = 0x20300300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+static struct resource sl811_hcd_resources[] = {
+       {
+               .start = 0x20340000,
+               .end = 0x20340000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20340004,
+               .end = 0x20340004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = CONFIG_USB_SL811_BFIN_IRQ,
+               .end = CONFIG_USB_SL811_BFIN_IRQ,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+void sl811_port_power(struct device *dev, int is_on)
+{
+       unsigned short mask = (1 << CONFIG_USB_SL811_BFIN_GPIO_VBUS);
+
+       bfin_write_PORT_FER(bfin_read_PORT_FER() & ~mask);
+       bfin_write_FIO_DIR(bfin_read_FIO_DIR() | mask);
+
+       if (is_on)
+               bfin_write_FIO_FLAG_S(mask);
+       else
+               bfin_write_FIO_FLAG_C(mask);
+}
+#endif
+
+static struct sl811_platform_data sl811_priv = {
+       .potpg = 10,
+       .power = 250,       /* == 500mA */
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+       .port_power = &sl811_port_power,
+#endif
+};
+
+static struct platform_device sl811_hcd_device = {
+       .name = "sl811-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &sl811_priv,
+       },
+       .num_resources = ARRAY_SIZE(sl811_hcd_resources),
+       .resource = sl811_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20360000,
+               .end = 0x20360000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20360004,
+               .end = 0x20360004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+               .end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+       .name = "bfin_mac",
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+       {
+               .start = 0x20300000,
+               .end = 0x20300000 + 0x100,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device net2272_bfin_device = {
+       .name = "net2272",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+       .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+       .enable_dma = 1,
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+       .ctl_reg        = 0x4, /* send zero */
+       .enable_dma     = 0,
+       .bits_per_word  = 8,
+       .cs_change_per_word = 1,
+};
+#endif
+
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+       .cs_change_per_word = 1,
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+       .model                  = 7877,
+       .vref_delay_usecs       = 50,   /* internal, no capacitor */
+       .x_plate_ohms           = 419,
+       .y_plate_ohms           = 486,
+       .pressure_max           = 1000,
+       .pressure_min           = 0,
+       .stopacq_polarity       = 1,
+       .first_conversion_delay = 3,
+       .acquisition_time       = 1,
+       .averaging              = 1,
+       .pen_down_acc_interval  = 1,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+       {
+               .modalias = "ad9960-spi",
+               .max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 1,
+               .controller_data = &ad9960_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc_dummy",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 7,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_PBX)
+       {
+               .modalias       = "fxs-spi",
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select    = 3,
+               .controller_data= &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias       = "fxo-spi",
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select    = 2,
+               .controller_data= &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+{
+       .modalias               = "ad7877",
+       .platform_data          = &bfin_ad7877_ts_info,
+       .irq                    = IRQ_PF2,
+       .max_speed_hz           = 12500000,     /* max spi clock (SCK) speed in HZ */
+       .bus_num                = 1,
+       .chip_select            = 5,
+       .controller_data = &spi_ad7877_chip_info,
+},
+#endif
+
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+static struct platform_device bfin_fb_device = {
+       .name = "bf537-fb",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+
+static struct platform_device *stamp_devices[] __initdata = {
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+       &bfin_pcmcia_cf_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+       &sl811_hcd_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+       &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+       &bfin_fb_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info,
+                               ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
new file mode 100644 (file)
index 0000000..ba2f875
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * File:         arch/blackfin/mach-bf537/boards/stamp.c
+ * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb_isp1362.h>
+#endif
+#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
+#include <linux/usb_sl811.h>
+
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADDS-BF537-STAMP";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#define ISP1761_BASE       0x203C0000
+#define ISP1761_IRQ        IRQ_PF7
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+static struct resource bfin_isp1761_resources[] = {
+       [0] = {
+               .name   = "isp1761-regs",
+               .start  = ISP1761_BASE + 0x00000000,
+               .end    = ISP1761_BASE + 0x000fffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = ISP1761_IRQ,
+               .end    = ISP1761_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_isp1761_device = {
+       .name           = "isp1761",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(bfin_isp1761_resources),
+       .resource       = bfin_isp1761_resources,
+};
+
+static struct platform_device *bfin_isp1761_devices[] = {
+       &bfin_isp1761_device,
+};
+
+int __init bfin_isp1761_init(void)
+{
+       unsigned int num_devices=ARRAY_SIZE(bfin_isp1761_devices);
+
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+       return platform_add_devices(bfin_isp1761_devices, num_devices);
+}
+
+void __exit bfin_isp1761_exit(void)
+{
+       platform_device_unregister(&bfin_isp1761_device);
+}
+
+arch_initcall(bfin_isp1761_init);
+#endif
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+static struct resource bfin_pcmcia_cf_resources[] = {
+       {
+               .start = 0x20310000, /* IO PORT */
+               .end = 0x20312000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20311000, /* Attribute Memeory */
+               .end = 0x20311FFF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF4,
+               .end = IRQ_PF4,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+       },{
+               .start = 6, /* Card Detect PF6 */
+               .end = 6,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_pcmcia_cf_device = {
+       .name = "bfin_cf_pcmcia",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources),
+       .resource = bfin_pcmcia_cf_resources,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x20300300,
+               .end = 0x20300300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+static struct resource sl811_hcd_resources[] = {
+       {
+               .start = 0x20340000,
+               .end = 0x20340000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20340004,
+               .end = 0x20340004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = CONFIG_USB_SL811_BFIN_IRQ,
+               .end = CONFIG_USB_SL811_BFIN_IRQ,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+void sl811_port_power(struct device *dev, int is_on)
+{
+       unsigned short mask = (1 << CONFIG_USB_SL811_BFIN_GPIO_VBUS);
+
+       bfin_write_PORT_FER(bfin_read_PORT_FER() & ~mask);
+       bfin_write_FIO_DIR(bfin_read_FIO_DIR() | mask);
+
+       if (is_on)
+               bfin_write_FIO_FLAG_S(mask);
+       else
+               bfin_write_FIO_FLAG_C(mask);
+}
+#endif
+
+static struct sl811_platform_data sl811_priv = {
+       .potpg = 10,
+       .power = 250,       /* == 500mA */
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+       .port_power = &sl811_port_power,
+#endif
+};
+
+static struct platform_device sl811_hcd_device = {
+       .name = "sl811-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &sl811_priv,
+       },
+       .num_resources = ARRAY_SIZE(sl811_hcd_resources),
+       .resource = sl811_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20360000,
+               .end = 0x20360000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20360004,
+               .end = 0x20360004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+               .end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+       .name = "bfin_mac",
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+       {
+               .start = 0x20300000,
+               .end = 0x20300000 + 0x100,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device net2272_bfin_device = {
+       .name = "net2272",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+       .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+       .enable_dma = 1,
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+       .ctl_reg        = 0x4, /* send zero */
+       .enable_dma     = 0,
+       .bits_per_word  = 8,
+       .cs_change_per_word = 1,
+};
+#endif
+
+#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE)
+static struct bfin5xx_spi_chip ad5304_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+//     .cs_change_per_word = 1,
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+       .model                  = 7877,
+       .vref_delay_usecs       = 50,   /* internal, no capacitor */
+       .x_plate_ohms           = 419,
+       .y_plate_ohms           = 486,
+       .pressure_max           = 1000,
+       .pressure_min           = 0,
+       .stopacq_polarity       = 1,
+       .first_conversion_delay = 3,
+       .acquisition_time       = 1,
+       .averaging              = 1,
+       .pen_down_acc_interval  = 1,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+       {
+               .modalias = "ad9960-spi",
+               .max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 1,
+               .controller_data = &ad9960_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc_dummy",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 0,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_PBX)
+       {
+               .modalias       = "fxs-spi",
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select    = 3,
+               .controller_data= &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias       = "fxo-spi",
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select    = 2,
+               .controller_data= &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE)
+       {
+               .modalias = "ad5304_spi",
+               .max_speed_hz = 1250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 2,
+               .platform_data = NULL,
+               .controller_data = &ad5304_chip_info,
+               .mode = SPI_MODE_2,
+       },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+       {
+               .modalias               = "ad7877",
+               .platform_data          = &bfin_ad7877_ts_info,
+               .irq                    = IRQ_PF6,
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 1,
+               .chip_select  = 1,
+               .controller_data = &spi_ad7877_chip_info,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+static struct platform_device bfin_fb_device = {
+       .name = "bf537-fb",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct platform_device i2c_bfin_twi_device = {
+       .name = "i2c-bfin-twi",
+       .id = 0,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 1,
+};
+#endif
+
+static struct platform_device *stamp_devices[] __initdata = {
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+       &bfin_pcmcia_cf_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+       &sl811_hcd_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+       &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+       &bfin_fb_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+       &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+       &bfin_sport0_uart_device,
+       &bfin_sport1_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info,
+                               ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf537/cpu.c b/arch/blackfin/mach-bf537/cpu.c
new file mode 100644 (file)
index 0000000..2d83b7e
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * File:         arch/blackfin/mach-bf537/cpu.c
+ * Based on:
+ * Author:       michael.kang@analog.com
+ *
+ * Created:
+ * Description:  clock scaling for the bf537
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/dpmc.h>
+#include <linux/fs.h>
+#include <asm/bfin-global.h>
+
+/* CONFIG_CLKIN_HZ=11059200 */
+#define VCO5 (CONFIG_CLKIN_HZ*45)      /*497664000 */
+#define VCO4 (CONFIG_CLKIN_HZ*36)      /*398131200 */
+#define VCO3 (CONFIG_CLKIN_HZ*27)      /*298598400 */
+#define VCO2 (CONFIG_CLKIN_HZ*18)      /*199065600 */
+#define VCO1 (CONFIG_CLKIN_HZ*9)       /*99532800 */
+#define VCO(x) VCO##x
+
+#define FREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+/* frequency */
+static struct cpufreq_frequency_table bf537_freq_table[] = {
+       FREQ(1),
+       FREQ(3),
+       {VCO4, VCO4 / 2}, {VCO4, VCO4},
+       FREQ(5),
+       {0, CPUFREQ_TABLE_END},
+};
+
+/*
+ * dpmc_fops->ioctl()
+ * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ */
+static int bf537_getfreq(unsigned int cpu)
+{
+       unsigned long cclk_mhz, vco_mhz;
+
+       /* The driver only support single cpu */
+       if (cpu == 0)
+               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+       else
+               cclk_mhz = -1;
+       return cclk_mhz;
+}
+
+static int bf537_target(struct cpufreq_policy *policy,
+                           unsigned int target_freq, unsigned int relation)
+{
+       unsigned long cclk_mhz;
+       unsigned long vco_mhz;
+       unsigned long flags;
+       unsigned int index, vco_index;
+       int i;
+
+       struct cpufreq_freqs freqs;
+       if (cpufreq_frequency_table_target
+           (policy, bf537_freq_table, target_freq, relation, &index))
+               return -EINVAL;
+       cclk_mhz = bf537_freq_table[index].frequency;
+       vco_mhz = bf537_freq_table[index].index;
+
+       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+       freqs.old = bf537_getfreq(0);
+       freqs.new = cclk_mhz;
+       freqs.cpu = 0;
+
+       pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+                cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       local_irq_save(flags);
+       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+       local_irq_restore(flags);
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       vco_mhz = get_vco();
+       cclk_mhz = get_cclk();
+       return 0;
+}
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
+ */
+static int bf537_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, &bf537_freq_table);
+}
+
+static int __init __bf537_cpu_init(struct cpufreq_policy *policy)
+{
+       int result;
+
+       if (policy->cpu != 0)
+               return -EINVAL;
+
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+       /*Now ,only support one cpu */
+       policy->cur = bf537_getfreq(0);
+       cpufreq_frequency_table_get_attr(bf537_freq_table, policy->cpu);
+       return cpufreq_frequency_table_cpuinfo(policy, bf537_freq_table);
+}
+
+static struct freq_attr *bf537_freq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver bf537_driver = {
+       .verify = bf537_verify_speed,
+       .target = bf537_target,
+       .get = bf537_getfreq,
+       .init = __bf537_cpu_init,
+       .name = "bf537",
+       .owner = THIS_MODULE,
+       .attr = bf537_freq_attr,
+};
+
+static int __init bf537_cpu_init(void)
+{
+       return cpufreq_register_driver(&bf537_driver);
+}
+
+static void __exit bf537_cpu_exit(void)
+{
+       cpufreq_unregister_driver(&bf537_driver);
+}
+
+MODULE_AUTHOR("Mickael Kang");
+MODULE_DESCRIPTION("cpufreq driver for BF537 CPU");
+MODULE_LICENSE("GPL");
+
+module_init(bf537_cpu_init);
+module_exit(bf537_cpu_exit);
diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
new file mode 100644 (file)
index 0000000..d104e1d
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * File:         arch/blackfin/mach-bf537/head.S
+ * Based on:     arch/blackfin/mach-bf533/head.S
+ * Author:       Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
+ *
+ * Created:      1998
+ * Description:  Startup code for Blackfin BF537
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach/mem_init.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK   0xFFB01000
+
+.text
+
+ENTRY(__start)
+ENTRY(__stext)
+       /* R0: argument of command line string, passed from uboot, save it */
+       R7 = R0;
+       /* Set the SYSCFG register */
+       R0 = 0x36;
+       SYSCFG = R0;   /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+       R0 = 0;
+
+       /* Clear Out All the data and pointer  Registers*/
+       R1 = R0;
+       R2 = R0;
+       R3 = R0;
+       R4 = R0;
+       R5 = R0;
+       R6 = R0;
+
+       P0 = R0;
+       P1 = R0;
+       P2 = R0;
+       P3 = R0;
+       P4 = R0;
+       P5 = R0;
+
+       LC0 = r0;
+       LC1 = r0;
+       L0 = r0;
+       L1 = r0;
+       L2 = r0;
+       L3 = r0;
+
+       /* Clear Out All the DAG Registers*/
+       B0 = r0;
+       B1 = r0;
+       B2 = r0;
+       B3 = r0;
+
+       I0 = r0;
+       I1 = r0;
+       I2 = r0;
+       I3 = r0;
+
+       M0 = r0;
+       M1 = r0;
+       M2 = r0;
+       M3 = r0;
+
+       /* Turn off the icache */
+       p0.l = (IMEM_CONTROL & 0xFFFF);
+       p0.h = (IMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENICPLB;
+       R0 = R0 & R1;
+
+       /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+       CLI R2;
+       SSYNC;
+#endif
+       [p0] = R0;
+       SSYNC;
+#ifdef ANOMALY_05000125
+       STI R2;
+#endif
+
+       /* Turn off the dcache */
+       p0.l = (DMEM_CONTROL & 0xFFFF);
+       p0.h = (DMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENDCPLB;
+       R0 = R0 & R1;
+
+       /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+       CLI R2;
+       SSYNC;
+#endif
+       [p0] = R0;
+       SSYNC;
+#ifdef ANOMALY_05000125
+       STI R2;
+#endif
+
+       /* Initialise General-Purpose I/O Modules on BF537 */
+       /* Rev 0.0 Anomaly 05000212 - PORTx_FER,
+        * PORT_MUX Registers Do Not accept "writes" correctly:
+        */
+       p0.h = hi(BFIN_PORT_MUX);
+       p0.l = lo(BFIN_PORT_MUX);
+#ifdef ANOMALY_05000212
+       R0.L = W[P0]; /* Read */
+       SSYNC;
+#endif
+       R0 = (PGDE_UART | PFTE_UART)(Z);
+#ifdef ANOMALY_05000212
+       W[P0] = R0.L; /* Write */
+       SSYNC;
+#endif
+       W[P0] = R0.L; /* Enable both UARTS */
+       SSYNC;
+
+       p0.h = hi(PORTF_FER);
+       p0.l = lo(PORTF_FER);
+#ifdef ANOMALY_05000212
+       R0.L = W[P0]; /* Read */
+       SSYNC;
+#endif
+       R0 = 0x000F(Z);
+#ifdef ANOMALY_05000212
+       W[P0] = R0.L; /* Write */
+       SSYNC;
+#endif
+       /* Enable peripheral function of PORTF for UART0 and UART1 */
+       W[P0] = R0.L;
+       SSYNC;
+
+#if !defined(CONFIG_BF534)
+       p0.h = hi(EMAC_SYSTAT);
+       p0.l = lo(EMAC_SYSTAT);
+       R0.h = 0xFFFF; /* Clear EMAC Interrupt Status bits */
+       R0.l = 0xFFFF;
+       [P0] = R0;
+       SSYNC;
+#endif
+
+#ifdef CONFIG_BF537_PORT_H
+       p0.h = hi(PORTH_FER);
+       p0.l = lo(PORTH_FER);
+       R0.L = W[P0]; /* Read */
+       SSYNC;
+       R0 = 0x0000;
+       W[P0] = R0.L; /* Write */
+       SSYNC;
+       W[P0] = R0.L; /* Disable peripheral function of PORTH */
+       SSYNC;
+#endif
+
+       /*Initialise UART*/
+       p0.h = hi(UART_LCR);
+       p0.l = lo(UART_LCR);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable DLL writes */
+       ssync;
+
+       p0.h = hi(UART_DLL);
+       p0.l = lo(UART_DLL);
+       r0 = 0x00(Z);
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_DLH);
+       p0.l = lo(UART_DLH);
+       r0 = 0x00(Z);
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_GCTL);
+       p0.l = lo(UART_GCTL);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable UART clock */
+       ssync;
+
+       /* Initialize stack pointer */
+       sp.l = lo(INITIAL_STACK);
+       sp.h = hi(INITIAL_STACK);
+       fp = sp;
+       usp = sp;
+
+       /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+       call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+       call _start_dma_code;
+#endif
+       /* Code for initializing Async memory banks */
+
+       p2.h = hi(EBIU_AMBCTL1);
+       p2.l = lo(EBIU_AMBCTL1);
+       r0.h = hi(AMBCTL1VAL);
+       r0.l = lo(AMBCTL1VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMBCTL0);
+       p2.l = lo(EBIU_AMBCTL0);
+       r0.h = hi(AMBCTL0VAL);
+       r0.l = lo(AMBCTL0VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMGCTL);
+       p2.l = lo(EBIU_AMGCTL);
+       r0 = AMGCTLVAL;
+       w[p2] = r0;
+       ssync;
+
+       /* This section keeps the processor in supervisor mode
+        * during kernel boot.  Switches to user mode at end of boot.
+        * See page 3-9 of Hardware Reference manual for documentation.
+        */
+
+       /* EVT15 = _real_start */
+
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _real_start;
+       p1.h = _real_start;
+       [p0] = p1;
+       csync;
+
+       p0.l = lo(IMASK);
+       p0.h = hi(IMASK);
+       p1.l = IMASK_IVG15;
+       p1.h = 0x0;
+       [p0] = p1;
+       csync;
+
+       raise 15;
+       p0.l = .LWAIT_HERE;
+       p0.h = .LWAIT_HERE;
+       reti = p0;
+#if defined(ANOMALY_05000281)
+       nop; nop; nop;
+#endif
+       rti;
+
+.LWAIT_HERE:
+       jump .LWAIT_HERE;
+
+ENTRY(_real_start)
+       [ -- sp ] = reti;
+       p0.l = lo(WDOG_CTL);
+       p0.h = hi(WDOG_CTL);
+       r0 = 0xAD6(z);
+       w[p0] = r0;     /* watchdog off for now */
+       ssync;
+
+       /* Code update for BSS size == 0
+        * Zero out the bss region.
+        */
+
+       p1.l = ___bss_start;
+       p1.h = ___bss_start;
+       p2.l = ___bss_stop;
+       p2.h = ___bss_stop;
+       r0 = 0;
+       p2 -= p1;
+       lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+.L_clear_bss:
+       B[p1++] = r0;
+
+       /* In case there is a NULL pointer reference
+        * Zero out region before stext
+        */
+
+       p1.l = 0x0;
+       p1.h = 0x0;
+       r0.l = __stext;
+       r0.h = __stext;
+       r0 = r0 >> 1;
+       p2 = r0;
+       r0 = 0;
+       lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+.L_clear_zero:
+       W[p1++] = r0;
+
+       /* pass the uboot arguments to the global value command line */
+       R0 = R7;
+       call _cmdline_init;
+
+       p1.l = __rambase;
+       p1.h = __rambase;
+       r0.l = __sdata;
+       r0.h = __sdata;
+       [p1] = r0;
+
+       p1.l = __ramstart;
+       p1.h = __ramstart;
+       p3.l = ___bss_stop;
+       p3.h = ___bss_stop;
+
+       r1 = p3;
+       [p1] = r1;
+
+
+       /*
+        *  load the current thread pointer and stack
+        */
+       r1.l = _init_thread_union;
+       r1.h = _init_thread_union;
+
+       r2.l = 0x2000;
+       r2.h = 0x0000;
+       r1 = r1 + r2;
+       sp = r1;
+       usp = sp;
+       fp = sp;
+       call _start_kernel;
+.L_exit:
+       jump.s  .L_exit;
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+
+       /* Enable PHY CLK buffer output */
+       p0.h = hi(VR_CTL);
+       p0.l = lo(VR_CTL);
+       r0.l = w[p0];
+       bitset(r0, 14);
+       w[p0] = r0.l;
+       ssync;
+
+       p0.h = hi(SIC_IWR);
+       p0.l = lo(SIC_IWR);
+       r0.l = 0x1;
+       r0.h = 0x0;
+       [p0] = r0;
+       SSYNC;
+
+       /*
+        *  Set PLL_CTL
+        *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+        *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
+        *   - [7]     = output delay (add 200ps of delay to mem signals)
+        *   - [6]     = input delay (add 200ps of input delay to mem signals)
+        *   - [5]     = PDWN      : 1=All Clocks off
+        *   - [3]     = STOPCK    : 1=Core Clock off
+        *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
+        *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+        *   all other bits set to zero
+        */
+
+       p0.h = hi(PLL_LOCKCNT);
+       p0.l = lo(PLL_LOCKCNT);
+       r0 = 0x300(Z);
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITSET (R0, 24);
+       [P2] = R0;
+       SSYNC;
+
+       r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
+       r0 = r0 << 9;                    /* Shift it over,                  */
+       r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
+       r0 = r1 | r0;
+       r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
+       r1 = r1 << 8;                    /* Shift it over                   */
+       r0 = r1 | r0;                    /* add them all together           */
+
+       p0.h = hi(PLL_CTL);
+       p0.l = lo(PLL_CTL);              /* Load the address                */
+       cli r2;                          /* Disable interrupts              */
+       ssync;
+       w[p0] = r0.l;                    /* Set the value                   */
+       idle;                            /* Wait for the PLL to stablize    */
+       sti r2;                          /* Enable interrupts               */
+
+.Lcheck_again:
+       p0.h = hi(PLL_STAT);
+       p0.l = lo(PLL_STAT);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,5);
+       if ! CC jump .Lcheck_again;
+
+       /* Configure SCLK & CCLK Dividers */
+       r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+       p0.h = hi(PLL_DIV);
+       p0.l = lo(PLL_DIV);
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = lo(EBIU_SDRRC);
+       p0.h = hi(EBIU_SDRRC);
+       r0 = mem_SDRRC;
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = (EBIU_SDBCTL & 0xFFFF);
+       p0.h = (EBIU_SDBCTL >> 16);     /* SDRAM Memory Bank Control Register */
+       r0 = mem_SDBCTL;
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITCLR (R0, 24);
+       p0.h = hi(EBIU_SDSTAT);
+       p0.l = lo(EBIU_SDSTAT);
+       r2.l = w[p0];
+       cc = bittst(r2,3);
+       if !cc jump .Lskip;
+       NOP;
+       BITSET (R0, 23);
+.Lskip:
+       [P2] = R0;
+       SSYNC;
+
+       R0.L = lo(mem_SDGCTL);
+       R0.H = hi(mem_SDGCTL);
+       R1 = [p2];
+       R1 = R1 | R0;
+       [P2] = R1;
+       SSYNC;
+
+       p0.h = hi(SIC_IWR);
+       p0.l = lo(SIC_IWR);
+       r0.l = lo(IWR_ENABLE_ALL);
+       r0.h = hi(IWR_ENABLE_ALL);
+       [p0] = r0;
+       SSYNC;
+
+       RTS;
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+ENTRY(_bfin_reset)
+       /* No more interrupts to be handled*/
+       CLI R6;
+       SSYNC;
+
+#if defined(CONFIG_MTD_M25P80)
+/*
+ * The following code fix the SPI flash reboot issue,
+ * /CS signal of the chip which is using PF10 return to GPIO mode
+ */
+       p0.h = hi(PORTF_FER);
+       p0.l = lo(PORTF_FER);
+       r0.l = 0x0000;
+       w[p0] = r0.l;
+       SSYNC;
+
+/* /CS return to high */
+       p0.h = hi(PORTFIO);
+       p0.l = lo(PORTFIO);
+       r0.l = 0xFFFF;
+       w[p0] = r0.l;
+       SSYNC;
+
+/* Delay some time, This is necessary */
+       r1.h = 0;
+       r1.l = 0x400;
+       p1   = r1;
+       lsetup (_delay_lab1,_delay_lab1_end ) lc1 = p1;
+_delay_lab1:
+       r0.h = 0;
+       r0.l = 0x8000;
+       p0   = r0;
+       lsetup (_delay_lab0,_delay_lab0_end ) lc0 = p0;
+_delay_lab0:
+       nop;
+_delay_lab0_end:
+       nop;
+_delay_lab1_end:
+       nop;
+#endif
+
+       /* Clear the bits 13-15 in SWRST if they werent cleared */
+       p0.h = hi(SWRST);
+       p0.l = lo(SWRST);
+       csync;
+       r0.l = w[p0];
+
+       /* Clear the IMASK register */
+       p0.h = hi(IMASK);
+       p0.l = lo(IMASK);
+       r0 = 0x0;
+       [p0] = r0;
+
+       /* Clear the ILAT register */
+       p0.h = hi(ILAT);
+       p0.l = lo(ILAT);
+       r0 = [p0];
+       [p0] = r0;
+       SSYNC;
+
+       /* Disable the WDOG TIMER */
+       p0.h = hi(WDOG_CTL);
+       p0.l = lo(WDOG_CTL);
+       r0.l = 0xAD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Clear the sticky bit incase it is already set */
+       p0.h = hi(WDOG_CTL);
+       p0.l = lo(WDOG_CTL);
+       r0.l = 0x8AD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Program the count value */
+       R0.l = 0x100;
+       R0.h = 0x0;
+       P0.h = hi(WDOG_CNT);
+       P0.l = lo(WDOG_CNT);
+       [P0] = R0;
+       SSYNC;
+
+       /* Program WDOG_STAT if necessary */
+       P0.h = hi(WDOG_CTL);
+       P0.l = lo(WDOG_CTL);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,1);
+       if !CC JUMP .LWRITESTAT;
+       CC = BITTST(R0,2);
+       if !CC JUMP .LWRITESTAT;
+       JUMP .LSKIP_WRITE;
+
+.LWRITESTAT:
+       /* When watch dog timer is enabled,
+        * a write to STAT will load the contents of CNT to STAT
+        */
+       R0 = 0x0000(z);
+       P0.h = hi(WDOG_STAT);
+       P0.l = lo(WDOG_STAT)
+       [P0] = R0;
+       SSYNC;
+
+.LSKIP_WRITE:
+       /* Enable the reset event */
+       P0.h = hi(WDOG_CTL);
+       P0.l = lo(WDOG_CTL);
+       R0 = W[P0](Z);
+       BITCLR(R0,1);
+       BITCLR(R0,2);
+       W[P0] = R0.L;
+       SSYNC;
+       NOP;
+
+       /* Enable the wdog counter */
+       R0 = W[P0](Z);
+       BITCLR(R0,4);
+       W[P0] = R0.L;
+       SSYNC;
+
+       IDLE;
+
+       RTS;
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long   0
+__ramstart:
+.long   0
+__ramend:
+.long   0
diff --git a/arch/blackfin/mach-bf537/ints-priority.c b/arch/blackfin/mach-bf537/ints-priority.c
new file mode 100644 (file)
index 0000000..fd6308e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * File:         arch/blackfin/mach-bf537/ints-priority.c
+ * Based on:     arch/blackfin/mach-bf533/ints-priority.c
+ * Author:       Michael Hennerich
+ *
+ * Created:
+ * Description:  Set up the interupt priorities
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+
+void program_IAR(void)
+{
+       /* Program the IAR0 Register with the configured priority */
+       bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+                           ((CONFIG_IRQ_DMA_ERROR - 7) << IRQ_DMA_ERROR_POS) |
+                           ((CONFIG_IRQ_ERROR - 7) << IRQ_ERROR_POS) |
+                           ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS) |
+                           ((CONFIG_IRQ_PPI - 7) << IRQ_PPI_POS) |
+                           ((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+                           ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+                           ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS));
+
+       bfin_write_SIC_IAR1(((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+                           ((CONFIG_IRQ_TWI - 7) << IRQ_TWI_POS) |
+                           ((CONFIG_IRQ_SPI - 7) << IRQ_SPI_POS) |
+                           ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+                           ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS) |
+                           ((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+                           ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+                           ((CONFIG_IRQ_CAN_RX - 7) << IRQ_CAN_RX_POS));
+
+       bfin_write_SIC_IAR2(((CONFIG_IRQ_CAN_TX - 7) << IRQ_CAN_TX_POS) |
+                           ((CONFIG_IRQ_MAC_RX - 7) << IRQ_MAC_RX_POS) |
+                           ((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
+                           ((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
+                           ((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
+                           ((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
+                           ((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
+                           ((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS));
+
+       bfin_write_SIC_IAR3(((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
+                           ((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
+                           ((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS) |
+                           ((CONFIG_IRQ_PROG_INTA - 7) << IRQ_PROG_INTA_POS) |
+                           ((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
+                           ((CONFIG_IRQ_MEM_DMA0 - 7) << IRQ_MEM_DMA0_POS) |
+                           ((CONFIG_IRQ_MEM_DMA1 - 7) << IRQ_MEM_DMA1_POS) |
+                           ((CONFIG_IRQ_WATCH - 7) << IRQ_WATCH_POS));
+
+       SSYNC();
+}
diff --git a/arch/blackfin/mach-bf561/Kconfig b/arch/blackfin/mach-bf561/Kconfig
new file mode 100644 (file)
index 0000000..0a17c4c
--- /dev/null
@@ -0,0 +1,222 @@
+if BF561
+
+menu "BF561 Specific Configuration"
+
+comment "Core B Support"
+
+menu "Core B Support"
+
+config BF561_COREB
+       bool "Enable Core B support"
+       default y
+
+config BF561_COREB_RESET
+       bool "Enable Core B reset support"
+       default n
+       help
+         This requires code in the application that is loaded
+         into Core B. In order to reset, the application needs
+         to install an interrupt handler for Supplemental
+         Interrupt 0, that sets RETI to 0xff600000 and writes
+         bit 11 of SICB_SYSCR when bit 5 of SICA_SYSCR is 0.
+         This causes Core B to stall when Supplemental Interrupt
+         0 is set, and will reset PC to 0xff600000 when
+         COREB_SRAM_INIT is cleared.
+
+endmenu
+
+comment "Interrupt Priority Assignment"
+
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+       int "PLL Wakeup Interrupt"
+       default 7
+config IRQ_DMA1_ERROR
+       int "DMA1 Error (generic)"
+       default 7
+config IRQ_DMA2_ERROR
+       int "DMA2 Error (generic)"
+       default 7
+config IRQ_IMDMA_ERROR
+       int "IMDMA Error (generic)"
+       default 7
+config IRQ_PPI0_ERROR
+       int "PPI0 Error Interrupt"
+       default 7
+config IRQ_PPI1_ERROR
+       int "PPI1 Error Interrupt"
+       default 7
+config IRQ_SPORT0_ERROR
+       int "SPORT0 Error Interrupt"
+       default 7
+config IRQ_SPORT1_ERROR
+       int "SPORT1 Error Interrupt"
+       default 7
+config IRQ_SPI_ERROR
+       int "SPI Error Interrupt"
+       default 7
+config IRQ_UART_ERROR
+       int "UART Error Interrupt"
+       default 7
+config IRQ_RESERVED_ERROR
+       int "Reserved Interrupt"
+       default 7
+config IRQ_DMA1_0
+       int "DMA1 0  Interrupt(PPI1)"
+       default 8
+config IRQ_DMA1_1
+       int "DMA1 1  Interrupt(PPI2)"
+       default 8
+config IRQ_DMA1_2
+       int "DMA1 2  Interrupt"
+       default 8
+config IRQ_DMA1_3
+       int "DMA1 3  Interrupt"
+       default 8
+config IRQ_DMA1_4
+       int "DMA1 4  Interrupt"
+       default 8
+config IRQ_DMA1_5
+       int "DMA1 5  Interrupt"
+       default 8
+config IRQ_DMA1_6
+       int "DMA1 6  Interrupt"
+       default 8
+config IRQ_DMA1_7
+       int "DMA1 7  Interrupt"
+       default 8
+config IRQ_DMA1_8
+       int "DMA1 8  Interrupt"
+       default 8
+config IRQ_DMA1_9
+       int "DMA1 9  Interrupt"
+       default 8
+config IRQ_DMA1_10
+       int "DMA1 10 Interrupt"
+       default 8
+config IRQ_DMA1_11
+       int "DMA1 11 Interrupt"
+       default 8
+config IRQ_DMA2_0
+       int "DMA2 0  (SPORT0 RX)"
+       default 9
+config IRQ_DMA2_1
+       int "DMA2 1  (SPORT0 TX)"
+       default 9
+config IRQ_DMA2_2
+       int "DMA2 2  (SPORT1 RX)"
+       default 9
+config IRQ_DMA2_3
+       int "DMA2 3  (SPORT2 TX)"
+       default 9
+config IRQ_DMA2_4
+       int "DMA2 4  (SPI)"
+       default 9
+config IRQ_DMA2_5
+       int "DMA2 5  (UART RX)"
+       default 9
+config IRQ_DMA2_6
+       int "DMA2 6  (UART TX)"
+       default 9
+config IRQ_DMA2_7
+       int "DMA2 7  Interrupt"
+       default 9
+config IRQ_DMA2_8
+       int "DMA2 8  Interrupt"
+       default 9
+config IRQ_DMA2_9
+       int "DMA2 9  Interrupt"
+       default 9
+config IRQ_DMA2_10
+       int "DMA2 10 Interrupt"
+       default 9
+config IRQ_DMA2_11
+       int "DMA2 11 Interrupt"
+       default 9
+config IRQ_TIMER0
+       int "TIMER 0  Interrupt"
+       default 10
+config IRQ_TIMER1
+       int "TIMER 1  Interrupt"
+       default 10
+config IRQ_TIMER2
+       int "TIMER 2  Interrupt"
+       default 10
+config IRQ_TIMER3
+       int "TIMER 3  Interrupt"
+       default 10
+config IRQ_TIMER4
+       int "TIMER 4  Interrupt"
+       default 10
+config IRQ_TIMER5
+       int "TIMER 5  Interrupt"
+       default 10
+config IRQ_TIMER6
+       int "TIMER 6  Interrupt"
+       default 10
+config IRQ_TIMER7
+       int "TIMER 7  Interrupt"
+       default 10
+config IRQ_TIMER8
+       int "TIMER 8  Interrupt"
+       default 10
+config IRQ_TIMER9
+       int "TIMER 9  Interrupt"
+       default 10
+config IRQ_TIMER10
+       int "TIMER 10 Interrupt"
+       default 10
+config IRQ_TIMER11
+       int "TIMER 11 Interrupt"
+       default 10
+config IRQ_PROG0_INTA
+       int "Programmable Flags0 A (8)"
+       default 11
+config IRQ_PROG0_INTB
+       int "Programmable Flags0 B (8)"
+       default 11
+config IRQ_PROG1_INTA
+       int "Programmable Flags1 A (8)"
+       default 11
+config IRQ_PROG1_INTB
+       int "Programmable Flags1 B (8)"
+       default 11
+config IRQ_PROG2_INTA
+       int "Programmable Flags2 A (8)"
+       default 11
+config IRQ_PROG2_INTB
+       int "Programmable Flags2 B (8)"
+       default 11
+config IRQ_DMA1_WRRD0
+       int "MDMA1 0 write/read INT"
+       default 8
+config IRQ_DMA1_WRRD1
+       int "MDMA1 1 write/read INT"
+       default 8
+config IRQ_DMA2_WRRD0
+       int "MDMA2 0 write/read INT"
+       default 9
+config IRQ_DMA2_WRRD1
+       int "MDMA2 1 write/read INT"
+       default 9
+config IRQ_IMDMA_WRRD0
+       int "IMDMA 0 write/read INT"
+       default 12
+config IRQ_IMDMA_WRRD1
+       int "IMDMA 1 write/read INT"
+       default 12
+config IRQ_WDTIMER
+       int "Watch Dog Timer"
+       default 13
+
+       help
+         Enter the priority numbers between 7-13 ONLY.  Others are Reserved.
+         This applies to all the above.  It is not recommended to assign the
+         highest priority number 7 to UART or any other device.
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf561/Makefile b/arch/blackfin/mach-bf561/Makefile
new file mode 100644 (file)
index 0000000..57f475a
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf561/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o
+
+obj-$(CONFIG_BF561_COREB) += coreb.o
diff --git a/arch/blackfin/mach-bf561/boards/Makefile b/arch/blackfin/mach-bf561/boards/Makefile
new file mode 100644 (file)
index 0000000..886edc7
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# arch/blackfin/mach-bf561/boards/Makefile
+#
+
+obj-$(CONFIG_GENERIC_BOARD)            += generic_board.o
+obj-$(CONFIG_BFIN561_EZKIT)            += ezkit.o
+obj-$(CONFIG_BFIN561_BLUETECHNIX_CM)   += cm_bf561.o
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
new file mode 100644 (file)
index 0000000..6824e95
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * File:         arch/blackfin/mach-bf533/boards/cm_bf561.c
+ * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au> Copright 2005
+ *
+ * Created:      2006
+ * Description:  Board description file
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/usb_isp1362.h>
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "Bluetechnix CM BF561";
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI perpherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00020000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       },{
+               .name = "kernel",
+               .size = 0xe0000,
+               .offset = 0x20000
+       },{
+               .name = "file system",
+               .size = 0x700000,
+               .offset = 0x00100000,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+       .enable_dma = 1,
+       .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+       {
+               .modalias = "ad9960-spi",
+               .max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = 1,
+               .controller_data = &ad9960_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x28000300,
+               .end = 0x28000300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF0,
+               .end = IRQ_PF0,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x24008000,
+               .end = 0x24008000,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x24008004,
+               .end = 0x24008004,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF47,
+               .end = IRQ_PF47,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+        {
+                .start = 0xFFC00400,
+                .end = 0xFFC004FF,
+                .flags = IORESOURCE_MEM,
+        },
+};
+
+static struct platform_device bfin_uart_device = {
+        .name = "bfin-uart",
+        .id = 1,
+        .num_resources = ARRAY_SIZE(bfin_uart_resources),
+        .resource = bfin_uart_resources,
+};
+#endif
+
+static struct platform_device *cm_bf561_devices[] __initdata = {
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+        &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+};
+
+static int __init cm_bf561_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(cm_bf561_devices, ARRAY_SIZE(cm_bf561_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+       return 0;
+}
+
+arch_initcall(cm_bf561_init);
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
new file mode 100644 (file)
index 0000000..14eb4f9
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * File:         arch/blackfin/mach-bf561/ezkit.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADDS-BF561-EZKIT";
+
+/*
+ *  USB-LAN EzExtender board
+ *  Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x2C010300,
+               .end = 0x2C010300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+
+               .start = IRQ_PF9,
+               .end = IRQ_PF9,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+        {
+                .start = 0xFFC00400,
+                .end = 0xFFC004FF,
+                .flags = IORESOURCE_MEM,
+        },
+};
+
+static struct platform_device bfin_uart_device = {
+        .name = "bfin-uart",
+        .id = 1,
+        .num_resources = ARRAY_SIZE(bfin_uart_resources),
+        .resource = bfin_uart_resources,
+};
+#endif
+
+#ifdef CONFIG_SPI_BFIN
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+#endif
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+};
+
+static struct platform_device *ezkit_devices[] __initdata = {
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+        &bfin_uart_device,
+#endif
+};
+
+static int __init ezkit_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       ret = platform_add_devices(ezkit_devices,
+                ARRAY_SIZE(ezkit_devices));
+       if (ret < 0)
+               return ret;
+       return spi_register_board_info(bfin_spi_board_info,
+                               ARRAY_SIZE(bfin_spi_board_info));
+}
+
+arch_initcall(ezkit_init);
diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
new file mode 100644 (file)
index 0000000..585ecdd
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * File:         arch/blackfin/mach-bf561/generic_board.c
+ * Based on:     arch/blackfin/mach-bf533/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/irq.h>
+
+char *bfin_board_name = "UNKNOWN BOARD";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .start = 0x2C010300,
+               .end = 0x2C010300 + 16,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PROG_INTB,
+               .end = IRQ_PROG_INTB,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },{
+               /*
+                *  denotes the flag pin and is used directly if
+                *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
+                */
+               .start = IRQ_PF9,
+               .end = IRQ_PF9,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+static struct platform_device *generic_board_devices[] __initdata = {
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+};
+
+static int __init generic_board_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       return platform_add_devices(generic_board_devices,
+                                   ARRAY_SIZE(generic_board_devices));
+}
+
+arch_initcall(generic_board_init);
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
new file mode 100644 (file)
index 0000000..b28582f
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * File:         arch/blackfin/mach-bf561/coreb.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  Handle CoreB on a BF561
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+#define MODULE_VER             "v0.1"
+
+static spinlock_t coreb_lock;
+static wait_queue_head_t coreb_dma_wait;
+
+#define COREB_IS_OPEN          0x00000001
+#define COREB_IS_RUNNING       0x00000010
+
+#define CMD_COREB_INDEX                1
+#define CMD_COREB_START                2
+#define CMD_COREB_STOP         3
+#define CMD_COREB_RESET                4
+
+#define COREB_MINOR            229
+
+static unsigned long coreb_status = 0;
+static unsigned long coreb_base = 0xff600000;
+static unsigned long coreb_size = 0x4000;
+int coreb_dma_done;
+
+static loff_t coreb_lseek(struct file *file, loff_t offset, int origin);
+static ssize_t coreb_read(struct file *file, char *buf, size_t count,
+                         loff_t * ppos);
+static ssize_t coreb_write(struct file *file, const char *buf, size_t count,
+                          loff_t * ppos);
+static int coreb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                      unsigned long arg);
+static int coreb_open(struct inode *inode, struct file *file);
+static int coreb_release(struct inode *inode, struct file *file);
+
+static irqreturn_t coreb_dma_interrupt(int irq, void *dev_id)
+{
+       clear_dma_irqstat(CH_MEM_STREAM2_DEST);
+       coreb_dma_done = 1;
+       wake_up_interruptible(&coreb_dma_wait);
+       return IRQ_HANDLED;
+}
+
+static ssize_t coreb_write(struct file *file, const char *buf, size_t count,
+                          loff_t * ppos)
+{
+       unsigned long p = *ppos;
+       ssize_t wrote = 0;
+
+       if (p + count > coreb_size)
+               return -EFAULT;
+
+       while (count > 0) {
+               int len = count;
+
+               if (len > PAGE_SIZE)
+                       len = PAGE_SIZE;
+
+               coreb_dma_done = 0;
+
+               /* Source Channel */
+               set_dma_start_addr(CH_MEM_STREAM2_SRC, (unsigned long)buf);
+               set_dma_x_count(CH_MEM_STREAM2_SRC, len);
+               set_dma_x_modify(CH_MEM_STREAM2_SRC, sizeof(char));
+               set_dma_config(CH_MEM_STREAM2_SRC, RESTART);
+               /* Destination Channel */
+               set_dma_start_addr(CH_MEM_STREAM2_DEST, coreb_base + p);
+               set_dma_x_count(CH_MEM_STREAM2_DEST, len);
+               set_dma_x_modify(CH_MEM_STREAM2_DEST, sizeof(char));
+               set_dma_config(CH_MEM_STREAM2_DEST, WNR | RESTART | DI_EN);
+
+               enable_dma(CH_MEM_STREAM2_SRC);
+               enable_dma(CH_MEM_STREAM2_DEST);
+
+               wait_event_interruptible(coreb_dma_wait, coreb_dma_done);
+
+               disable_dma(CH_MEM_STREAM2_SRC);
+               disable_dma(CH_MEM_STREAM2_DEST);
+
+               count -= len;
+               wrote += len;
+               buf += len;
+               p += len;
+       }
+       *ppos = p;
+       return wrote;
+}
+
+static ssize_t coreb_read(struct file *file, char *buf, size_t count,
+                         loff_t * ppos)
+{
+       unsigned long p = *ppos;
+       ssize_t read = 0;
+
+       if ((p + count) > coreb_size)
+               return -EFAULT;
+
+       while (count > 0) {
+               int len = count;
+
+               if (len > PAGE_SIZE)
+                       len = PAGE_SIZE;
+
+               coreb_dma_done = 0;
+
+               /* Source Channel */
+               set_dma_start_addr(CH_MEM_STREAM2_SRC, coreb_base + p);
+               set_dma_x_count(CH_MEM_STREAM2_SRC, len);
+               set_dma_x_modify(CH_MEM_STREAM2_SRC, sizeof(char));
+               set_dma_config(CH_MEM_STREAM2_SRC, RESTART);
+               /* Destination Channel */
+               set_dma_start_addr(CH_MEM_STREAM2_DEST, (unsigned long)buf);
+               set_dma_x_count(CH_MEM_STREAM2_DEST, len);
+               set_dma_x_modify(CH_MEM_STREAM2_DEST, sizeof(char));
+               set_dma_config(CH_MEM_STREAM2_DEST, WNR | RESTART | DI_EN);
+
+               enable_dma(CH_MEM_STREAM2_SRC);
+               enable_dma(CH_MEM_STREAM2_DEST);
+
+               wait_event_interruptible(coreb_dma_wait, coreb_dma_done);
+
+               disable_dma(CH_MEM_STREAM2_SRC);
+               disable_dma(CH_MEM_STREAM2_DEST);
+
+               count -= len;
+               read += len;
+               buf += len;
+               p += len;
+       }
+
+       return read;
+}
+
+static loff_t coreb_lseek(struct file *file, loff_t offset, int origin)
+{
+       loff_t ret;
+
+       mutex_lock(&file->f_dentry->d_inode->i_mutex);
+
+       switch (origin) {
+       case 0 /* SEEK_SET */ :
+               if (offset < coreb_size) {
+                       file->f_pos = offset;
+                       ret = file->f_pos;
+               } else
+                       ret = -EINVAL;
+               break;
+       case 1 /* SEEK_CUR */ :
+               if ((offset + file->f_pos) < coreb_size) {
+                       file->f_pos += offset;
+                       ret = file->f_pos;
+               } else
+                       ret = -EINVAL;
+       default:
+               ret = -EINVAL;
+       }
+       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+       return ret;
+}
+
+static int coreb_open(struct inode *inode, struct file *file)
+{
+       spin_lock_irq(&coreb_lock);
+
+       if (coreb_status & COREB_IS_OPEN)
+               goto out_busy;
+
+       coreb_status |= COREB_IS_OPEN;
+
+       spin_unlock_irq(&coreb_lock);
+       return 0;
+
+      out_busy:
+       spin_unlock_irq(&coreb_lock);
+       return -EBUSY;
+}
+
+static int coreb_release(struct inode *inode, struct file *file)
+{
+       spin_lock_irq(&coreb_lock);
+       coreb_status &= ~COREB_IS_OPEN;
+       spin_unlock_irq(&coreb_lock);
+       return 0;
+}
+
+static int coreb_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+       int coreb_index = 0;
+
+       switch (cmd) {
+       case CMD_COREB_INDEX:
+               if (copy_from_user(&coreb_index, (int *)arg, sizeof(int))) {
+                       retval = -EFAULT;
+                       break;
+               }
+
+               spin_lock_irq(&coreb_lock);
+               switch (coreb_index) {
+               case 0:
+                       coreb_base = 0xff600000;
+                       coreb_size = 0x4000;
+                       break;
+               case 1:
+                       coreb_base = 0xff610000;
+                       coreb_size = 0x4000;
+                       break;
+               case 2:
+                       coreb_base = 0xff500000;
+                       coreb_size = 0x8000;
+                       break;
+               case 3:
+                       coreb_base = 0xff400000;
+                       coreb_size = 0x8000;
+                       break;
+               default:
+                       retval = -EINVAL;
+                       break;
+               }
+               spin_unlock_irq(&coreb_lock);
+
+               mutex_lock(&file->f_dentry->d_inode->i_mutex);
+               file->f_pos = 0;
+               mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+               break;
+       case CMD_COREB_START:
+               spin_lock_irq(&coreb_lock);
+               if (coreb_status & COREB_IS_RUNNING) {
+                       retval = -EBUSY;
+                       break;
+               }
+               printk(KERN_INFO "Starting Core B\n");
+               coreb_status |= COREB_IS_RUNNING;
+               bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~0x0020);
+               SSYNC();
+               spin_lock_irq(&coreb_lock);
+               break;
+#if defined(CONFIG_BF561_COREB_RESET)
+       case CMD_COREB_STOP:
+               spin_lock_irq(&coreb_lock);
+               printk(KERN_INFO "Stopping Core B\n");
+               bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() | 0x0020);
+               bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080);
+               coreb_status &= ~COREB_IS_RUNNING;
+               spin_lock_irq(&coreb_lock);
+               break;
+       case CMD_COREB_RESET:
+               printk(KERN_INFO "Resetting Core B\n");
+               bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080);
+               break;
+#endif
+       }
+
+       return retval;
+}
+
+static struct file_operations coreb_fops = {
+       .owner = THIS_MODULE,
+       .llseek = coreb_lseek,
+       .read = coreb_read,
+       .write = coreb_write,
+       .ioctl = coreb_ioctl,
+       .open = coreb_open,
+       .release = coreb_release
+};
+
+static struct miscdevice coreb_dev = {
+       COREB_MINOR,
+       "coreb",
+       &coreb_fops
+};
+
+static ssize_t coreb_show_status(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf,
+                      "Base Address:\t0x%08lx\n"
+                      "Core B is %s\n"
+                      "SICA_SYSCR:\t%04x\n"
+                      "SICB_SYSCR:\t%04x\n"
+                      "\n"
+                      "IRQ Status:\tCore A\t\tCore B\n"
+                      "ISR0:\t\t%08x\t\t%08x\n"
+                      "ISR1:\t\t%08x\t\t%08x\n"
+                      "IMASK0:\t\t%08x\t\t%08x\n"
+                      "IMASK1:\t\t%08x\t\t%08x\n",
+                      coreb_base,
+                      coreb_status & COREB_IS_RUNNING ? "running" : "stalled",
+                      bfin_read_SICA_SYSCR(), bfin_read_SICB_SYSCR(),
+                      bfin_read_SICA_ISR0(), bfin_read_SICB_ISR0(),
+                      bfin_read_SICA_ISR1(), bfin_read_SICB_ISR0(),
+                      bfin_read_SICA_IMASK0(), bfin_read_SICB_IMASK0(),
+                      bfin_read_SICA_IMASK1(), bfin_read_SICB_IMASK1());
+}
+
+static DEVICE_ATTR(coreb_status, S_IRUGO, coreb_show_status, NULL);
+
+int __init bf561_coreb_init(void)
+{
+       init_waitqueue_head(&coreb_dma_wait);
+
+       spin_lock_init(&coreb_lock);
+       /* Request the core memory regions for Core B */
+       if (request_mem_region(0xff600000, 0x4000,
+                              "Core B - Instruction SRAM") == NULL)
+               goto exit;
+
+       if (request_mem_region(0xFF610000, 0x4000,
+                              "Core B - Instruction SRAM") == NULL)
+               goto release_instruction_a_sram;
+
+       if (request_mem_region(0xFF500000, 0x8000,
+                              "Core B - Data Bank B SRAM") == NULL)
+               goto release_instruction_b_sram;
+
+       if (request_mem_region(0xff400000, 0x8000,
+                              "Core B - Data Bank A SRAM") == NULL)
+               goto release_data_b_sram;
+
+       if (request_dma(CH_MEM_STREAM2_DEST, "Core B - DMA Destination") < 0)
+               goto release_data_a_sram;
+
+       if (request_dma(CH_MEM_STREAM2_SRC, "Core B - DMA Source") < 0)
+               goto release_dma_dest;
+
+       set_dma_callback(CH_MEM_STREAM2_DEST, coreb_dma_interrupt, NULL);
+
+       misc_register(&coreb_dev);
+
+       if (device_create_file(coreb_dev.this_device, &dev_attr_coreb_status))
+               goto release_dma_src;
+
+       printk(KERN_INFO "BF561 Core B driver %s initialized.\n", MODULE_VER);
+       return 0;
+
+      release_dma_src:
+       free_dma(CH_MEM_STREAM2_SRC);
+      release_dma_dest:
+       free_dma(CH_MEM_STREAM2_DEST);
+      release_data_a_sram:
+       release_mem_region(0xff400000, 0x8000);
+      release_data_b_sram:
+       release_mem_region(0xff500000, 0x8000);
+      release_instruction_b_sram:
+       release_mem_region(0xff610000, 0x4000);
+      release_instruction_a_sram:
+       release_mem_region(0xff600000, 0x4000);
+      exit:
+       return -ENOMEM;
+}
+
+void __exit bf561_coreb_exit(void)
+{
+       device_remove_file(coreb_dev.this_device, &dev_attr_coreb_status);
+       misc_deregister(&coreb_dev);
+
+       release_mem_region(0xff610000, 0x4000);
+       release_mem_region(0xff600000, 0x4000);
+       release_mem_region(0xff500000, 0x8000);
+       release_mem_region(0xff400000, 0x8000);
+
+       free_dma(CH_MEM_STREAM2_DEST);
+       free_dma(CH_MEM_STREAM2_SRC);
+}
+
+module_init(bf561_coreb_init);
+module_exit(bf561_coreb_exit);
+
+MODULE_AUTHOR("Bas Vermeulen <bvermeul@blackstar.xs4all.nl>");
+MODULE_DESCRIPTION("BF561 Core B Support");
diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
new file mode 100644 (file)
index 0000000..7bca478
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * File:         arch/blackfin/mach-bf561/head.S
+ * Based on:     arch/blackfin/mach-bf533/head.S
+ * Author:
+ *
+ * Created:
+ * Description:  BF561 startup file
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach/mem_init.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK  0xFFB01000
+
+.text
+
+ENTRY(__start)
+ENTRY(__stext)
+       /*  R0: argument of command line string, passed from uboot, save it */
+       R7 = R0;
+       /* Set the SYSCFG register */
+       R0 = 0x36;
+       SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+       R0 = 0;
+
+       /*Clear Out All the data and pointer  Registers*/
+       R1 = R0;
+       R2 = R0;
+       R3 = R0;
+       R4 = R0;
+       R5 = R0;
+       R6 = R0;
+
+       P0 = R0;
+       P1 = R0;
+       P2 = R0;
+       P3 = R0;
+       P4 = R0;
+       P5 = R0;
+
+       LC0 = r0;
+       LC1 = r0;
+       L0 = r0;
+       L1 = r0;
+       L2 = r0;
+       L3 = r0;
+
+       /* Clear Out All the DAG Registers*/
+       B0 = r0;
+       B1 = r0;
+       B2 = r0;
+       B3 = r0;
+
+       I0 = r0;
+       I1 = r0;
+       I2 = r0;
+       I3 = r0;
+
+       M0 = r0;
+       M1 = r0;
+       M2 = r0;
+       M3 = r0;
+
+       /* Turn off the icache */
+       p0.l = (IMEM_CONTROL & 0xFFFF);
+       p0.h = (IMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENICPLB;
+       R0 = R0 & R1;
+
+       /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+       CLI R2;
+       SSYNC;
+#endif
+       [p0] = R0;
+       SSYNC;
+#ifdef ANOMALY_05000125
+       STI R2;
+#endif
+
+       /* Turn off the dcache */
+       p0.l = (DMEM_CONTROL & 0xFFFF);
+       p0.h = (DMEM_CONTROL >> 16);
+       R1 = [p0];
+       R0 = ~ENDCPLB;
+       R0 = R0 & R1;
+
+       /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+       CLI R2;
+       SSYNC;
+#endif
+       [p0] = R0;
+       SSYNC;
+#ifdef ANOMALY_05000125
+       STI R2;
+#endif
+
+       /* Initialise UART*/
+       p0.h = hi(UART_LCR);
+       p0.l = lo(UART_LCR);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable DLL writes */
+       ssync;
+
+       p0.h = hi(UART_DLL);
+       p0.l = lo(UART_DLL);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_DLH);
+       p0.l = lo(UART_DLH);
+       r0 = 0x00(Z);
+       w[p0] = r0.L;
+       ssync;
+
+       p0.h = hi(UART_GCTL);
+       p0.l = lo(UART_GCTL);
+       r0 = 0x0(Z);
+       w[p0] = r0.L;   /* To enable UART clock */
+       ssync;
+
+       /* Initialize stack pointer */
+       sp.l = lo(INITIAL_STACK);
+       sp.h = hi(INITIAL_STACK);
+       fp = sp;
+       usp = sp;
+
+       /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+       call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+       call _start_dma_code;
+#endif
+
+       /* Code for initializing Async memory banks */
+
+       p2.h = hi(EBIU_AMBCTL1);
+       p2.l = lo(EBIU_AMBCTL1);
+       r0.h = hi(AMBCTL1VAL);
+       r0.l = lo(AMBCTL1VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMBCTL0);
+       p2.l = lo(EBIU_AMBCTL0);
+       r0.h = hi(AMBCTL0VAL);
+       r0.l = lo(AMBCTL0VAL);
+       [p2] = r0;
+       ssync;
+
+       p2.h = hi(EBIU_AMGCTL);
+       p2.l = lo(EBIU_AMGCTL);
+       r0 = AMGCTLVAL;
+       w[p2] = r0;
+       ssync;
+
+       /* This section keeps the processor in supervisor mode
+        * during kernel boot.  Switches to user mode at end of boot.
+        * See page 3-9 of Hardware Reference manual for documentation.
+        */
+
+       /* EVT15 = _real_start */
+
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _real_start;
+       p1.h = _real_start;
+       [p0] = p1;
+       csync;
+
+       p0.l = lo(IMASK);
+       p0.h = hi(IMASK);
+       p1.l = IMASK_IVG15;
+       p1.h = 0x0;
+       [p0] = p1;
+       csync;
+
+       raise 15;
+       p0.l = .LWAIT_HERE;
+       p0.h = .LWAIT_HERE;
+       reti = p0;
+#if defined(ANOMALY_05000281)
+       nop; nop; nop;
+#endif
+       rti;
+
+.LWAIT_HERE:
+       jump .LWAIT_HERE;
+
+ENTRY(_real_start)
+       [ -- sp ] = reti;
+       p0.l = lo(WDOGA_CTL);
+       p0.h = hi(WDOGA_CTL);
+       r0 = 0xAD6(z);
+       w[p0] = r0;     /* watchdog off for now */
+       ssync;
+
+       /* Code update for BSS size == 0
+        * Zero out the bss region.
+        */
+
+       p1.l = ___bss_start;
+       p1.h = ___bss_start;
+       p2.l = ___bss_stop;
+       p2.h = ___bss_stop;
+       r0 = 0;
+       p2 -= p1;
+       lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+.L_clear_bss:
+       B[p1++] = r0;
+
+       /* In case there is a NULL pointer reference
+        * Zero out region before stext
+        */
+
+       p1.l = 0x0;
+       p1.h = 0x0;
+       r0.l = __stext;
+       r0.h = __stext;
+       r0 = r0 >> 1;
+       p2 = r0;
+       r0 = 0;
+       lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+.L_clear_zero:
+       W[p1++] = r0;
+
+/* pass the uboot arguments to the global value command line */
+       R0 = R7;
+       call _cmdline_init;
+
+       p1.l = __rambase;
+       p1.h = __rambase;
+       r0.l = __sdata;
+       r0.h = __sdata;
+       [p1] = r0;
+
+       p1.l = __ramstart;
+       p1.h = __ramstart;
+       p3.l = ___bss_stop;
+       p3.h = ___bss_stop;
+
+       r1 = p3;
+       [p1] = r1;
+
+       /*
+        * load the current thread pointer and stack
+        */
+       r1.l = _init_thread_union;
+       r1.h = _init_thread_union;
+
+       r2.l = 0x2000;
+       r2.h = 0x0000;
+       r1 = r1 + r2;
+       sp = r1;
+       usp = sp;
+       fp = sp;
+       call _start_kernel;
+.L_exit:
+       jump.s  .L_exit;
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+       p0.h = hi(SICA_IWR0);
+       p0.l = lo(SICA_IWR0);
+       r0.l = 0x1;
+       [p0] = r0;
+       SSYNC;
+
+       /*
+        *  Set PLL_CTL
+        *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+        *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
+        *   - [7]     = output delay (add 200ps of delay to mem signals)
+        *   - [6]     = input delay (add 200ps of input delay to mem signals)
+        *   - [5]     = PDWN      : 1=All Clocks off
+        *   - [3]     = STOPCK    : 1=Core Clock off
+        *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
+        *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+        *   all other bits set to zero
+        */
+
+       p0.h = hi(PLL_LOCKCNT);
+       p0.l = lo(PLL_LOCKCNT);
+       r0 = 0x300(Z);
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITSET (R0, 24);
+       [P2] = R0;
+       SSYNC;
+
+       r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
+       r0 = r0 << 9;                    /* Shift it over,                  */
+       r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
+       r0 = r1 | r0;
+       r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
+       r1 = r1 << 8;                    /* Shift it over                   */
+       r0 = r1 | r0;                    /* add them all together           */
+
+       p0.h = hi(PLL_CTL);
+       p0.l = lo(PLL_CTL);              /* Load the address                */
+       cli r2;                          /* Disable interrupts              */
+       ssync;
+       w[p0] = r0.l;                    /* Set the value                   */
+       idle;                            /* Wait for the PLL to stablize    */
+       sti r2;                          /* Enable interrupts               */
+
+.Lcheck_again:
+       p0.h = hi(PLL_STAT);
+       p0.l = lo(PLL_STAT);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,5);
+       if ! CC jump .Lcheck_again;
+
+       /* Configure SCLK & CCLK Dividers */
+               r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+       p0.h = hi(PLL_DIV);
+       p0.l = lo(PLL_DIV);
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = lo(EBIU_SDRRC);
+       p0.h = hi(EBIU_SDRRC);
+       r0 = mem_SDRRC;
+       w[p0] = r0.l;
+       ssync;
+
+       p0.l = (EBIU_SDBCTL & 0xFFFF);
+       p0.h = (EBIU_SDBCTL >> 16);     /* SDRAM Memory Bank Control Register */
+       r0 = mem_SDBCTL;
+       w[p0] = r0.l;
+       ssync;
+
+       P2.H = hi(EBIU_SDGCTL);
+       P2.L = lo(EBIU_SDGCTL);
+       R0 = [P2];
+       BITCLR (R0, 24);
+       p0.h = hi(EBIU_SDSTAT);
+       p0.l = lo(EBIU_SDSTAT);
+       r2.l = w[p0];
+       cc = bittst(r2,3);
+       if !cc jump .Lskip;
+       NOP;
+       BITSET (R0, 23);
+.Lskip:
+       [P2] = R0;
+       SSYNC;
+
+       R0.L = lo(mem_SDGCTL);
+       R0.H = hi(mem_SDGCTL);
+       R1 = [p2];
+       R1 = R1 | R0;
+       [P2] = R1;
+       SSYNC;
+
+       RTS;
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+ENTRY(_bfin_reset)
+       /* No more interrupts to be handled*/
+       CLI R6;
+       SSYNC;
+
+#if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
+       p0.h = hi(FIO_INEN);
+       p0.l = lo(FIO_INEN);
+       r0.l = ~(PF1 | PF0);
+       w[p0] = r0.l;
+
+       p0.h = hi(FIO_DIR);
+       p0.l = lo(FIO_DIR);
+       r0.l = (PF1 | PF0);
+       w[p0] = r0.l;
+
+       p0.h = hi(FIO_FLAG_C);
+       p0.l = lo(FIO_FLAG_C);
+       r0.l = (PF1 | PF0);
+       w[p0] = r0.l;
+#endif
+
+       /* Clear the bits 13-15 in SWRST if they werent cleared */
+       p0.h = hi(SICA_SWRST);
+       p0.l = lo(SICA_SWRST);
+       csync;
+       r0.l = w[p0];
+
+       /* Clear the IMASK register */
+       p0.h = hi(IMASK);
+       p0.l = lo(IMASK);
+       r0 = 0x0;
+       [p0] = r0;
+
+       /* Clear the ILAT register */
+       p0.h = hi(ILAT);
+       p0.l = lo(ILAT);
+       r0 = [p0];
+       [p0] = r0;
+       SSYNC;
+
+       /* Disable the WDOG TIMER */
+       p0.h = hi(WDOGA_CTL);
+       p0.l = lo(WDOGA_CTL);
+       r0.l = 0xAD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Clear the sticky bit incase it is already set */
+       p0.h = hi(WDOGA_CTL);
+       p0.l = lo(WDOGA_CTL);
+       r0.l = 0x8AD6;
+       w[p0] = r0.l;
+       SSYNC;
+
+       /* Program the count value */
+       R0.l = 0x100;
+       R0.h = 0x0;
+       P0.h = hi(WDOGA_CNT);
+       P0.l = lo(WDOGA_CNT);
+       [P0] = R0;
+       SSYNC;
+
+       /* Program WDOG_STAT if necessary */
+       P0.h = hi(WDOGA_CTL);
+       P0.l = lo(WDOGA_CTL);
+       R0 = W[P0](Z);
+       CC = BITTST(R0,1);
+       if !CC JUMP .LWRITESTAT;
+       CC = BITTST(R0,2);
+       if !CC JUMP .LWRITESTAT;
+       JUMP .LSKIP_WRITE;
+
+.LWRITESTAT:
+       /* When watch dog timer is enabled,
+        * a write to STAT will load the contents of CNT to STAT
+        */
+       R0 = 0x0000(z);
+       P0.h = hi(WDOGA_STAT);
+       P0.l = lo(WDOGA_STAT)
+       [P0] = R0;
+       SSYNC;
+
+.LSKIP_WRITE:
+       /* Enable the reset event */
+       P0.h = hi(WDOGA_CTL);
+       P0.l = lo(WDOGA_CTL);
+       R0 = W[P0](Z);
+       BITCLR(R0,1);
+       BITCLR(R0,2);
+       W[P0] = R0.L;
+       SSYNC;
+       NOP;
+
+       /* Enable the wdog counter */
+       R0 = W[P0](Z);
+       BITCLR(R0,4);
+       W[P0] = R0.L;
+       SSYNC;
+
+       IDLE;
+
+       RTS;
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long   0
+__ramstart:
+.long   0
+__ramend:
+.long   0
diff --git a/arch/blackfin/mach-bf561/ints-priority.c b/arch/blackfin/mach-bf561/ints-priority.c
new file mode 100644 (file)
index 0000000..89c52ff
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * File:         arch/blackfin/mach-bf561/ints-priority.c
+ * Based on:     arch/blackfin/mach-bf537/ints-priority.c
+ * Author:       Michael Hennerich
+ *
+ * Created:
+ * Description:  Set up the interupt priorities
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+
+void program_IAR(void)
+{
+       /* Program the IAR0 Register with the configured priority */
+       bfin_write_SICA_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+                            ((CONFIG_IRQ_DMA1_ERROR - 7) << IRQ_DMA1_ERROR_POS) |
+                            ((CONFIG_IRQ_DMA2_ERROR - 7) << IRQ_DMA2_ERROR_POS) |
+                            ((CONFIG_IRQ_IMDMA_ERROR - 7) << IRQ_IMDMA_ERROR_POS) |
+                            ((CONFIG_IRQ_PPI0_ERROR - 7) << IRQ_PPI0_ERROR_POS) |
+                            ((CONFIG_IRQ_PPI1_ERROR - 7) << IRQ_PPI1_ERROR_POS) |
+                            ((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |
+                            ((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS));
+
+       bfin_write_SICA_IAR1(((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS) |
+                            ((CONFIG_IRQ_UART_ERROR - 7) << IRQ_UART_ERROR_POS) |
+                            ((CONFIG_IRQ_RESERVED_ERROR - 7) << IRQ_RESERVED_ERROR_POS) |
+                            ((CONFIG_IRQ_DMA1_0 - 7) << IRQ_DMA1_0_POS) |
+                            ((CONFIG_IRQ_DMA1_1 - 7) << IRQ_DMA1_1_POS) |
+                            ((CONFIG_IRQ_DMA1_2 - 7) << IRQ_DMA1_2_POS) |
+                            ((CONFIG_IRQ_DMA1_3 - 7) << IRQ_DMA1_3_POS) |
+                            ((CONFIG_IRQ_DMA1_4 - 7) << IRQ_DMA1_4_POS));
+
+       bfin_write_SICA_IAR2(((CONFIG_IRQ_DMA1_5 - 7) << IRQ_DMA1_5_POS) |
+                            ((CONFIG_IRQ_DMA1_6 - 7) << IRQ_DMA1_6_POS) |
+                            ((CONFIG_IRQ_DMA1_7 - 7) << IRQ_DMA1_7_POS) |
+                            ((CONFIG_IRQ_DMA1_8 - 7) << IRQ_DMA1_8_POS) |
+                            ((CONFIG_IRQ_DMA1_9 - 7) << IRQ_DMA1_9_POS) |
+                            ((CONFIG_IRQ_DMA1_10 - 7) << IRQ_DMA1_10_POS) |
+                            ((CONFIG_IRQ_DMA1_11 - 7) << IRQ_DMA1_11_POS) |
+                            ((CONFIG_IRQ_DMA2_0 - 7) << IRQ_DMA2_0_POS));
+
+       bfin_write_SICA_IAR3(((CONFIG_IRQ_DMA2_1 - 7) << IRQ_DMA2_1_POS) |
+                            ((CONFIG_IRQ_DMA2_2 - 7) << IRQ_DMA2_2_POS) |
+                            ((CONFIG_IRQ_DMA2_3 - 7) << IRQ_DMA2_3_POS) |
+                            ((CONFIG_IRQ_DMA2_4 - 7) << IRQ_DMA2_4_POS) |
+                            ((CONFIG_IRQ_DMA2_5 - 7) << IRQ_DMA2_5_POS) |
+                            ((CONFIG_IRQ_DMA2_6 - 7) << IRQ_DMA2_6_POS) |
+                            ((CONFIG_IRQ_DMA2_7 - 7) << IRQ_DMA2_7_POS) |
+                            ((CONFIG_IRQ_DMA2_8 - 7) << IRQ_DMA2_8_POS));
+
+       bfin_write_SICA_IAR4(((CONFIG_IRQ_DMA2_9 - 7) << IRQ_DMA2_9_POS) |
+                            ((CONFIG_IRQ_DMA2_10 - 7) << IRQ_DMA2_10_POS) |
+                            ((CONFIG_IRQ_DMA2_11 - 7) << IRQ_DMA2_11_POS) |
+                            ((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+                            ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+                            ((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+                            ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+                            ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS));
+
+       bfin_write_SICA_IAR5(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+                            ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+                            ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
+                            ((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |
+                            ((CONFIG_IRQ_TIMER9 - 7) << IRQ_TIMER9_POS) |
+                            ((CONFIG_IRQ_TIMER10 - 7) << IRQ_TIMER10_POS) |
+                            ((CONFIG_IRQ_TIMER11 - 7) << IRQ_TIMER11_POS) |
+                            ((CONFIG_IRQ_PROG0_INTA - 7) << IRQ_PROG0_INTA_POS));
+
+       bfin_write_SICA_IAR6(((CONFIG_IRQ_PROG0_INTB - 7) << IRQ_PROG0_INTB_POS) |
+                            ((CONFIG_IRQ_PROG1_INTA - 7) << IRQ_PROG1_INTA_POS) |
+                            ((CONFIG_IRQ_PROG1_INTB - 7) << IRQ_PROG1_INTB_POS) |
+                            ((CONFIG_IRQ_PROG2_INTA - 7) << IRQ_PROG2_INTA_POS) |
+                            ((CONFIG_IRQ_PROG2_INTB - 7) << IRQ_PROG2_INTB_POS) |
+                            ((CONFIG_IRQ_DMA1_WRRD0 - 7) << IRQ_DMA1_WRRD0_POS) |
+                            ((CONFIG_IRQ_DMA1_WRRD1 - 7) << IRQ_DMA1_WRRD1_POS) |
+                            ((CONFIG_IRQ_DMA2_WRRD0 - 7) << IRQ_DMA2_WRRD0_POS));
+
+       bfin_write_SICA_IAR7(((CONFIG_IRQ_DMA2_WRRD1 - 7) << IRQ_DMA2_WRRD1_POS) |
+                            ((CONFIG_IRQ_IMDMA_WRRD0 - 7) << IRQ_IMDMA_WRRD0_POS) |
+                            ((CONFIG_IRQ_IMDMA_WRRD1 - 7) << IRQ_IMDMA_WRRD1_POS) |
+                            ((CONFIG_IRQ_WDTIMER - 7) << IRQ_WDTIMER_POS) |
+                            (0 << IRQ_RESERVED_1_POS) | (0 << IRQ_RESERVED_2_POS) |
+                            (0 << IRQ_SUPPLE_0_POS) | (0 << IRQ_SUPPLE_1_POS));
+
+       SSYNC();
+}
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
new file mode 100644 (file)
index 0000000..d3a4907
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# arch/blackfin/mach-common/Makefile
+#
+
+obj-y := \
+       cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \
+       interrupt.o lock.o dpmc.o irqpanic.o
+
+obj-$(CONFIG_CPLB_INFO)          += cplbinfo.o
+obj-$(CONFIG_BFIN_SINGLE_CORE)   += ints-priority-sc.o
+obj-$(CONFIG_BFIN_DUAL_CORE)     += ints-priority-dc.o
+obj-$(CONFIG_PM)                 += pm.o
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
new file mode 100644 (file)
index 0000000..bb9446e
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * File:         arch/blackfin/mach-common/cache.S
+ * Based on:
+ * Author:       LG Soft India
+ *
+ * Created:
+ * Description:  cache control support
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/cplb.h>
+#include <asm/entry.h>
+#include <asm/blackfin.h>
+#include <asm/cache.h>
+
+.text
+.align 2
+ENTRY(_cache_invalidate)
+
+       /*
+        * Icache or DcacheA or DcacheB Invalidation
+        * or any combination thereof
+        * R0 has bits
+        * CPLB_ENABLE_ICACHE_P,CPLB_ENABLE_DCACHE_P,CPLB_ENABLE_DCACHE2_P
+        * set as required
+        */
+       [--SP] = R7;
+
+       R7 = R0;
+       CC = BITTST(R7,CPLB_ENABLE_ICACHE_P);
+       IF !CC JUMP .Lno_icache;
+       [--SP] = RETS;
+       CALL _icache_invalidate;
+       RETS = [SP++];
+.Lno_icache:
+       CC = BITTST(R7,CPLB_ENABLE_DCACHE_P);
+       IF !CC JUMP .Lno_dcache_a;
+       R0 = 0;         /* specifies bank A */
+       [--SP] = RETS;
+       CALL _dcache_invalidate;
+       RETS = [SP++];
+.Lno_dcache_a:
+       CC = BITTST(R7,CPLB_ENABLE_DCACHE2_P);
+       IF !CC JUMP .Lno_dcache_b;
+       R0 = 0;
+       BITSET(R0, 23);         /* specifies bank B */
+       [--SP] = RETS;
+       CALL  _dcache_invalidate;
+       RETS = [SP++];
+.Lno_dcache_b:
+       R7 = [SP++];
+       RTS;
+
+/* Invalidate the Entire Instruction cache by
+ * disabling IMC bit
+ */
+ENTRY(_icache_invalidate)
+ENTRY(_invalidate_entire_icache)
+       [--SP] = ( R7:5);
+
+       P0.L = (IMEM_CONTROL & 0xFFFF);
+       P0.H = (IMEM_CONTROL >> 16);
+       R7 = [P0];
+
+       /* Clear the IMC bit , All valid bits in the instruction
+        * cache are set to the invalid state
+        */
+       BITCLR(R7,IMC_P);
+       CLI R6;
+       SSYNC;          /* SSYNC required before invalidating cache. */
+       .align 8;
+       [P0] = R7;
+       SSYNC;
+       STI R6;
+
+       /* Configures the instruction cache agian */
+       R6 = (IMC | ENICPLB);
+       R7 = R7 | R6;
+
+       CLI R6;
+       SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+       .align 8;
+       [P0] = R7;
+       SSYNC;
+       STI R6;
+
+       ( R7:5) = [SP++];
+       RTS;
+
+/*
+ * blackfin_cache_flush_range(start, end)
+ * Invalidate all cache lines assocoiated with this
+ * area of memory.
+ *
+ * start:      Start address
+ * end:                End address
+ */
+ENTRY(_blackfin_icache_flush_range)
+       R2 = -L1_CACHE_BYTES;
+       R2 = R0 & R2;
+       P0 = R2;
+       P1 = R1;
+       CSYNC;
+       IFLUSH [P0];
+1:
+       IFLUSH [P0++];
+       CC = P0 < P1 (iu);
+       IF CC JUMP 1b (bp);
+       IFLUSH [P0];
+       SSYNC;
+       RTS;
+
+/*
+ * blackfin_icache_dcache_flush_range(start, end)
+ * FLUSH all cache lines assocoiated with this
+ * area of memory.
+ *
+ * start:      Start address
+ * end:                End address
+ */
+
+ENTRY(_blackfin_icache_dcache_flush_range)
+       R2 = -L1_CACHE_BYTES;
+       R2 = R0 & R2;
+       P0 = R2;
+       P1 = R1;
+       CSYNC;
+       IFLUSH [P0];
+1:
+       FLUSH [P0];
+       IFLUSH [P0++];
+       CC = P0 < P1 (iu);
+       IF CC JUMP 1b (bp);
+       IFLUSH [P0];
+       FLUSH [P0];
+       SSYNC;
+       RTS;
+
+/* Throw away all D-cached data in specified region without any obligation to
+ * write them back. However, we must clean the D-cached entries around the
+ * boundaries of the start and/or end address is not cache aligned.
+ *
+ * Start: start address,
+ * end  : end address.
+ */
+
+ENTRY(_blackfin_dcache_invalidate_range)
+       R2 = -L1_CACHE_BYTES;
+       R2 = R0 & R2;
+       P0 = R2;
+       P1 = R1;
+       CSYNC;
+       FLUSHINV[P0];
+1:
+       FLUSHINV[P0++];
+       CC = P0 < P1 (iu);
+       IF CC JUMP 1b (bp);
+
+       /* If the data crosses a cache line, then we'll be pointing to
+        * the last cache line, but won't have flushed/invalidated it yet,
+        * so do one more.
+        */
+       FLUSHINV[P0];
+       SSYNC;
+       RTS;
+
+/* Invalidate the Entire Data cache by
+ * clearing DMC[1:0] bits
+ */
+ENTRY(_invalidate_entire_dcache)
+ENTRY(_dcache_invalidate)
+       [--SP] = ( R7:6);
+
+       P0.L = (DMEM_CONTROL & 0xFFFF);
+       P0.H = (DMEM_CONTROL >> 16);
+       R7 = [P0];
+
+       /* Clear the DMC[1:0] bits, All valid bits in the data
+        * cache are set to the invalid state
+        */
+       BITCLR(R7,DMC0_P);
+       BITCLR(R7,DMC1_P);
+       CLI R6;
+       SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+       .align 8;
+       [P0] = R7;
+       SSYNC;
+       STI R6;
+
+       /* Configures the data cache again */
+
+       R6 = DMEM_CNTR;
+       R7 = R7 | R6;
+
+       CLI R6;
+       SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+       .align 8;
+       [P0] = R7;
+       SSYNC;
+       STI R6;
+
+       ( R7:6) = [SP++];
+       RTS;
+
+ENTRY(_blackfin_dcache_flush_range)
+       R2 = -L1_CACHE_BYTES;
+       R2 = R0 & R2;
+       P0 = R2;
+       P1 = R1;
+       CSYNC;
+       FLUSH[P0];
+1:
+       FLUSH[P0++];
+       CC = P0 < P1 (iu);
+       IF CC JUMP 1b (bp);
+
+       /* If the data crosses a cache line, then we'll be pointing to
+        * the last cache line, but won't have flushed it yet, so do
+        * one more.
+        */
+       FLUSH[P0];
+       SSYNC;
+       RTS;
+
+ENTRY(_blackfin_dflush_page)
+       P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
+       P0 = R0;
+       CSYNC;
+       FLUSH[P0];
+       LSETUP (.Lfl1, .Lfl1) LC0 = P1;
+.Lfl1: FLUSH [P0++];
+       SSYNC;
+       RTS;
diff --git a/arch/blackfin/mach-common/cacheinit.S b/arch/blackfin/mach-common/cacheinit.S
new file mode 100644 (file)
index 0000000..8c17f09
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * File:         arch/blackfin/mach-common/cacheinit.S
+ * Based on:
+ * Author:       LG Soft India
+ *
+ * Created:      ?
+ * Description:  cache initialization
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* This function sets up the data and instruction cache. The
+ * tables like icplb table, dcplb table and Page Descriptor table
+ * are defined in cplbtab.h. You can configure those tables for
+ * your suitable requirements
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+.text
+
+#if defined(CONFIG_BLKFIN_CACHE)
+ENTRY(_bfin_icache_init)
+
+       /* Initialize Instruction CPLBS */
+
+       I0.L = (ICPLB_ADDR0 & 0xFFFF);
+       I0.H = (ICPLB_ADDR0 >> 16);
+
+       I1.L = (ICPLB_DATA0 & 0xFFFF);
+       I1.H = (ICPLB_DATA0 >> 16);
+
+       I2.L = _icplb_table;
+       I2.H = _icplb_table;
+
+       r1 = -1;        /* end point comparison */
+       r3 = 15;        /* max counter */
+
+/* read entries from table */
+
+.Lread_iaddr:
+       R0 = [I2++];
+       CC = R0 == R1;
+       IF CC JUMP .Lidone;
+       [I0++] = R0;
+
+.Lread_idata:
+       R2 = [I2++];
+       [I1++] = R2;
+       R3 = R3 + R1;
+       CC = R3 == R1;
+       IF !CC JUMP .Lread_iaddr;
+
+.Lidone:
+       /* Enable Instruction Cache */
+       P0.l = (IMEM_CONTROL & 0xFFFF);
+       P0.h = (IMEM_CONTROL >> 16);
+       R1 = [P0];
+       R0 = (IMC | ENICPLB);
+       R0 = R0 | R1;
+
+       /* Anomaly 05000125 */
+       CLI R2;
+       SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+       .align 8;
+       [P0] = R0;
+       SSYNC;
+       STI R2;
+       RTS;
+#endif
+
+#if defined(CONFIG_BLKFIN_DCACHE)
+ENTRY(_bfin_dcache_init)
+
+       /* Initialize Data CPLBS */
+
+       I0.L = (DCPLB_ADDR0 & 0xFFFF);
+       I0.H = (DCPLB_ADDR0 >> 16);
+
+       I1.L = (DCPLB_DATA0 & 0xFFFF);
+       I1.H = (DCPLB_DATA0 >> 16);
+
+       I2.L = _dcplb_table;
+       I2.H = _dcplb_table;
+
+       R1 = -1;        /* end point comparison */
+       R3 = 15;        /* max counter */
+
+       /* read entries from table */
+.Lread_daddr:
+       R0 = [I2++];
+       cc = R0 == R1;
+       IF CC JUMP .Lddone;
+       [I0++] = R0;
+
+.Lread_ddata:
+       R2 = [I2++];
+       [I1++] = R2;
+       R3 = R3 + R1;
+       CC = R3 == R1;
+       IF !CC JUMP .Lread_daddr;
+.Lddone:
+       P0.L = (DMEM_CONTROL & 0xFFFF);
+       P0.H = (DMEM_CONTROL >> 16);
+       R1 = [P0];
+
+       R0 = DMEM_CNTR;
+
+       R0 = R0 | R1;
+       /* Anomaly 05000125 */
+       CLI R2;
+       SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+       .align 8;
+       [P0] = R0;
+       SSYNC;
+       STI R2;
+       RTS;
+#endif
diff --git a/arch/blackfin/mach-common/cplbhdlr.S b/arch/blackfin/mach-common/cplbhdlr.S
new file mode 100644 (file)
index 0000000..b979067
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * File:         arch/blackfin/mach-common/cplbhdlr.S
+ * Based on:
+ * Author:       LG Soft India
+ *
+ * Created:      ?
+ * Description:  CPLB exception handler
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/cplb.h>
+#include <asm/entry.h>
+
+#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.type _cplb_mgr, STT_FUNC;
+.type _panic_cplb_error, STT_FUNC;
+
+.align 2
+
+.global __cplb_hdr;
+.type __cplb_hdr, STT_FUNC;
+ENTRY(__cplb_hdr)
+       R2 = SEQSTAT;
+
+       /* Mask the contents of SEQSTAT and leave only EXCAUSE in R2 */
+       R2 <<= 26;
+       R2 >>= 26;
+
+       R1 = 0x23; /* Data access CPLB protection violation */
+       CC = R2 == R1;
+       IF !CC JUMP .Lnot_data_write;
+       R0 = 2;         /* is a write to data space*/
+       JUMP .Lis_icplb_miss;
+
+.Lnot_data_write:
+       R1 = 0x2C; /* CPLB miss on an instruction fetch */
+       CC = R2 == R1;
+       R0 = 0;         /* is_data_miss == False*/
+       IF CC JUMP .Lis_icplb_miss;
+
+       R1 = 0x26;
+       CC = R2 == R1;
+       IF !CC JUMP .Lunknown;
+
+       R0 = 1;         /* is_data_miss == True*/
+
+.Lis_icplb_miss:
+
+#if defined(CONFIG_BLKFIN_CACHE) || defined(CONFIG_BLKFIN_DCACHE)
+# if defined(CONFIG_BLKFIN_CACHE) && !defined(CONFIG_BLKFIN_DCACHE)
+       R1 = CPLB_ENABLE_ICACHE;
+# endif
+# if !defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE)
+       R1 = CPLB_ENABLE_DCACHE;
+# endif
+# if defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE)
+       R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE;
+# endif
+#else
+       R1 = 0;
+#endif
+
+       [--SP] = RETS;
+       CALL _cplb_mgr;
+       RETS = [SP++];
+       CC = R0 == 0;
+       IF !CC JUMP .Lnot_replaced;
+       RTS;
+
+/*
+ * Diagnostic exception handlers
+ */
+.Lunknown:
+       R0 = CPLB_UNKNOWN_ERR;
+       JUMP .Lcplb_error;
+
+.Lnot_replaced:
+       CC = R0 == CPLB_NO_UNLOCKED;
+       IF !CC JUMP .Lnext_check;
+       R0 = CPLB_NO_UNLOCKED;
+       JUMP .Lcplb_error;
+
+.Lnext_check:
+       CC = R0 == CPLB_NO_ADDR_MATCH;
+       IF !CC JUMP .Lnext_check2;
+       R0 = CPLB_NO_ADDR_MATCH;
+       JUMP .Lcplb_error;
+
+.Lnext_check2:
+       CC = R0 == CPLB_PROT_VIOL;
+       IF !CC JUMP .Lstrange_return_from_cplb_mgr;
+       R0 = CPLB_PROT_VIOL;
+       JUMP .Lcplb_error;
+
+.Lstrange_return_from_cplb_mgr:
+       IDLE;
+       CSYNC;
+       JUMP .Lstrange_return_from_cplb_mgr;
+
+.Lcplb_error:
+       R1 = sp;
+       SP += -12;
+       call _panic_cplb_error;
+       SP += 12;
+       JUMP _handle_bad_cplb;
diff --git a/arch/blackfin/mach-common/cplbinfo.c b/arch/blackfin/mach-common/cplbinfo.c
new file mode 100644 (file)
index 0000000..d65fac3
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * File:         arch/blackfin/mach-common/cplbinfo.c
+ * Based on:
+ * Author:       Sonic Zhang <sonic.zhang@analog.com>
+ *
+ * Created:      Jan. 2005
+ * Description:  Display CPLB status
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <asm/cplb.h>
+#include <asm/blackfin.h>
+
+#define CPLB_I 1
+#define CPLB_D 2
+
+#define SYNC_SYS    SSYNC()
+#define SYNC_CORE   CSYNC()
+
+#define CPLB_BIT_PAGESIZE 0x30000
+
+static int page_size_table[4] = {
+       0x00000400,             /* 1K */
+       0x00001000,             /* 4K */
+       0x00100000,             /* 1M */
+       0x00400000              /* 4M */
+};
+
+static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
+
+static int cplb_find_entry(unsigned long *cplb_addr,
+                          unsigned long *cplb_data, unsigned long addr,
+                          unsigned long data)
+{
+       int ii;
+
+       for (ii = 0; ii < 16; ii++)
+               if (addr >= cplb_addr[ii] && addr < cplb_addr[ii] +
+                   page_size_table[(cplb_data[ii] & CPLB_BIT_PAGESIZE) >> 16]
+                       && (cplb_data[ii] == data))
+                       return ii;
+
+       return -1;
+}
+
+static char *cplb_print_entry(char *buf, int type)
+{
+       unsigned long *p_addr = dpdt_table;
+       unsigned long *p_data = dpdt_table + 1;
+       unsigned long *p_icount = dpdt_swapcount_table;
+       unsigned long *p_ocount = dpdt_swapcount_table + 1;
+       unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0;
+       unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0;
+       int entry = 0, used_cplb = 0;
+
+       if (type == CPLB_I) {
+               buf += sprintf(buf, "Instrction CPLB entry:\n");
+               p_addr = ipdt_table;
+               p_data = ipdt_table + 1;
+               p_icount = ipdt_swapcount_table;
+               p_ocount = ipdt_swapcount_table + 1;
+               cplb_addr = (unsigned long *)ICPLB_ADDR0;
+               cplb_data = (unsigned long *)ICPLB_DATA0;
+       } else
+               buf += sprintf(buf, "Data CPLB entry:\n");
+
+       buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\
+\tiCount\toCount\n");
+
+       while (*p_addr != 0xffffffff) {
+               entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data);
+               if (entry >= 0)
+                       used_cplb |= 1 << entry;
+
+               buf +=
+                   sprintf(buf,
+                           "0x%08lx\t0x%05lx\t%s\t%c\t%c\t%2d\t%ld\t%ld\n",
+                           *p_addr, *p_data,
+                           page_size_string_table[(*p_data & 0x30000) >> 16],
+                           (*p_data & CPLB_VALID) ? 'Y' : 'N',
+                           (*p_data & CPLB_LOCK) ? 'Y' : 'N', entry, *p_icount,
+                           *p_ocount);
+
+               p_addr += 2;
+               p_data += 2;
+               p_icount += 2;
+               p_ocount += 2;
+       }
+
+       if (used_cplb != 0xffff) {
+               buf += sprintf(buf, "Unused/mismatched CPLBs:\n");
+
+               for (entry = 0; entry < 16; entry++)
+                       if (0 == ((1 << entry) & used_cplb)) {
+                               int flags = cplb_data[entry];
+                               buf +=
+                                   sprintf(buf,
+                                           "%2d: 0x%08lx\t0x%05x\t%s\t%c\t%c\n",
+                                           entry, cplb_addr[entry], flags,
+                                           page_size_string_table[(flags &
+                                                                   0x30000) >>
+                                                                  16],
+                                           (flags & CPLB_VALID) ? 'Y' : 'N',
+                                           (flags & CPLB_LOCK) ? 'Y' : 'N');
+                       }
+       }
+
+       buf += sprintf(buf, "\n");
+
+       return buf;
+}
+
+static int cplbinfo_proc_output(char *buf)
+{
+       char *p;
+
+       p = buf;
+
+       p += sprintf(p,
+                    "------------------ CPLB Information ------------------\n\n");
+
+       if (bfin_read_IMEM_CONTROL() & ENICPLB)
+               p = cplb_print_entry(p, CPLB_I);
+       else
+               p += sprintf(p, "Instruction CPLB is disabled.\n\n");
+
+       if (bfin_read_DMEM_CONTROL() & ENDCPLB)
+               p = cplb_print_entry(p, CPLB_D);
+       else
+               p += sprintf(p, "Data CPLB is disabled.\n");
+
+       return p - buf;
+}
+
+static int cplbinfo_read_proc(char *page, char **start, off_t off,
+                             int count, int *eof, void *data)
+{
+       int len;
+
+       len = cplbinfo_proc_output(page);
+       if (len <= off + count)
+               *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len > count)
+               len = count;
+       if (len < 0)
+               len = 0;
+       return len;
+}
+
+static int cplbinfo_write_proc(struct file *file, const char __user *buffer,
+                              unsigned long count, void *data)
+{
+       printk(KERN_INFO "Reset the CPLB swap in/out counts.\n");
+       memset(ipdt_swapcount_table, 0, MAX_SWITCH_I_CPLBS * sizeof(unsigned long));
+       memset(dpdt_swapcount_table, 0, MAX_SWITCH_D_CPLBS * sizeof(unsigned long));
+
+       return count;
+}
+
+static int __init cplbinfo_init(void)
+{
+       struct proc_dir_entry *entry;
+
+       if ((entry = create_proc_entry("cplbinfo", 0, NULL)) == NULL) {
+               return -ENOMEM;
+       }
+
+       entry->read_proc = cplbinfo_read_proc;
+       entry->write_proc = cplbinfo_write_proc;
+       entry->data = NULL;
+
+       return 0;
+}
+
+static void __exit cplbinfo_exit(void)
+{
+       remove_proc_entry("cplbinfo", NULL);
+}
+
+module_init(cplbinfo_init);
+module_exit(cplbinfo_exit);
diff --git a/arch/blackfin/mach-common/cplbmgr.S b/arch/blackfin/mach-common/cplbmgr.S
new file mode 100644 (file)
index 0000000..f5efc4b
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * File:         arch/blackfin/mach-common/cplbmgtr.S
+ * Based on:
+ * Author:       LG Soft India
+ *
+ * Created:      ?
+ * Description:  CPLB replacement routine for CPLB mismatch
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* Usage: int _cplb_mgr(is_data_miss,int enable_cache)
+ * is_data_miss==2 => Mark as Dirty, write to the clean data page
+ * is_data_miss==1 => Replace a data CPLB.
+ * is_data_miss==0 => Replace an instruction CPLB.
+ *
+ * Returns:
+ * CPLB_RELOADED       => Successfully updated CPLB table.
+ * CPLB_NO_UNLOCKED    => All CPLBs are locked, so cannot be evicted.
+ *                        This indicates that the CPLBs in the configuration
+ *                        tablei are badly configured, as this should never
+ *                        occur.
+ * CPLB_NO_ADDR_MATCH  => The address being accessed, that triggered the
+ *                        exception, is not covered by any of the CPLBs in
+ *                        the configuration table. The application is
+ *                        presumably misbehaving.
+ * CPLB_PROT_VIOL      => The address being accessed, that triggered the
+ *                        exception, was not a first-write to a clean Write
+ *                        Back Data page, and so presumably is a genuine
+ *                        violation of the page's protection attributes.
+ *                        The application is misbehaving.
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/cplb.h>
+
+#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2;
+ENTRY(_cplb_mgr)
+
+       [--SP]=( R7:4,P5:3 );
+
+       CC = R0 == 2;
+       IF CC JUMP .Ldcplb_write;
+
+       CC = R0 == 0;
+       IF !CC JUMP .Ldcplb_miss_compare;
+
+       /* ICPLB Miss Exception. We need to choose one of the
+       * currently-installed CPLBs, and replace it with one
+       * from the configuration table.
+       */
+
+       P4.L = (ICPLB_FAULT_ADDR & 0xFFFF);
+       P4.H = (ICPLB_FAULT_ADDR >> 16);
+
+       P1 = 16;
+       P5.L = _page_size_table;
+       P5.H = _page_size_table;
+
+       P0.L = (ICPLB_DATA0 & 0xFFFF);
+       P0.H = (ICPLB_DATA0 >> 16);
+       R4 = [P4];              /* Get faulting address*/
+       R6 = 64;                /* Advance past the fault address, which*/
+       R6 = R6 + R4;           /* we'll use if we find a match*/
+       R3 = ((16 << 8) | 2);   /* Extract mask, bits 16 and 17.*/
+
+       R5 = 0;
+.Lisearch:
+
+       R1 = [P0-0x100];        /* Address for this CPLB */
+
+       R0 = [P0++];            /* Info for this CPLB*/
+       CC = BITTST(R0,0);      /* Is the CPLB valid?*/
+       IF !CC JUMP .Lnomatch;  /* Skip it, if not.*/
+       CC = R4 < R1(IU);       /* If fault address less than page start*/
+       IF CC JUMP .Lnomatch;   /* then skip this one.*/
+       R2 = EXTRACT(R0,R3.L) (Z);      /* Get page size*/
+       P1 = R2;
+       P1 = P5 + (P1<<2);      /* index into page-size table*/
+       R2 = [P1];              /* Get the page size*/
+       R1 = R1 + R2;           /* and add to page start, to get page end*/
+       CC = R4 < R1(IU);       /* and see whether fault addr is in page.*/
+       IF !CC R4 = R6;         /* If so, advance the address and finish loop.*/
+       IF !CC JUMP .Lisearch_done;
+.Lnomatch:
+       /* Go around again*/
+       R5 += 1;
+       CC = BITTST(R5, 4);     /* i.e CC = R5 >= 16*/
+       IF !CC JUMP .Lisearch;
+
+.Lisearch_done:
+       I0 = R4;                /* Fault address we'll search for*/
+
+       /* set up pointers */
+       P0.L = (ICPLB_DATA0 & 0xFFFF);
+       P0.H = (ICPLB_DATA0 >> 16);
+
+       /* The replacement procedure for ICPLBs */
+
+       P4.L = (IMEM_CONTROL & 0xFFFF);
+       P4.H = (IMEM_CONTROL >> 16);
+
+       /* disable cplbs */
+       R5 = [P4];              /* Control Register*/
+       BITCLR(R5,ENICPLB_P);
+       CLI R1;
+       SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+       STI R1;
+
+       R1 = -1;                /* end point comparison */
+       R3 = 16;                /* counter */
+
+       /* Search through CPLBs for first non-locked entry */
+       /* Overwrite it by moving everyone else up by 1 */
+.Licheck_lock:
+       R0 = [P0++];
+       R3 = R3 + R1;
+       CC = R3 == R1;
+       IF CC JUMP .Lall_locked;
+       CC = BITTST(R0, 0);             /* an invalid entry is good */
+       IF !CC JUMP .Lifound_victim;
+       CC = BITTST(R0,1);              /* but a locked entry isn't */
+       IF CC JUMP .Licheck_lock;
+
+.Lifound_victim:
+#ifdef CONFIG_CPLB_INFO
+       R7 = [P0 - 0x104];
+       P2.L = _ipdt_table;
+       P2.H = _ipdt_table;
+       P3.L = _ipdt_swapcount_table;
+       P3.H = _ipdt_swapcount_table;
+       P3 += -4;
+.Licount:
+       R2 = [P2];      /* address from config table */
+       P2 += 8;
+       P3 += 8;
+       CC = R2==-1;
+       IF CC JUMP .Licount_done;
+       CC = R7==R2;
+       IF !CC JUMP .Licount;
+       R7 = [P3];
+       R7 += 1;
+       [P3] = R7;
+       CSYNC;
+.Licount_done:
+#endif
+       LC0=R3;
+       LSETUP(.Lis_move,.Lie_move) LC0;
+.Lis_move:
+       R0 = [P0];
+       [P0 - 4] = R0;
+       R0 = [P0 - 0x100];
+       [P0-0x104] = R0;
+.Lie_move:P0+=4;
+
+       /* We've made space in the ICPLB table, so that ICPLB15
+        * is now free to be overwritten. Next, we have to determine
+        * which CPLB we need to install, from the configuration
+        * table. This is a matter of getting the start-of-page
+        * addresses and page-lengths from the config table, and
+        * determining whether the fault address falls within that
+        * range.
+        */
+
+       P2.L = _ipdt_table;
+       P2.H = _ipdt_table;
+#ifdef CONFIG_CPLB_INFO
+       P3.L = _ipdt_swapcount_table;
+       P3.H = _ipdt_swapcount_table;
+       P3 += -8;
+#endif
+       P0.L = _page_size_table;
+       P0.H = _page_size_table;
+
+       /* Retrieve our fault address (which may have been advanced
+        * because the faulting instruction crossed a page boundary).
+        */
+
+       R0 = I0;
+
+       /* An extraction pattern, to get the page-size bits from
+        * the CPLB data entry. Bits 16-17, so two bits at posn 16.
+        */
+
+       R1 = ((16<<8)|2);
+.Linext:       R4 = [P2++];    /* address from config table */
+       R2 = [P2++];    /* data from config table */
+#ifdef CONFIG_CPLB_INFO
+       P3 += 8;
+#endif
+
+       CC = R4 == -1;  /* End of config table*/
+       IF CC JUMP .Lno_page_in_table;
+
+       /* See if failed address > start address */
+       CC = R4 <= R0(IU);
+       IF !CC JUMP .Linext;
+
+       /* extract page size (17:16)*/
+       R3 = EXTRACT(R2, R1.L) (Z);
+
+       /* add page size to addr to get range */
+
+       P5 = R3;
+       P5 = P0 + (P5 << 2);    /* scaled, for int access*/
+       R3 = [P5];
+       R3 = R3 + R4;
+
+       /* See if failed address < (start address + page size) */
+       CC = R0 < R3(IU);
+       IF !CC JUMP .Linext;
+
+       /* We've found a CPLB in the config table that covers
+        * the faulting address, so install this CPLB into the
+        * last entry of the table.
+        */
+
+       P1.L = (ICPLB_DATA15 & 0xFFFF);         /* ICPLB_DATA15 */
+       P1.H = (ICPLB_DATA15 >> 16);
+       [P1] = R2;
+       [P1-0x100] = R4;
+#ifdef CONFIG_CPLB_INFO
+       R3 = [P3];
+       R3 += 1;
+       [P3] = R3;
+#endif
+
+       /* P4 points to IMEM_CONTROL, and R5 contains its old
+        * value, after we disabled ICPLBS. Re-enable them.
+        */
+
+       BITSET(R5,ENICPLB_P);
+       CLI R2;
+       SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+       STI R2;
+
+       ( R7:4,P5:3 ) = [SP++];
+       R0 = CPLB_RELOADED;
+       RTS;
+
+/* FAILED CASES*/
+.Lno_page_in_table:
+       ( R7:4,P5:3 ) = [SP++];
+       R0 = CPLB_NO_ADDR_MATCH;
+       RTS;
+.Lall_locked:
+       ( R7:4,P5:3 ) = [SP++];
+       R0 = CPLB_NO_UNLOCKED;
+       RTS;
+.Lprot_violation:
+       ( R7:4,P5:3 ) = [SP++];
+       R0 = CPLB_PROT_VIOL;
+       RTS;
+
+.Ldcplb_write:
+
+       /* if a DCPLB is marked as write-back (CPLB_WT==0), and
+        * it is clean (CPLB_DIRTY==0), then a write to the
+        * CPLB's page triggers a protection violation. We have to
+        * mark the CPLB as dirty, to indicate that there are
+        * pending writes associated with the CPLB.
+        */
+
+       P4.L = (DCPLB_STATUS & 0xFFFF);
+       P4.H = (DCPLB_STATUS >> 16);
+       P3.L = (DCPLB_DATA0 & 0xFFFF);
+       P3.H = (DCPLB_DATA0 >> 16);
+       R5 = [P4];
+
+       /* A protection violation can be caused by more than just writes
+        * to a clean WB page, so we have to ensure that:
+        * - It's a write
+        * - to a clean WB page
+        * - and is allowed in the mode the access occurred.
+        */
+
+       CC = BITTST(R5, 16);    /* ensure it was a write*/
+       IF !CC JUMP .Lprot_violation;
+
+       /* to check the rest, we have to retrieve the DCPLB.*/
+
+       /* The low half of DCPLB_STATUS is a bit mask*/
+
+       R2 = R5.L (Z);  /* indicating which CPLB triggered the event.*/
+       R3 = 30;        /* so we can use this to determine the offset*/
+       R2.L = SIGNBITS R2;
+       R2 = R2.L (Z);  /* into the DCPLB table.*/
+       R3 = R3 - R2;
+       P4 = R3;
+       P3 = P3 + (P4<<2);
+       R3 = [P3];      /* Retrieve the CPLB*/
+
+       /* Now we can check whether it's a clean WB page*/
+
+       CC = BITTST(R3, 14);    /* 0==WB, 1==WT*/
+       IF CC JUMP .Lprot_violation;
+       CC = BITTST(R3, 7);     /* 0 == clean, 1 == dirty*/
+       IF CC JUMP .Lprot_violation;
+
+       /* Check whether the write is allowed in the mode that was active.*/
+
+       R2 = 1<<3;              /* checking write in user mode*/
+       CC = BITTST(R5, 17);    /* 0==was user, 1==was super*/
+       R5 = CC;
+       R2 <<= R5;              /* if was super, check write in super mode*/
+       R2 = R3 & R2;
+       CC = R2 == 0;
+       IF CC JUMP .Lprot_violation;
+
+       /* It's a genuine write-to-clean-page.*/
+
+       BITSET(R3, 7);          /* mark as dirty*/
+       [P3] = R3;              /* and write back.*/
+       NOP;
+       CSYNC;
+       ( R7:4,P5:3 ) = [SP++];
+       R0 = CPLB_RELOADED;
+       RTS;
+
+.Ldcplb_miss_compare:
+
+       /* Data CPLB Miss event. We need to choose a CPLB to
+        * evict, and then locate a new CPLB to install from the
+        * config table, that covers the faulting address.
+        */
+
+       P1.L = (DCPLB_DATA15 & 0xFFFF);
+       P1.H = (DCPLB_DATA15 >> 16);
+
+       P4.L = (DCPLB_FAULT_ADDR & 0xFFFF);
+       P4.H = (DCPLB_FAULT_ADDR >> 16);
+       R4 = [P4];
+       I0 = R4;
+
+       /* The replacement procedure for DCPLBs*/
+
+       R6 = R1;        /* Save for later*/
+
+       /* Turn off CPLBs while we work.*/
+       P4.L = (DMEM_CONTROL & 0xFFFF);
+       P4.H = (DMEM_CONTROL >> 16);
+       R5 = [P4];
+       BITCLR(R5,ENDCPLB_P);
+       CLI R0;
+       SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+       STI R0;
+
+       /* Start looking for a CPLB to evict. Our order of preference
+        * is: invalid CPLBs, clean CPLBs, dirty CPLBs. Locked CPLBs
+        * are no good.
+        */
+
+       I1.L = (DCPLB_DATA0 & 0xFFFF);
+       I1.H = (DCPLB_DATA0 >> 16);
+       P1 = 2;
+       P2 = 16;
+       I2.L = _dcplb_preference;
+       I2.H = _dcplb_preference;
+       LSETUP(.Lsdsearch1, .Ledsearch1) LC0 = P1;
+.Lsdsearch1:
+       R0 = [I2++];            /* Get the bits we're interested in*/
+       P0 = I1;                /* Go back to start of table*/
+       LSETUP (.Lsdsearch2, .Ledsearch2) LC1 = P2;
+.Lsdsearch2:
+       R1 = [P0++];            /* Fetch each installed CPLB in turn*/
+       R2 = R1 & R0;           /* and test for interesting bits.*/
+       CC = R2 == 0;           /* If none are set, it'll do.*/
+       IF !CC JUMP .Lskip_stack_check;
+
+       R2 = [P0 - 0x104];      /* R2 - PageStart */
+       P3.L = _page_size_table; /* retrieve end address */
+       P3.H = _page_size_table; /* retrieve end address */
+       R3 = 0x1002;            /* 16th - position, 2 bits -length */
+#ifdef ANOMALY_05000209
+       nop;                    /* Anomaly 05000209 */
+#endif
+       R7 = EXTRACT(R1,R3.l);
+       R7 = R7 << 2;           /* Page size index offset */
+       P5 = R7;
+       P3 = P3 + P5;
+       R7 = [P3];              /* page size in bytes */
+
+       R7 = R2 + R7;           /* R7 - PageEnd */
+       R4 = SP;                /* Test SP is in range */
+
+       CC = R7 < R4;           /* if PageEnd < SP */
+       IF CC JUMP .Ldfound_victim;
+       R3 = 0x284;             /* stack length from start of trap till
+                                * the point.
+                                * 20 stack locations for future modifications
+                                */
+       R4 = R4 + R3;
+       CC = R4 < R2;           /* if SP + stacklen < PageStart */
+       IF CC JUMP .Ldfound_victim;
+.Lskip_stack_check:
+
+.Ledsearch2: NOP;
+.Ledsearch1: NOP;
+
+       /* If we got here, we didn't find a DCPLB we considered
+        * replacable, which means all of them were locked.
+        */
+
+       JUMP .Lall_locked;
+.Ldfound_victim:
+
+#ifdef CONFIG_CPLB_INFO
+       R7 = [P0 - 0x104];
+       P2.L = _dpdt_table;
+       P2.H = _dpdt_table;
+       P3.L = _dpdt_swapcount_table;
+       P3.H = _dpdt_swapcount_table;
+       P3 += -4;
+.Ldicount:
+       R2 = [P2];
+       P2 += 8;
+       P3 += 8;
+       CC = R2==-1;
+       IF CC JUMP .Ldicount_done;
+       CC = R7==R2;
+       IF !CC JUMP .Ldicount;
+       R7 = [P3];
+       R7 += 1;
+       [P3] = R7;
+.Ldicount_done:
+#endif
+
+       /* Clean down the hardware loops*/
+       R2 = 0;
+       LC1 = R2;
+       LC0 = R2;
+
+       /* There's a suitable victim in [P0-4] (because we've
+        * advanced already).
+        */
+
+.LDdoverwrite:
+
+       /* [P0-4] is a suitable victim CPLB, so we want to
+        * overwrite it by moving all the following CPLBs
+        * one space closer to the start.
+        */
+
+       R1.L = (DCPLB_DATA16 & 0xFFFF);         /* DCPLB_DATA15 + 4 */
+       R1.H = (DCPLB_DATA16 >> 16);
+       R0 = P0;
+
+       /* If the victim happens to be in DCPLB15,
+        * we don't need to move anything.
+        */
+
+       CC = R1 == R0;
+       IF CC JUMP .Lde_moved;
+       R1 = R1 - R0;
+       R1 >>= 2;
+       P1 = R1;
+       LSETUP(.Lds_move, .Lde_move) LC0=P1;
+.Lds_move:
+       R0 = [P0++];    /* move data */
+       [P0 - 8] = R0;
+       R0 = [P0-0x104] /* move address */
+.Lde_move: [P0-0x108] = R0;
+
+       /* We've now made space in DCPLB15 for the new CPLB to be
+        * installed. The next stage is to locate a CPLB in the
+        * config table that covers the faulting address.
+        */
+
+.Lde_moved:NOP;
+       R0 = I0;                /* Our faulting address */
+
+       P2.L = _dpdt_table;
+       P2.H = _dpdt_table;
+#ifdef CONFIG_CPLB_INFO
+       P3.L = _dpdt_swapcount_table;
+       P3.H = _dpdt_swapcount_table;
+       P3 += -8;
+#endif
+
+       P1.L = _page_size_table;
+       P1.H = _page_size_table;
+
+       /* An extraction pattern, to retrieve bits 17:16.*/
+
+       R1 = (16<<8)|2;
+.Ldnext:       R4 = [P2++];    /* address */
+       R2 = [P2++];    /* data */
+#ifdef CONFIG_CPLB_INFO
+       P3 += 8;
+#endif
+
+       CC = R4 == -1;
+       IF CC JUMP .Lno_page_in_table;
+
+       /* See if failed address > start address */
+       CC = R4 <= R0(IU);
+       IF !CC JUMP .Ldnext;
+
+       /* extract page size (17:16)*/
+       R3 = EXTRACT(R2, R1.L) (Z);
+
+       /* add page size to addr to get range */
+
+       P5 = R3;
+       P5 = P1 + (P5 << 2);
+       R3 = [P5];
+       R3 = R3 + R4;
+
+       /* See if failed address < (start address + page size) */
+       CC = R0 < R3(IU);
+       IF !CC JUMP .Ldnext;
+
+       /* We've found the CPLB that should be installed, so
+        * write it into CPLB15, masking off any caching bits
+        * if necessary.
+        */
+
+       P1.L = (DCPLB_DATA15 & 0xFFFF);
+       P1.H = (DCPLB_DATA15 >> 16);
+
+       /* If the DCPLB has cache bits set, but caching hasn't
+        * been enabled, then we want to mask off the cache-in-L1
+        * bit before installing. Moreover, if caching is off, we
+        * also want to ensure that the DCPLB has WT mode set, rather
+        * than WB, since WB pages still trigger first-write exceptions
+        * even when not caching is off, and the page isn't marked as
+        * cachable. Finally, we could mark the page as clean, not dirty,
+        * but we choose to leave that decision to the user; if the user
+        * chooses to have a CPLB pre-defined as dirty, then they always
+        * pay the cost of flushing during eviction, but don't pay the
+        * cost of first-write exceptions to mark the page as dirty.
+        */
+
+#ifdef CONFIG_BLKFIN_WT
+       BITSET(R6, 14);         /* Set WT*/
+#endif
+
+       [P1] = R2;
+       [P1-0x100] = R4;
+#ifdef CONFIG_CPLB_INFO
+       R3 = [P3];
+       R3 += 1;
+       [P3] = R3;
+#endif
+
+       /* We've installed the CPLB, so re-enable CPLBs. P4
+        * points to DMEM_CONTROL, and R5 is the value we
+        * last wrote to it, when we were disabling CPLBs.
+        */
+
+       BITSET(R5,ENDCPLB_P);
+       CLI R2;
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+       STI R2;
+
+       ( R7:4,P5:3 ) = [SP++];
+       R0 = CPLB_RELOADED;
+       RTS;
+
+.data
+.align 4;
+_page_size_table:
+.byte4 0x00000400;     /* 1K */
+.byte4 0x00001000;     /* 4K */
+.byte4 0x00100000;     /* 1M */
+.byte4 0x00400000;     /* 4M */
+
+.align 4;
+_dcplb_preference:
+.byte4 0x00000001;     /* valid bit */
+.byte4 0x00000002;     /* lock bit */
diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S
new file mode 100644 (file)
index 0000000..97cdcd6
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * File:         arch/blackfin/mach-common/dpmc.S
+ * Based on:
+ * Author:       LG Soft India
+ *
+ * Created:      ?
+ * Description:  Watchdog Timer APIs
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/mach/irq.h>
+
+.text
+
+ENTRY(_unmask_wdog_wakeup_evt)
+       [--SP] = ( R7:0, P5:0 );
+#if defined(CONFIG_BF561)
+       P0.H = hi(SICA_IWR1);
+       P0.L = lo(SICA_IWR1);
+#else
+       P0.h = (SIC_IWR >> 16);
+       P0.l = (SIC_IWR & 0xFFFF);
+#endif
+       R7 = [P0];
+#if defined(CONFIG_BF561)
+       BITSET(R7, 27);
+#else
+       BITSET(R7,(IRQ_WATCH - IVG7));
+#endif
+       [P0] = R7;
+       SSYNC;
+
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+.LWRITE_TO_STAT:
+       /* When watch dog timer is enabled, a write to STAT will load the
+        * contents of CNT to STAT
+        */
+       R7 = 0x0000(z);
+#if defined(CONFIG_BF561)
+       P0.h = (WDOGA_STAT >> 16);
+       P0.l = (WDOGA_STAT & 0xFFFF);
+#else
+       P0.h = (WDOG_STAT >> 16);
+       P0.l = (WDOG_STAT & 0xFFFF);
+#endif
+       [P0] = R7;
+       SSYNC;
+       JUMP .LSKIP_WRITE_TO_STAT;
+
+ENTRY(_program_wdog_timer)
+       [--SP] = ( R7:0, P5:0 );
+#if defined(CONFIG_BF561)
+       P0.h = (WDOGA_CNT >> 16);
+       P0.l = (WDOGA_CNT & 0xFFFF);
+#else
+       P0.h = (WDOG_CNT >> 16);
+       P0.l = (WDOG_CNT & 0xFFFF);
+#endif
+       [P0] = R0;
+       SSYNC;
+
+#if defined(CONFIG_BF561)
+       P0.h = (WDOGA_CTL >> 16);
+       P0.l = (WDOGA_CTL & 0xFFFF);
+#else
+       P0.h = (WDOG_CTL >> 16);
+       P0.l = (WDOG_CTL & 0xFFFF);
+#endif
+       R7 = W[P0](Z);
+       CC = BITTST(R7,1);
+       if !CC JUMP .LWRITE_TO_STAT;
+       CC = BITTST(R7,2);
+       if !CC JUMP .LWRITE_TO_STAT;
+
+.LSKIP_WRITE_TO_STAT:
+#if defined(CONFIG_BF561)
+       P0.h = (WDOGA_CTL >> 16);
+           P0.l = (WDOGA_CTL & 0xFFFF);
+#else
+       P0.h = (WDOG_CTL >> 16);
+           P0.l = (WDOG_CTL & 0xFFFF);
+#endif
+       R7 = W[P0](Z);
+       BITCLR(R7,1);   /* Enable GP event */
+       BITSET(R7,2);
+       W[P0] = R7.L;
+       SSYNC;
+       NOP;
+
+       R7 = W[P0](Z);
+       BITCLR(R7,4);   /* Enable the wdog counter */
+       W[P0] = R7.L;
+       SSYNC;
+
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_clear_wdog_wakeup_evt)
+       [--SP] = ( R7:0, P5:0 );
+
+#if defined(CONFIG_BF561)
+       P0.h = (WDOGA_CTL >> 16);
+       P0.l = (WDOGA_CTL & 0xFFFF);
+#else
+       P0.h = (WDOG_CTL >> 16);
+       P0.l = (WDOG_CTL & 0xFFFF);
+#endif
+       R7 = 0x0AD6(Z);
+       W[P0] = R7.L;
+       SSYNC;
+
+       R7 = W[P0](Z);
+       BITSET(R7,15);
+       W[P0] = R7.L;
+       SSYNC;
+
+       R7 = W[P0](Z);
+       BITSET(R7,1);
+       BITSET(R7,2);
+       W[P0] = R7.L;
+       SSYNC;
+
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_disable_wdog_timer)
+       [--SP] = ( R7:0, P5:0 );
+#if defined(CONFIG_BF561)
+       P0.h = (WDOGA_CTL >> 16);
+       P0.l = (WDOGA_CTL & 0xFFFF);
+#else
+       P0.h = (WDOG_CTL >> 16);
+       P0.l = (WDOG_CTL & 0xFFFF);
+#endif
+       R7 = 0xAD6(Z);
+       W[P0] = R7.L;
+       SSYNC;
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+#if !defined(CONFIG_BF561)
+
+.section .l1.text
+
+ENTRY(_sleep_mode)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       call _set_sic_iwr;
+
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R1 = W[P0](z);
+       BITSET (R1, 3);
+       W[P0] = R1.L;
+
+       CLI R2;
+       SSYNC;
+       IDLE;
+       STI R2;
+
+       call _test_pll_locked;
+
+       R0 = IWR_ENABLE(0);
+       call _set_sic_iwr;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R7 = w[p0](z);
+       BITCLR (R7, 3);
+       BITCLR (R7, 5);
+       w[p0] = R7.L;
+       IDLE;
+       call _test_pll_locked;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_hibernate_mode)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       call _set_sic_iwr;
+
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat
+
+       P0.H = hi(VR_CTL);
+       P0.L = lo(VR_CTL);
+       R1 = W[P0](z);
+       BITSET (R1, 8);
+       BITCLR (R1, 0);
+       BITCLR (R1, 1);
+       W[P0] = R1.L;
+       SSYNC;
+
+       CLI R2;
+       IDLE;
+
+       /* Actually, adding anything may not be necessary...SDRAM contents
+        * are lost
+        */
+
+ENTRY(_deep_sleep)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       CLI R4;
+
+       call _set_sic_iwr;
+
+       call _set_sdram_srfs;
+
+       /* Clear all the interrupts,bits sticky */
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R0 = W[P0](z);
+       BITSET (R0, 5);
+       W[P0] = R0.L;
+
+       call _test_pll_locked;
+
+       SSYNC;
+       IDLE;
+
+       call _unset_sdram_srfs;
+
+       call _test_pll_locked;
+
+       R0 = IWR_ENABLE(0);
+       call _set_sic_iwr;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R0 = w[p0](z);
+       BITCLR (R0, 3);
+       BITCLR (R0, 5);
+       BITCLR (R0, 8);
+       w[p0] = R0;
+       IDLE;
+       call _test_pll_locked;
+
+       STI R4;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_sleep_deeper)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       CLI R4;
+
+       P3 = R0;
+       R0 = IWR_ENABLE(0);
+       call _set_sic_iwr;
+       call _set_sdram_srfs;
+
+       /* Clear all the interrupts,bits sticky */
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat
+
+       P0.H = hi(PLL_DIV);
+       P0.L = lo(PLL_DIV);
+       R6 = W[P0](z);
+       R0.L = 0xF;
+       W[P0] = R0.l;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R5 = W[P0](z);
+       R0.L = (MIN_VC/CONFIG_CLKIN_HZ) << 9;
+       W[P0] = R0.l;
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       P0.H = hi(VR_CTL);
+       P0.L = lo(VR_CTL);
+       R7 = W[P0](z);
+       R1 = 0x6;
+       R1 <<= 16;
+       R2 = 0x0404(Z);
+       R1 = R1|R2;
+
+       R2 = DEPOSIT(R7, R1);
+       W[P0] = R2;
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R0 = W[P0](z);
+       BITSET (R0, 3);
+       W[P0] = R0.L;
+
+       R0 = P3;
+       call _set_sic_iwr;
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       R0 = IWR_ENABLE(0);
+       call _set_sic_iwr;
+
+       P0.H = hi(VR_CTL);
+       P0.L = lo(VR_CTL);
+       W[P0]= R7;
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       P0.H = hi(PLL_DIV);
+       P0.L = lo(PLL_DIV);
+       W[P0]= R6;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       w[p0] = R5;
+       IDLE;
+       call _test_pll_locked;
+
+       call _unset_sdram_srfs;
+
+       STI R4;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_set_sdram_srfs)
+       /*  set the sdram to self refresh mode */
+       P0.H = hi(EBIU_SDGCTL);
+       P0.L = lo(EBIU_SDGCTL);
+       R2 = [P0];
+       R3.H = hi(SRFS);
+       R3.L = lo(SRFS);
+       R2 = R2|R3;
+       [P0] = R2;
+       ssync;
+       RTS;
+
+ENTRY(_unset_sdram_srfs)
+       /*  set the sdram out of self refresh mode */
+       P0.H = hi(EBIU_SDGCTL);
+       P0.L = lo(EBIU_SDGCTL);
+       R2 = [P0];
+       R3.H = hi(SRFS);
+       R3.L = lo(SRFS);
+       R3 = ~R3;
+       R2 = R2&R3;
+       [P0] = R2;
+       ssync;
+       RTS;
+
+ENTRY(_set_sic_iwr)
+       P0.H = hi(SIC_IWR);
+       P0.L = lo(SIC_IWR);
+       [P0] = R0;
+       SSYNC;
+       RTS;
+
+ENTRY(_set_rtc_istat)
+       P0.H = hi(RTC_ISTAT);
+       P0.L = lo(RTC_ISTAT);
+       w[P0] = R0.L;
+       SSYNC;
+       RTS;
+
+ENTRY(_test_pll_locked)
+       P0.H = hi(PLL_STAT);
+       P0.L = lo(PLL_STAT);
+1:
+       R0 = W[P0] (Z);
+       CC = BITTST(R0,5);
+       IF !CC JUMP 1b;
+       RTS;
+#endif
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
new file mode 100644 (file)
index 0000000..8eb0a90
--- /dev/null
@@ -0,0 +1,1207 @@
+/*
+ * File:         arch/blackfin/mach-common/entry.S
+ * Based on:
+ * Author:       Linus Torvalds
+ *
+ * Created:      ?
+ * Description:  contains the system-call and fault low-level handling routines.
+ *               This also contains the timer-interrupt handler, as well as all
+ *               interrupts and faults that can result in a task-switch.
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * 25-Dec-2004 - LG Soft India
+ *     1. Fix in return_from_int, to make sure any pending
+ *     system call in ILAT for this process to get
+ *     executed, otherwise in case context switch happens,
+ *     system call of first process (i.e in ILAT) will be
+ *     carried forward to the switched process.
+ *     2. Removed Constant references for the following
+ *             a.  IPEND
+ *             b.  EXCAUSE mask
+ *             c.  PAGE Mask
+ */
+
+/*
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ */
+
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
+#include <asm/asm-offsets.h>
+
+#include <asm/mach-common/context.S>
+
+#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
+       /*
+        * TODO: this should be proper save/restore, but for now
+        * we'll just cheat and use 0x1/0x13
+        */
+# define DEBUG_START_HWTRACE \
+       P5.l = LO(TBUFCTL); \
+       P5.h = HI(TBUFCTL); \
+       R7 = 0x13; \
+       [P5] = R7;
+# define DEBUG_STOP_HWTRACE \
+       P5.l = LO(TBUFCTL); \
+       P5.h = HI(TBUFCTL); \
+       R7 = 0x01; \
+       [P5] = R7;
+#else
+# define DEBUG_START_HWTRACE
+# define DEBUG_STOP_HWTRACE
+#endif
+
+#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+.section .l1.text
+#else
+.text
+#endif
+
+/* Slightly simplified and streamlined entry point for CPLB misses.
+ * This one does not lower the level to IRQ5, and thus can be used to
+ * patch up CPLB misses on the kernel stack.
+ */
+ENTRY(_ex_dcplb)
+#if defined(ANOMALY_05000261)
+       /*
+        * Work around an anomaly: if we see a new DCPLB fault, return
+        * without doing anything.  Then, if we get the same fault again,
+        * handle it.
+        */
+       p5.l = _last_cplb_fault_retx;
+       p5.h = _last_cplb_fault_retx;
+       r7 = [p5];
+       r6 = retx;
+       [p5] = r6;
+       cc = r6 == r7;
+       if !cc jump _return_from_exception;
+       /* fall through */
+#endif
+
+ENTRY(_ex_icplb)
+       (R7:6,P5:4) = [sp++];
+       ASTAT = [sp++];
+       SAVE_ALL_SYS
+       call __cplb_hdr;
+       DEBUG_START_HWTRACE
+       RESTORE_ALL_SYS
+       SP = RETN;
+       rtx;
+
+ENTRY(_ex_spinlock)
+       /* Transform this into a syscall - twiddle the syscall vector.  */
+       p5.l = lo(EVT15);
+       p5.h = hi(EVT15);
+       r7.l = _spinlock_bh;
+       r7.h = _spinlock_bh;
+       [p5] = r7;
+       csync;
+       /* Fall through.  */
+
+ENTRY(_ex_syscall)
+       DEBUG_START_HWTRACE
+       (R7:6,P5:4) = [sp++];
+       ASTAT = [sp++];
+       raise 15;               /* invoked by TRAP #0, for sys call */
+       sp = retn;
+       rtx
+
+ENTRY(_spinlock_bh)
+       SAVE_ALL_SYS
+       /* To end up here, vector 15 was changed - so we have to change it
+        * back.
+        */
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _evt_system_call;
+       p1.h = _evt_system_call;
+       [p0] = p1;
+       csync;
+       r0 = [sp + PT_R0];
+       sp += -12;
+       call _sys_bfin_spinlock;
+       sp += 12;
+       [SP + PT_R0] = R0;
+       RESTORE_ALL_SYS
+       rti;
+
+ENTRY(_ex_soft_bp)
+       r7 = retx;
+       r7 += -2;
+       retx = r7;
+       jump.s _ex_trap_c;
+
+ENTRY(_ex_single_step)
+       r7 = retx;
+       r6 = reti;
+       cc = r7 == r6;
+       if cc jump _return_from_exception
+       r7 = syscfg;
+       bitclr (r7, 0);
+       syscfg = R7;
+
+       p5.l = lo(IPEND);
+       p5.h = hi(IPEND);
+       r6 = [p5];
+       cc = bittst(r6, 5);
+       if !cc jump _ex_trap_c;
+       p4.l = lo(EVT5);
+       p4.h = hi(EVT5);
+       r6.h = _exception_to_level5;
+       r6.l = _exception_to_level5;
+       r7 = [p4];
+       cc = r6 == r7;
+       if !cc jump _ex_trap_c;
+
+_return_from_exception:
+       DEBUG_START_HWTRACE
+       (R7:6,P5:4) = [sp++];
+       ASTAT = [sp++];
+       sp = retn;
+       rtx;
+
+ENTRY(_handle_bad_cplb)
+       /* To get here, we just tried and failed to change a CPLB
+        * so, handle things in trap_c (C code), by lowering to
+        * IRQ5, just like we normally do. Since this is not a
+        * "normal" return path, we have a do alot of stuff to
+        * the stack to get ready so, we can fall through - we
+        * need to make a CPLB exception look like a normal exception
+        */
+
+       DEBUG_START_HWTRACE
+       RESTORE_ALL_SYS
+       [--sp] = ASTAT;
+       [--sp] = (R7:6, P5:4);
+
+ENTRY(_ex_trap_c)
+       /* Call C code (trap_c) to handle the exception, which most
+        * likely involves sending a signal to the current process.
+        * To avoid double faults, lower our priority to IRQ5 first.
+        */
+       P5.h = _exception_to_level5;
+       P5.l = _exception_to_level5;
+       p4.l = lo(EVT5);
+       p4.h = hi(EVT5);
+       [p4] = p5;
+       csync;
+
+       /* Disable all interrupts, but make sure level 5 is enabled so
+        * we can switch to that level.  Save the old mask.  */
+       cli r6;
+       p4.l = _excpt_saved_imask;
+       p4.h = _excpt_saved_imask;
+       [p4] = r6;
+       r6 = 0x3f;
+       sti r6;
+
+       /* Save the excause into a circular buffer, in case the instruction
+        * which caused this excecptions causes others.
+        */
+       P5.l = _in_ptr_excause;
+       P5.h = _in_ptr_excause;
+       R7 = [P5];
+       R7 += 4;
+       R6 = 0xF;
+       R7 = R7 & R6;
+       [P5] = R7;
+       R6.l = _excause_circ_buf;
+       R6.h = _excause_circ_buf;
+       R7 = R7 + R6;
+       p5 = R7;
+       R6 = SEQSTAT;
+       [P5] = R6;
+
+       DEBUG_START_HWTRACE
+       (R7:6,P5:4) = [sp++];
+       ASTAT = [sp++];
+       SP = RETN;
+       raise 5;
+       rtx;
+
+ENTRY(_exception_to_level5)
+       SAVE_ALL_SYS
+
+       /* Restore interrupt mask.  We haven't pushed RETI, so this
+        * doesn't enable interrupts until we return from this handler.  */
+       p4.l = _excpt_saved_imask;
+       p4.h = _excpt_saved_imask;
+       r6 = [p4];
+       sti r6;
+
+       /* Restore the hardware error vector.  */
+       P5.h = _evt_ivhw;
+       P5.l = _evt_ivhw;
+       p4.l = lo(EVT5);
+       p4.h = hi(EVT5);
+       [p4] = p5;
+       csync;
+
+       p2.l = lo(IPEND);
+       p2.h = hi(IPEND);
+       csync;
+       r0 = [p2];              /* Read current IPEND */
+       [sp + PT_IPEND] = r0;   /* Store IPEND */
+
+       /* Pop the excause from the circular buffer and push it on the stack
+        * (in the right place - if you change the location of SEQSTAT, you
+        * must change this offset.
+        */
+.L_excep_to_5_again:
+       P5.l = _out_ptr_excause;
+       P5.h = _out_ptr_excause;
+       R7 = [P5];
+       R7 += 4;
+       R6 = 0xF;
+       R7 = R7 & R6;
+       [P5] = R7;
+       R6.l = _excause_circ_buf;
+       R6.h = _excause_circ_buf;
+       R7 = R7 + R6;
+       P5 = R7;
+       R1 = [P5];
+       [SP + 8] = r1;
+
+       r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
+       SP += -12;
+       call _trap_c;
+       SP += 12;
+
+       /* See if anything else is in the exception buffer
+        * if there is, process it
+        */
+       P5.l = _out_ptr_excause;
+       P5.h = _out_ptr_excause;
+       P4.l = _in_ptr_excause;
+       P4.h = _in_ptr_excause;
+       R6 = [P5];
+       R7 = [P4];
+       CC = R6 == R7;
+       if ! CC JUMP .L_excep_to_5_again
+
+       call _ret_from_exception;
+       RESTORE_ALL_SYS
+       rti;
+
+ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
+       /* Since the kernel stack can be anywhere, it's not guaranteed to be
+        * covered by a CPLB.  Switch to an exception stack; use RETN as a
+        * scratch register (for want of a better option).
+        */
+       retn = sp;
+       sp.l = _exception_stack_top;
+       sp.h = _exception_stack_top;
+       /* Try to deal with syscalls quickly.  */
+       [--sp] = ASTAT;
+       [--sp] = (R7:6, P5:4);
+       DEBUG_STOP_HWTRACE
+       r7 = SEQSTAT;           /* reason code is in bit 5:0 */
+       r6.l = lo(SEQSTAT_EXCAUSE);
+       r6.h = hi(SEQSTAT_EXCAUSE);
+       r7 = r7 & r6;
+       p5.h = _extable;
+       p5.l = _extable;
+       p4 = r7;
+       p5 = p5 + (p4 << 2);
+       p4 = [p5];
+       jump (p4);
+
+.Lbadsys:
+       r7 = -ENOSYS;           /* signextending enough */
+       [sp + PT_R0] = r7;      /* return value from system call */
+       jump .Lsyscall_really_exit;
+
+ENTRY(_kernel_execve)
+       link SIZEOF_PTREGS;
+       p0 = sp;
+       r3 = SIZEOF_PTREGS / 4;
+       r4 = 0(x);
+0:
+       [p0++] = r4;
+       r3 += -1;
+       cc = r3 == 0;
+       if !cc jump 0b (bp);
+
+       p0 = sp;
+       sp += -16;
+       [sp + 12] = p0;
+       call _do_execve;
+       SP += 16;
+       cc = r0 == 0;
+       if ! cc jump 1f;
+       /* Success.  Copy our temporary pt_regs to the top of the kernel
+        * stack and do a normal exception return.
+        */
+       r1 = sp;
+       r0 = (-KERNEL_STACK_SIZE) (x);
+       r1 = r1 & r0;
+       p2 = r1;
+       p3 = [p2];
+       r0 = KERNEL_STACK_SIZE - 4 (z);
+       p1 = r0;
+       p1 = p1 + p2;
+
+       p0 = fp;
+       r4 = [p0--];
+       r3 = SIZEOF_PTREGS / 4;
+0:
+       r4 = [p0--];
+       [p1--] = r4;
+       r3 += -1;
+       cc = r3 == 0;
+       if ! cc jump 0b (bp);
+
+       r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);
+       p1 = r0;
+       p1 = p1 + p2;
+       sp = p1;
+       r0 = syscfg;
+       [SP + PT_SYSCFG] = r0;
+       [p3 + (TASK_THREAD + THREAD_KSP)] = sp;
+
+       RESTORE_CONTEXT;
+       rti;
+1:
+       unlink;
+       rts;
+
+ENTRY(_system_call)
+       /* Store IPEND */
+       p2.l = lo(IPEND);
+       p2.h = hi(IPEND);
+       csync;
+       r0 = [p2];
+       [sp + PT_IPEND] = r0;
+
+       /* Store RETS for now */
+       r0 = rets;
+       [sp + PT_RESERVED] = r0;
+       /* Set the stack for the current process */
+       r7 = sp;
+       r6.l = lo(ALIGN_PAGE_MASK);
+       r6.h = hi(ALIGN_PAGE_MASK);
+       r7 = r7 & r6;           /* thread_info */
+       p2 = r7;
+       p2 = [p2];
+
+       [p2+(TASK_THREAD+THREAD_KSP)] = sp;
+
+       /* Check the System Call */
+       r7 = __NR_syscall;
+       /* System call number is passed in P0 */
+       r6 = p0;
+       cc = r6 < r7;
+       if ! cc jump .Lbadsys;
+
+       /* are we tracing syscalls?*/
+       r7 = sp;
+       r6.l = lo(ALIGN_PAGE_MASK);
+       r6.h = hi(ALIGN_PAGE_MASK);
+       r7 = r7 & r6;
+       p2 = r7;
+       r7 = [p2+TI_FLAGS];
+       CC = BITTST(r7,TIF_SYSCALL_TRACE);
+       if CC JUMP _sys_trace;
+
+       /* Execute the appropriate system call */
+
+       p4 = p0;
+       p5.l = _sys_call_table;
+       p5.h = _sys_call_table;
+       p5 = p5 + (p4 << 2);
+       r0 = [sp + PT_R0];
+       r1 = [sp + PT_R1];
+       r2 = [sp + PT_R2];
+       p5 = [p5];
+
+       [--sp] = r5;
+       [--sp] = r4;
+       [--sp] = r3;
+       SP += -12;
+       call (p5);
+       SP += 24;
+       [sp + PT_R0] = r0;
+
+.Lresume_userspace:
+       r7 = sp;
+       r4.l = lo(ALIGN_PAGE_MASK);
+       r4.h = hi(ALIGN_PAGE_MASK);
+       r7 = r7 & r4;           /* thread_info->flags */
+       p5 = r7;
+.Lresume_userspace_1:
+       /* Disable interrupts.  */
+       [--sp] = reti;
+       reti = [sp++];
+
+       r7 = [p5 + TI_FLAGS];
+       r4.l = lo(_TIF_WORK_MASK);
+       r4.h = hi(_TIF_WORK_MASK);
+       r7 =  r7 & r4;
+
+.Lsyscall_resched:
+       cc = BITTST(r7, TIF_NEED_RESCHED);
+       if !cc jump .Lsyscall_sigpending;
+
+       /* Reenable interrupts.  */
+       [--sp] = reti;
+       r0 = [sp++];
+
+       SP += -12;
+       call _schedule;
+       SP += 12;
+
+       jump .Lresume_userspace_1;
+
+.Lsyscall_sigpending:
+       cc = BITTST(r7, TIF_RESTORE_SIGMASK);
+       if cc jump .Lsyscall_do_signals;
+       cc = BITTST(r7, TIF_SIGPENDING);
+       if !cc jump .Lsyscall_really_exit;
+.Lsyscall_do_signals:
+       /* Reenable interrupts.  */
+       [--sp] = reti;
+       r0 = [sp++];
+
+       r0 = sp;
+       SP += -12;
+       call _do_signal;
+       SP += 12;
+
+.Lsyscall_really_exit:
+       r5 = [sp + PT_RESERVED];
+       rets = r5;
+       rts;
+
+_sys_trace:
+       call _syscall_trace;
+
+       /* Execute the appropriate system call */
+
+       p4 = [SP + PT_P0];
+       p5.l = _sys_call_table;
+       p5.h = _sys_call_table;
+       p5 = p5 + (p4 << 2);
+       r0 = [sp + PT_R0];
+       r1 = [sp + PT_R1];
+       r2 = [sp + PT_R2];
+       r3 = [sp + PT_R3];
+       r4 = [sp + PT_R4];
+       r5 = [sp + PT_R5];
+       p5 = [p5];
+
+       [--sp] = r5;
+       [--sp] = r4;
+       [--sp] = r3;
+       SP += -12;
+       call (p5);
+       SP += 24;
+       [sp + PT_R0] = r0;
+
+       call _syscall_trace;
+       jump .Lresume_userspace;
+
+ENTRY(_resume)
+       /*
+        * Beware - when entering resume, prev (the current task) is
+        * in r0, next (the new task) is in r1.
+        */
+       p0 = r0;
+       p1 = r1;
+       [--sp] = rets;
+       [--sp] = fp;
+       [--sp] = (r7:4, p5:3);
+
+       /* save usp */
+       p2 = usp;
+       [p0+(TASK_THREAD+THREAD_USP)] = p2;
+
+       /* save current kernel stack pointer */
+       [p0+(TASK_THREAD+THREAD_KSP)] = sp;
+
+       /* save program counter */
+       r1.l = _new_old_task;
+       r1.h = _new_old_task;
+       [p0+(TASK_THREAD+THREAD_PC)] = r1;
+
+       /* restore the kernel stack pointer */
+       sp = [p1+(TASK_THREAD+THREAD_KSP)];
+
+       /* restore user stack pointer */
+       p0 = [p1+(TASK_THREAD+THREAD_USP)];
+       usp = p0;
+
+       /* restore pc */
+       p0 = [p1+(TASK_THREAD+THREAD_PC)];
+       jump (p0);
+
+       /*
+        * Following code actually lands up in a new (old) task.
+        */
+
+_new_old_task:
+       (r7:4, p5:3) = [sp++];
+       fp = [sp++];
+       rets = [sp++];
+
+       /*
+        * When we come out of resume, r0 carries "old" task, becuase we are
+        * in "new" task.
+        */
+       rts;
+
+ENTRY(_ret_from_exception)
+       p2.l = lo(IPEND);
+       p2.h = hi(IPEND);
+
+       csync;
+       r0 = [p2];
+       [sp + PT_IPEND] = r0;
+
+1:
+       r1 = 0x37(Z);
+       r2 = ~r1;
+       r2.h = 0;
+       r0 = r2 & r0;
+       cc = r0 == 0;
+       if !cc jump 4f; /* if not return to user mode, get out */
+
+       /* Make sure any pending system call or deferred exception
+        * return in ILAT for this process to get executed, otherwise
+        * in case context switch happens, system call of
+        * first process (i.e in ILAT) will be carried
+        * forward to the switched process
+        */
+
+       p2.l = lo(ILAT);
+       p2.h = hi(ILAT);
+       r0 = [p2];
+       r1 = (EVT_IVG14 | EVT_IVG15) (z);
+       r0 = r0 & r1;
+       cc = r0 == 0;
+       if !cc jump 5f;
+
+       /* Set the stack for the current process */
+       r7 = sp;
+       r4.l = lo(ALIGN_PAGE_MASK);
+       r4.h = hi(ALIGN_PAGE_MASK);
+       r7 = r7 & r4;           /* thread_info->flags */
+       p5 = r7;
+       r7 = [p5 + TI_FLAGS];
+       r4.l = lo(_TIF_WORK_MASK);
+       r4.h = hi(_TIF_WORK_MASK);
+       r7 =  r7 & r4;
+       cc = r7 == 0;
+       if cc jump 4f;
+
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _schedule_and_signal;
+       p1.h = _schedule_and_signal;
+       [p0] = p1;
+       csync;
+       raise 15;               /* raise evt14 to do signal or reschedule */
+4:
+       r0 = syscfg;
+       bitclr(r0, 0);
+       syscfg = r0;
+5:
+       rts;
+
+ENTRY(_return_from_int)
+       /* If someone else already raised IRQ 15, do nothing.  */
+       csync;
+       p2.l = lo(ILAT);
+       p2.h = hi(ILAT);
+       r0 = [p2];
+       cc = bittst (r0, EVT_IVG15_P);
+       if cc jump 2f;
+
+       /* if not return to user mode, get out */
+       p2.l = lo(IPEND);
+       p2.h = hi(IPEND);
+       r0 = [p2];
+       r1 = 0x17(Z);
+       r2 = ~r1;
+       r2.h = 0;
+       r0 = r2 & r0;
+       r1 = 1;
+       r1 = r0 - r1;
+       r2 = r0 & r1;
+       cc = r2 == 0;
+       if !cc jump 2f;
+
+       /* Lower the interrupt level to 15.  */
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _schedule_and_signal_from_int;
+       p1.h = _schedule_and_signal_from_int;
+       [p0] = p1;
+       csync;
+#if defined(ANOMALY_05000281)
+       r0.l = lo(CONFIG_BOOT_LOAD);
+       r0.h = hi(CONFIG_BOOT_LOAD);
+       reti = r0;
+#endif
+       r0 = 0x801f (z);
+       STI r0;
+       raise 15;       /* raise evt15 to do signal or reschedule */
+       rti;
+2:
+       rts;
+
+ENTRY(_lower_to_irq14)
+#if defined(ANOMALY_05000281)
+       r0.l = lo(CONFIG_BOOT_LOAD);
+       r0.h = hi(CONFIG_BOOT_LOAD);
+       reti = r0;
+#endif
+       r0 = 0x401f;
+       sti r0;
+       raise 14;
+       rti;
+ENTRY(_evt14_softirq)
+#ifdef CONFIG_DEBUG_HWERR
+       r0 = 0x3f;
+       sti r0;
+#else
+       cli r0;
+#endif
+       [--sp] = RETI;
+       SP += 4;
+       rts;
+
+_schedule_and_signal_from_int:
+       /* To end up here, vector 15 was changed - so we have to change it
+        * back.
+        */
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _evt_system_call;
+       p1.h = _evt_system_call;
+       [p0] = p1;
+       csync;
+       p1 = rets;
+       [sp + PT_RESERVED] = p1;
+
+       p0.l = _irq_flags;
+       p0.h = _irq_flags;
+       r0 = [p0];
+       sti r0;
+
+       jump.s .Lresume_userspace;
+
+_schedule_and_signal:
+       SAVE_CONTEXT_SYSCALL
+       /* To end up here, vector 15 was changed - so we have to change it
+        * back.
+        */
+       p0.l = lo(EVT15);
+       p0.h = hi(EVT15);
+       p1.l = _evt_system_call;
+       p1.h = _evt_system_call;
+       [p0] = p1;
+       csync;
+       p0.l = 1f;
+       p0.h = 1f;
+       [sp + PT_RESERVED] = P0;
+       call .Lresume_userspace;
+1:
+       RESTORE_CONTEXT
+       rti;
+
+/* Make sure when we start, that the circular buffer is initialized properly
+ * R0 and P0 are call clobbered, so we can use them here.
+ */
+ENTRY(_init_exception_buff)
+       r0 = 0;
+       p0.h = _in_ptr_excause;
+       p0.l = _in_ptr_excause;
+       [p0] = r0;
+       p0.h = _out_ptr_excause;
+       p0.l = _out_ptr_excause;
+       [p0] = r0;
+       rts;
+
+/*
+ * Put these in the kernel data section - that should always be covered by
+ * a CPLB. This is needed to ensure we don't get double fault conditions
+ */
+
+#ifdef CONFIG_SYSCALL_TAB_L1
+.section .l1.data
+#else
+.data
+#endif
+ALIGN
+_extable:
+       /* entry for each EXCAUSE[5:0]
+        * This table bmust be in sync with the table in ./kernel/traps.c
+        * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
+        */
+       .long _ex_syscall;      /* 0x00 - User Defined - Linux Syscall */
+       .long _ex_soft_bp       /* 0x01 - User Defined - Software breakpoint */
+       .long _ex_trap_c        /* 0x02 - User Defined */
+       .long _ex_trap_c        /* 0x03 - User Defined  - Atomic test and set service */
+       .long _ex_spinlock      /* 0x04 - User Defined */
+       .long _ex_trap_c        /* 0x05 - User Defined */
+       .long _ex_trap_c        /* 0x06 - User Defined */
+       .long _ex_trap_c        /* 0x07 - User Defined */
+       .long _ex_trap_c        /* 0x08 - User Defined */
+       .long _ex_trap_c        /* 0x09 - User Defined */
+       .long _ex_trap_c        /* 0x0A - User Defined */
+       .long _ex_trap_c        /* 0x0B - User Defined */
+       .long _ex_trap_c        /* 0x0C - User Defined */
+       .long _ex_trap_c        /* 0x0D - User Defined */
+       .long _ex_trap_c        /* 0x0E - User Defined */
+       .long _ex_trap_c        /* 0x0F - User Defined */
+       .long _ex_single_step   /* 0x10 - HW Single step */
+       .long _ex_trap_c        /* 0x11 - Trace Buffer Full */
+       .long _ex_trap_c        /* 0x12 - Reserved */
+       .long _ex_trap_c        /* 0x13 - Reserved */
+       .long _ex_trap_c        /* 0x14 - Reserved */
+       .long _ex_trap_c        /* 0x15 - Reserved */
+       .long _ex_trap_c        /* 0x16 - Reserved */
+       .long _ex_trap_c        /* 0x17 - Reserved */
+       .long _ex_trap_c        /* 0x18 - Reserved */
+       .long _ex_trap_c        /* 0x19 - Reserved */
+       .long _ex_trap_c        /* 0x1A - Reserved */
+       .long _ex_trap_c        /* 0x1B - Reserved */
+       .long _ex_trap_c        /* 0x1C - Reserved */
+       .long _ex_trap_c        /* 0x1D - Reserved */
+       .long _ex_trap_c        /* 0x1E - Reserved */
+       .long _ex_trap_c        /* 0x1F - Reserved */
+       .long _ex_trap_c        /* 0x20 - Reserved */
+       .long _ex_trap_c        /* 0x21 - Undefined Instruction */
+       .long _ex_trap_c        /* 0x22 - Illegal Instruction Combination */
+       .long _ex_dcplb         /* 0x23 - Data CPLB Protection Violation */
+       .long _ex_trap_c        /* 0x24 - Data access misaligned */
+       .long _ex_trap_c        /* 0x25 - Unrecoverable Event */
+       .long _ex_dcplb         /* 0x26 - Data CPLB Miss */
+       .long _ex_trap_c        /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */
+       .long _ex_trap_c        /* 0x28 - Emulation Watchpoint */
+       .long _ex_trap_c        /* 0x29 - Instruction fetch access error (535 only) */
+       .long _ex_trap_c        /* 0x2A - Instruction fetch misaligned */
+       .long _ex_icplb         /* 0x2B - Instruction CPLB protection Violation */
+       .long _ex_icplb         /* 0x2C - Instruction CPLB miss */
+       .long _ex_trap_c        /* 0x2D - Instruction CPLB Multiple Hits */
+       .long _ex_trap_c        /* 0x2E - Illegal use of Supervisor Resource */
+       .long _ex_trap_c        /* 0x2E - Illegal use of Supervisor Resource */
+       .long _ex_trap_c        /* 0x2F - Reserved */
+       .long _ex_trap_c        /* 0x30 - Reserved */
+       .long _ex_trap_c        /* 0x31 - Reserved */
+       .long _ex_trap_c        /* 0x32 - Reserved */
+       .long _ex_trap_c        /* 0x33 - Reserved */
+       .long _ex_trap_c        /* 0x34 - Reserved */
+       .long _ex_trap_c        /* 0x35 - Reserved */
+       .long _ex_trap_c        /* 0x36 - Reserved */
+       .long _ex_trap_c        /* 0x37 - Reserved */
+       .long _ex_trap_c        /* 0x38 - Reserved */
+       .long _ex_trap_c        /* 0x39 - Reserved */
+       .long _ex_trap_c        /* 0x3A - Reserved */
+       .long _ex_trap_c        /* 0x3B - Reserved */
+       .long _ex_trap_c        /* 0x3C - Reserved */
+       .long _ex_trap_c        /* 0x3D - Reserved */
+       .long _ex_trap_c        /* 0x3E - Reserved */
+       .long _ex_trap_c        /* 0x3F - Reserved */
+
+ALIGN
+ENTRY(_sys_call_table)
+       .long _sys_ni_syscall   /* 0  -  old "setup()" system call*/
+       .long _sys_exit
+       .long _sys_fork
+       .long _sys_read
+       .long _sys_write
+       .long _sys_open         /* 5 */
+       .long _sys_close
+       .long _sys_ni_syscall   /* old waitpid */
+       .long _sys_creat
+       .long _sys_link
+       .long _sys_unlink       /* 10 */
+       .long _sys_execve
+       .long _sys_chdir
+       .long _sys_time
+       .long _sys_mknod
+       .long _sys_chmod                /* 15 */
+       .long _sys_chown        /* chown16 */
+       .long _sys_ni_syscall   /* old break syscall holder */
+       .long _sys_ni_syscall   /* old stat */
+       .long _sys_lseek
+       .long _sys_getpid       /* 20 */
+       .long _sys_mount
+       .long _sys_ni_syscall   /* old umount */
+       .long _sys_setuid
+       .long _sys_getuid
+       .long _sys_stime                /* 25 */
+       .long _sys_ptrace
+       .long _sys_alarm
+       .long _sys_ni_syscall   /* old fstat */
+       .long _sys_pause
+       .long _sys_ni_syscall   /* old utime */ /* 30 */
+       .long _sys_ni_syscall   /* old stty syscall holder */
+       .long _sys_ni_syscall   /* old gtty syscall holder */
+       .long _sys_access
+       .long _sys_nice
+       .long _sys_ni_syscall   /* 35 */ /* old ftime syscall holder */
+       .long _sys_sync
+       .long _sys_kill
+       .long _sys_rename
+       .long _sys_mkdir
+       .long _sys_rmdir                /* 40 */
+       .long _sys_dup
+       .long _sys_pipe
+       .long _sys_times
+       .long _sys_ni_syscall   /* old prof syscall holder */
+       .long _sys_brk          /* 45 */
+       .long _sys_setgid
+       .long _sys_getgid
+       .long _sys_ni_syscall   /* old sys_signal */
+       .long _sys_geteuid      /* geteuid16 */
+       .long _sys_getegid      /* getegid16 */ /* 50 */
+       .long _sys_acct
+       .long _sys_umount       /* recycled never used phys() */
+       .long _sys_ni_syscall   /* old lock syscall holder */
+       .long _sys_ioctl
+       .long _sys_fcntl                /* 55 */
+       .long _sys_ni_syscall   /* old mpx syscall holder */
+       .long _sys_setpgid
+       .long _sys_ni_syscall   /* old ulimit syscall holder */
+       .long _sys_ni_syscall   /* old old uname */
+       .long _sys_umask                /* 60 */
+       .long _sys_chroot
+       .long _sys_ustat
+       .long _sys_dup2
+       .long _sys_getppid
+       .long _sys_getpgrp      /* 65 */
+       .long _sys_setsid
+       .long _sys_ni_syscall   /* old sys_sigaction */
+       .long _sys_sgetmask
+       .long _sys_ssetmask
+       .long _sys_setreuid     /* setreuid16 */        /* 70 */
+       .long _sys_setregid     /* setregid16 */
+       .long _sys_ni_syscall   /* old sys_sigsuspend */
+       .long _sys_ni_syscall   /* old sys_sigpending */
+       .long _sys_sethostname
+       .long _sys_setrlimit    /* 75 */
+       .long _sys_ni_syscall   /* old getrlimit */
+       .long _sys_getrusage
+       .long _sys_gettimeofday
+       .long _sys_settimeofday
+       .long _sys_getgroups    /* getgroups16 */       /* 80 */
+       .long _sys_setgroups    /* setgroups16 */
+       .long _sys_ni_syscall   /* old_select */
+       .long _sys_symlink
+       .long _sys_ni_syscall   /* old lstat */
+       .long _sys_readlink     /* 85 */
+       .long _sys_uselib
+       .long _sys_ni_syscall   /* sys_swapon */
+       .long _sys_reboot
+       .long _sys_ni_syscall   /* old_readdir */
+       .long _sys_ni_syscall   /* sys_mmap */  /* 90 */
+       .long _sys_munmap
+       .long _sys_truncate
+       .long _sys_ftruncate
+       .long _sys_fchmod
+       .long _sys_fchown       /* fchown16 */  /* 95 */
+       .long _sys_getpriority
+       .long _sys_setpriority
+       .long _sys_ni_syscall   /* old profil syscall holder */
+       .long _sys_statfs
+       .long _sys_fstatfs      /* 100 */
+       .long _sys_ni_syscall
+       .long _sys_ni_syscall   /* old sys_socketcall */
+       .long _sys_syslog
+       .long _sys_setitimer
+       .long _sys_getitimer    /* 105 */
+       .long _sys_newstat
+       .long _sys_newlstat
+       .long _sys_newfstat
+       .long _sys_ni_syscall   /* old uname */
+       .long _sys_ni_syscall   /* iopl for i386 */ /* 110 */
+       .long _sys_vhangup
+       .long _sys_ni_syscall   /* obsolete idle() syscall */
+       .long _sys_ni_syscall   /* vm86old for i386 */
+       .long _sys_wait4
+       .long _sys_ni_syscall   /* 115 */ /* sys_swapoff */
+       .long _sys_sysinfo
+       .long _sys_ni_syscall   /* old sys_ipc */
+       .long _sys_fsync
+       .long _sys_ni_syscall   /* old sys_sigreturn */
+       .long _sys_clone                /* 120 */
+       .long _sys_setdomainname
+       .long _sys_newuname
+       .long _sys_ni_syscall   /* old sys_modify_ldt */
+       .long _sys_adjtimex
+       .long _sys_ni_syscall   /* 125 */ /* sys_mprotect */
+       .long _sys_ni_syscall   /* old sys_sigprocmask */
+       .long _sys_ni_syscall   /* old "creat_module" */
+       .long _sys_init_module
+       .long _sys_delete_module
+       .long _sys_ni_syscall   /* 130: old "get_kernel_syms" */
+       .long _sys_quotactl
+       .long _sys_getpgid
+       .long _sys_fchdir
+       .long _sys_bdflush
+       .long _sys_ni_syscall   /* 135 */ /* sys_sysfs */
+       .long _sys_personality
+       .long _sys_ni_syscall   /* for afs_syscall */
+       .long _sys_setfsuid     /* setfsuid16 */
+       .long _sys_setfsgid     /* setfsgid16 */
+       .long _sys_llseek       /* 140 */
+       .long _sys_getdents
+       .long _sys_ni_syscall   /* sys_select */
+       .long _sys_flock
+       .long _sys_ni_syscall   /* sys_msync */
+       .long _sys_readv                /* 145 */
+       .long _sys_writev
+       .long _sys_getsid
+       .long _sys_fdatasync
+       .long _sys_sysctl
+       .long _sys_ni_syscall   /* 150 */ /* sys_mlock */
+       .long _sys_ni_syscall   /* sys_munlock */
+       .long _sys_ni_syscall   /* sys_mlockall */
+       .long _sys_ni_syscall   /* sys_munlockall */
+       .long _sys_sched_setparam
+       .long _sys_sched_getparam /* 155 */
+       .long _sys_sched_setscheduler
+       .long _sys_sched_getscheduler
+       .long _sys_sched_yield
+       .long _sys_sched_get_priority_max
+       .long _sys_sched_get_priority_min  /* 160 */
+       .long _sys_sched_rr_get_interval
+       .long _sys_nanosleep
+       .long _sys_ni_syscall   /* sys_mremap */
+       .long _sys_setresuid    /* setresuid16 */
+       .long _sys_getresuid    /* getresuid16 */       /* 165 */
+       .long _sys_ni_syscall   /* for vm86 */
+       .long _sys_ni_syscall   /* old "query_module" */
+       .long _sys_ni_syscall   /* sys_poll */
+       .long _sys_ni_syscall   /* sys_nfsservctl */
+       .long _sys_setresgid    /* setresgid16 */       /* 170 */
+       .long _sys_getresgid    /* getresgid16 */
+       .long _sys_prctl
+       .long _sys_rt_sigreturn
+       .long _sys_rt_sigaction
+       .long _sys_rt_sigprocmask /* 175 */
+       .long _sys_rt_sigpending
+       .long _sys_rt_sigtimedwait
+       .long _sys_rt_sigqueueinfo
+       .long _sys_rt_sigsuspend
+       .long _sys_pread64      /* 180 */
+       .long _sys_pwrite64
+       .long _sys_lchown       /* lchown16 */
+       .long _sys_getcwd
+       .long _sys_capget
+       .long _sys_capset       /* 185 */
+       .long _sys_sigaltstack
+       .long _sys_sendfile
+       .long _sys_ni_syscall   /* streams1 */
+       .long _sys_ni_syscall   /* streams2 */
+       .long _sys_vfork                /* 190 */
+       .long _sys_getrlimit
+       .long _sys_mmap2
+       .long _sys_truncate64
+       .long _sys_ftruncate64
+       .long _sys_stat64       /* 195 */
+       .long _sys_lstat64
+       .long _sys_fstat64
+       .long _sys_chown
+       .long _sys_getuid
+       .long _sys_getgid       /* 200 */
+       .long _sys_geteuid
+       .long _sys_getegid
+       .long _sys_setreuid
+       .long _sys_setregid
+       .long _sys_getgroups    /* 205 */
+       .long _sys_setgroups
+       .long _sys_fchown
+       .long _sys_setresuid
+       .long _sys_getresuid
+       .long _sys_setresgid    /* 210 */
+       .long _sys_getresgid
+       .long _sys_lchown
+       .long _sys_setuid
+       .long _sys_setgid
+       .long _sys_setfsuid     /* 215 */
+       .long _sys_setfsgid
+       .long _sys_pivot_root
+       .long _sys_ni_syscall   /* sys_mincore */
+       .long _sys_ni_syscall   /* sys_madvise */
+       .long _sys_getdents64   /* 220 */
+       .long _sys_fcntl64
+       .long _sys_ni_syscall   /* reserved for TUX */
+       .long _sys_ni_syscall
+       .long _sys_gettid
+       .long _sys_ni_syscall   /* 225 */ /* sys_readahead */
+       .long _sys_setxattr
+       .long _sys_lsetxattr
+       .long _sys_fsetxattr
+       .long _sys_getxattr
+       .long _sys_lgetxattr    /* 230 */
+       .long _sys_fgetxattr
+       .long _sys_listxattr
+       .long _sys_llistxattr
+       .long _sys_flistxattr
+       .long _sys_removexattr  /* 235 */
+       .long _sys_lremovexattr
+       .long _sys_fremovexattr
+       .long _sys_tkill
+       .long _sys_sendfile64
+       .long _sys_futex                /* 240 */
+       .long _sys_sched_setaffinity
+       .long _sys_sched_getaffinity
+       .long _sys_ni_syscall   /* sys_set_thread_area */
+       .long _sys_ni_syscall   /* sys_get_thread_area */
+       .long _sys_io_setup     /* 245 */
+       .long _sys_io_destroy
+       .long _sys_io_getevents
+       .long _sys_io_submit
+       .long _sys_io_cancel
+       .long _sys_ni_syscall   /* 250 */ /* sys_alloc_hugepages */
+       .long _sys_ni_syscall   /* sys_freec_hugepages */
+       .long _sys_exit_group
+       .long _sys_lookup_dcookie
+       .long _sys_bfin_spinlock
+       .long _sys_epoll_create /* 255 */
+       .long _sys_epoll_ctl
+       .long _sys_epoll_wait
+       .long _sys_ni_syscall /* remap_file_pages */
+       .long _sys_set_tid_address
+       .long _sys_timer_create /* 260 */
+       .long _sys_timer_settime
+       .long _sys_timer_gettime
+       .long _sys_timer_getoverrun
+       .long _sys_timer_delete
+       .long _sys_clock_settime /* 265 */
+       .long _sys_clock_gettime
+       .long _sys_clock_getres
+       .long _sys_clock_nanosleep
+       .long _sys_statfs64
+       .long _sys_fstatfs64    /* 270 */
+       .long _sys_tgkill
+       .long _sys_utimes
+       .long _sys_fadvise64_64
+       .long _sys_ni_syscall /* vserver */
+       .long _sys_ni_syscall /* 275, mbind */
+       .long _sys_ni_syscall /* get_mempolicy */
+       .long _sys_ni_syscall /* set_mempolicy */
+       .long _sys_mq_open
+       .long _sys_mq_unlink
+       .long _sys_mq_timedsend /* 280 */
+       .long _sys_mq_timedreceive
+       .long _sys_mq_notify
+       .long _sys_mq_getsetattr
+       .long _sys_ni_syscall /* kexec_load */
+       .long _sys_waitid       /* 285 */
+       .long _sys_add_key
+       .long _sys_request_key
+       .long _sys_keyctl
+       .long _sys_ioprio_set
+       .long _sys_ioprio_get   /* 290 */
+       .long _sys_inotify_init
+       .long _sys_inotify_add_watch
+       .long _sys_inotify_rm_watch
+       .long _sys_ni_syscall /* migrate_pages */
+       .long _sys_openat       /* 295 */
+       .long _sys_mkdirat
+       .long _sys_mknodat
+       .long _sys_fchownat
+       .long _sys_futimesat
+       .long _sys_fstatat64    /* 300 */
+       .long _sys_unlinkat
+       .long _sys_renameat
+       .long _sys_linkat
+       .long _sys_symlinkat
+       .long _sys_readlinkat   /* 305 */
+       .long _sys_fchmodat
+       .long _sys_faccessat
+       .long _sys_pselect6
+       .long _sys_ppoll
+       .long _sys_unshare      /* 310 */
+       .long _sys_sram_alloc
+       .long _sys_sram_free
+       .long _sys_dma_memcpy
+       .long _sys_accept
+       .long _sys_bind         /* 315 */
+       .long _sys_connect
+       .long _sys_getpeername
+       .long _sys_getsockname
+       .long _sys_getsockopt
+       .long _sys_listen       /* 320 */
+       .long _sys_recv
+       .long _sys_recvfrom
+       .long _sys_recvmsg
+       .long _sys_send
+       .long _sys_sendmsg      /* 325 */
+       .long _sys_sendto
+       .long _sys_setsockopt
+       .long _sys_shutdown
+       .long _sys_socket
+       .long _sys_socketpair   /* 330 */
+       .long _sys_semctl
+       .long _sys_semget
+       .long _sys_semop
+       .long _sys_msgctl
+       .long _sys_msgget       /* 335 */
+       .long _sys_msgrcv
+       .long _sys_msgsnd
+       .long _sys_shmat
+       .long _sys_shmctl
+       .long _sys_shmdt        /* 340 */
+       .long _sys_shmget
+       .rept NR_syscalls-(.-_sys_call_table)/4
+       .long _sys_ni_syscall
+       .endr
+_excpt_saved_imask:
+       .long 0;
+
+_exception_stack:
+       .rept 1024
+       .long 0;
+       .endr
+_exception_stack_top:
+
+#if defined(ANOMALY_05000261)
+/* Used by the assembly entry point to work around an anomaly.  */
+_last_cplb_fault_retx:
+       .long 0;
+#endif
+/*
+ * Single instructions can have multiple faults, which need to be
+ * handled by traps.c, in irq5. We store the exception cause to ensure
+ * we don't miss a double fault condition
+ */
+ENTRY(_in_ptr_excause)
+       .long 0;
+ENTRY(_out_ptr_excause)
+       .long 0;
+ALIGN
+ENTRY(_excause_circ_buf)
+       .rept 4
+       .long 0
+       .endr
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
new file mode 100644 (file)
index 0000000..dd45664
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * File:         arch/blackfin/mach-common/interrupt.S
+ * Based on:
+ * Author:       D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>
+ *               Kenneth Albanowski <kjahds@kjahds.com>
+ *
+ * Created:      ?
+ * Description:  Interrupt Entries
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <asm/blackfin.h>
+#include <asm/mach/irq.h>
+#include <linux/autoconf.h>
+#include <linux/linkage.h>
+#include <asm/entry.h>
+#include <asm/asm-offsets.h>
+
+#include <asm/mach-common/context.S>
+
+#ifdef CONFIG_I_ENTRY_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 4       /* just in case */
+
+/*
+ * initial interrupt handlers
+ */
+
+#ifndef CONFIG_KGDB
+       /* interrupt routine for emulation - 0 */
+       /* Currently used only if GDB stub is not in - invalid */
+       /* gdb-stub set the evt itself */
+       /* save registers for post-mortem only */
+ENTRY(_evt_emulation)
+       SAVE_ALL_SYS
+#ifdef CONFIG_FRAME_POINTER
+       fp = 0;
+#endif
+       r0 = IRQ_EMU;
+       r1 = sp;
+       SP += -12;
+       call _irq_panic;
+       SP += 12;
+       /* - GDB stub fills this in by itself (if defined) */
+       rte;
+#endif
+
+/* Common interrupt entry code.         First we do CLI, then push
+ * RETI, to keep interrupts disabled, but to allow this state to be changed
+ * by local_bh_enable.
+ * R0 contains the interrupt number, while R1 may contain the value of IPEND,
+ * or garbage if IPEND won't be needed by the ISR.  */
+__common_int_entry:
+       [--sp] = fp;
+       [--sp] = usp;
+
+       [--sp] = i0;
+       [--sp] = i1;
+       [--sp] = i2;
+       [--sp] = i3;
+
+       [--sp] = m0;
+       [--sp] = m1;
+       [--sp] = m2;
+       [--sp] = m3;
+
+       [--sp] = l0;
+       [--sp] = l1;
+       [--sp] = l2;
+       [--sp] = l3;
+
+       [--sp] = b0;
+       [--sp] = b1;
+       [--sp] = b2;
+       [--sp] = b3;
+       [--sp] = a0.x;
+       [--sp] = a0.w;
+       [--sp] = a1.x;
+       [--sp] = a1.w;
+
+       [--sp] = LC0;
+       [--sp] = LC1;
+       [--sp] = LT0;
+       [--sp] = LT1;
+       [--sp] = LB0;
+       [--sp] = LB1;
+
+       [--sp] = ASTAT;
+
+       [--sp] = r0;    /* Skip reserved */
+       [--sp] = RETS;
+       r2 = RETI;
+       [--sp] = r2;
+       [--sp] = RETX;
+       [--sp] = RETN;
+       [--sp] = RETE;
+       [--sp] = SEQSTAT;
+       [--sp] = r1;    /* IPEND - R1 may or may not be set up before jumping here. */
+
+       /* Switch to other method of keeping interrupts disabled.  */
+#ifdef CONFIG_DEBUG_HWERR
+       r1 = 0x3f;
+       sti r1;
+#else
+       cli r1;
+#endif
+       [--sp] = RETI;  /* orig_pc */
+       /* Clear all L registers.  */
+       r1 = 0 (x);
+       l0 = r1;
+       l1 = r1;
+       l2 = r1;
+       l3 = r1;
+#ifdef CONFIG_FRAME_POINTER
+       fp = 0;
+#endif
+
+#ifdef ANOMALY_05000283
+       cc = r7 == r7;
+       p5.h = 0xffc0;
+       p5.l = 0x0014;
+       if cc jump 1f;
+       r7.l = W[p5];
+1:
+#endif
+       r1 =  sp;
+       SP += -12;
+       call _do_irq;
+       SP += 12;
+       call _return_from_int;
+.Lcommon_restore_context:
+       RESTORE_CONTEXT
+       rti;
+
+/* interrupt routine for ivhw - 5 */
+ENTRY(_evt_ivhw)
+       SAVE_CONTEXT
+#ifdef CONFIG_FRAME_POINTER
+       fp = 0;
+#endif
+#ifdef ANOMALY_05000283
+       cc = r7 == r7;
+       p5.h = 0xffc0;
+       p5.l = 0x0014;
+       if cc jump 1f;
+       r7.l = W[p5];
+1:
+#endif
+       p0.l = lo(TBUFCTL);
+       p0.h = hi(TBUFCTL);
+       r0 = 1;
+       [p0] = r0;
+       r0 = IRQ_HWERR;
+       r1 = sp;
+
+#ifdef CONFIG_HARDWARE_PM
+       r7 = SEQSTAT;
+       r7 = r7 >>> 0xe;
+       r6 = 0x1F;
+       r7 = r7 & r6;
+       r5 = 0x12;
+       cc = r7 == r5;
+       if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */
+#endif
+
+       SP += -12;
+       call _irq_panic;
+       SP += 12;
+       rti;
+#ifdef CONFIG_HARDWARE_PM
+.Lcall_do_ovf:
+
+       SP += -12;
+       call _pm_overflow;
+       SP += 12;
+
+       jump .Lcommon_restore_context;
+#endif
+
+/* interrupt routine for evt2 - 2.  This is NMI.  */
+ENTRY(_evt_evt2)
+       SAVE_CONTEXT
+#ifdef CONFIG_FRAME_POINTER
+       fp = 0;
+#endif
+#ifdef ANOMALY_05000283
+       cc = r7 == r7;
+       p5.h = 0xffc0;
+       p5.l = 0x0014;
+       if cc jump 1f;
+       r7.l = W[p5];
+1:
+#endif
+       r0 = IRQ_NMI;
+       r1 =  sp;
+       SP += -12;
+       call _asm_do_IRQ;
+       SP += 12;
+       RESTORE_CONTEXT
+       rtn;
+
+/* interrupt routine for core timer - 6 */
+ENTRY(_evt_timer)
+       TIMER_INTERRUPT_ENTRY(EVT_IVTMR_P)
+
+/* interrupt routine for evt7 - 7 */
+ENTRY(_evt_evt7)
+       INTERRUPT_ENTRY(EVT_IVG7_P)
+ENTRY(_evt_evt8)
+       INTERRUPT_ENTRY(EVT_IVG8_P)
+ENTRY(_evt_evt9)
+       INTERRUPT_ENTRY(EVT_IVG9_P)
+ENTRY(_evt_evt10)
+       INTERRUPT_ENTRY(EVT_IVG10_P)
+ENTRY(_evt_evt11)
+       INTERRUPT_ENTRY(EVT_IVG11_P)
+ENTRY(_evt_evt12)
+       INTERRUPT_ENTRY(EVT_IVG12_P)
+ENTRY(_evt_evt13)
+       INTERRUPT_ENTRY(EVT_IVG13_P)
+
+
+ /* interrupt routine for system_call - 15 */
+ENTRY(_evt_system_call)
+       SAVE_CONTEXT_SYSCALL
+#ifdef CONFIG_FRAME_POINTER
+       fp = 0;
+#endif
+       call _system_call;
+       jump .Lcommon_restore_context;
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c
new file mode 100644 (file)
index 0000000..f3cf070
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * File:         arch/blackfin/mach-common/ints-priority-dc.c
+ * Based on:
+ * Author:
+ *
+ * Created:      ?
+ * Description:  Set up the interupt priorities
+ *
+ * Modified:
+ *               1996 Roman Zippel
+ *               1999 D. Jeff Dionne <jeff@uclinux.org>
+ *               2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
+ *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
+ *               2003 Metrowerks/Motorola
+ *               2003 Bas Vermeulen <bas@buyways.nl>
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#ifdef CONFIG_KGDB
+#include <linux/kgdb.h>
+#endif
+#include <asm/traps.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/irq_handler.h>
+
+/*
+ * NOTES:
+ * - we have separated the physical Hardware interrupt from the
+ * levels that the LINUX kernel sees (see the description in irq.h)
+ * -
+ */
+
+unsigned long irq_flags = 0;
+
+/* The number of spurious interrupts */
+atomic_t num_spurious;
+
+struct ivgx {
+       /* irq number for request_irq, available in mach-bf561/irq.h */
+       int irqno;
+       /* corresponding bit in the SICA_ISR0 register */
+       int isrflag0;
+       /* corresponding bit in the SICA_ISR1 register */
+       int isrflag1;
+} ivg_table[NR_PERI_INTS];
+
+struct ivg_slice {
+       /* position of first irq in ivg_table for given ivg */
+       struct ivgx *ifirst;
+       struct ivgx *istop;
+} ivg7_13[IVG13 - IVG7 + 1];
+
+static void search_IAR(void);
+
+/*
+ * Search SIC_IAR and fill tables with the irqvalues
+ * and their positions in the SIC_ISR register.
+ */
+static void __init search_IAR(void)
+{
+       unsigned ivg, irq_pos = 0;
+       for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
+               int irqn;
+
+               ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
+
+               for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
+                       int iar_shift = (irqn & 7) * 4;
+                       if (ivg ==
+                           (0xf &
+                            bfin_read32((unsigned long *)SICA_IAR0 +
+                                        (irqn >> 3)) >> iar_shift)) {
+                               ivg_table[irq_pos].irqno = IVG7 + irqn;
+                               ivg_table[irq_pos].isrflag0 =
+                                   (irqn < 32 ? (1 << irqn) : 0);
+                               ivg_table[irq_pos].isrflag1 =
+                                   (irqn < 32 ? 0 : (1 << (irqn - 32)));
+                               ivg7_13[ivg].istop++;
+                               irq_pos++;
+                       }
+               }
+       }
+}
+
+/*
+ * This is for BF561 internal IRQs
+ */
+
+static void ack_noop(unsigned int irq)
+{
+       /* Dummy function.  */
+}
+
+static void bf561_core_mask_irq(unsigned int irq)
+{
+       irq_flags &= ~(1 << irq);
+       if (!irqs_disabled())
+               local_irq_enable();
+}
+
+static void bf561_core_unmask_irq(unsigned int irq)
+{
+       irq_flags |= 1 << irq;
+       /*
+        * If interrupts are enabled, IMASK must contain the same value
+        * as irq_flags.  Make sure that invariant holds.  If interrupts
+        * are currently disabled we need not do anything; one of the
+        * callers will take care of setting IMASK to the proper value
+        * when reenabling interrupts.
+        * local_irq_enable just does "STI irq_flags", so it's exactly
+        * what we need.
+        */
+       if (!irqs_disabled())
+               local_irq_enable();
+       return;
+}
+
+static void bf561_internal_mask_irq(unsigned int irq)
+{
+       unsigned long irq_mask;
+       if ((irq - (IRQ_CORETMR + 1)) < 32) {
+               irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
+               bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() & ~irq_mask);
+       } else {
+               irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
+               bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() & ~irq_mask);
+       }
+}
+
+static void bf561_internal_unmask_irq(unsigned int irq)
+{
+       unsigned long irq_mask;
+
+       if ((irq - (IRQ_CORETMR + 1)) < 32) {
+               irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
+               bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() | irq_mask);
+       } else {
+               irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
+               bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() | irq_mask);
+       }
+       SSYNC();
+}
+
+static struct irq_chip bf561_core_irqchip = {
+       .ack = ack_noop,
+       .mask = bf561_core_mask_irq,
+       .unmask = bf561_core_unmask_irq,
+};
+
+static struct irq_chip bf561_internal_irqchip = {
+       .ack = ack_noop,
+       .mask = bf561_internal_mask_irq,
+       .unmask = bf561_internal_unmask_irq,
+};
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+static void bf561_gpio_ack_irq(unsigned int irq)
+{
+       u16 gpionr = irq - IRQ_PF0;
+
+       if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+               set_gpio_data(gpionr, 0);
+               SSYNC();
+       }
+}
+
+static void bf561_gpio_mask_ack_irq(unsigned int irq)
+{
+       u16 gpionr = irq - IRQ_PF0;
+
+       if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+               set_gpio_data(gpionr, 0);
+               SSYNC();
+       }
+
+       set_gpio_maska(gpionr, 0);
+       SSYNC();
+}
+
+static void bf561_gpio_mask_irq(unsigned int irq)
+{
+       set_gpio_maska(irq - IRQ_PF0, 0);
+       SSYNC();
+}
+
+static void bf561_gpio_unmask_irq(unsigned int irq)
+{
+       set_gpio_maska(irq - IRQ_PF0, 1);
+       SSYNC();
+}
+
+static unsigned int bf561_gpio_irq_startup(unsigned int irq)
+{
+       unsigned int ret;
+       u16 gpionr = irq - IRQ_PF0;
+
+       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+
+               ret = gpio_request(gpionr, NULL);
+               if(ret)
+                       return ret;
+
+       }
+
+       gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+       bf561_gpio_unmask_irq(irq);
+
+  return ret;
+
+}
+
+static void bf561_gpio_irq_shutdown(unsigned int irq)
+{
+       bf561_gpio_mask_irq(irq);
+       gpio_free(irq - IRQ_PF0);
+       gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
+}
+
+static int bf561_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+
+       unsigned int ret;
+       u16 gpionr = irq - IRQ_PF0;
+
+
+               if (type == IRQ_TYPE_PROBE) {
+                       /* only probe unenabled GPIO interrupt lines */
+                       if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+                               return 0;
+                       type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+               }
+
+               if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+                           IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+
+               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+
+                       ret = gpio_request(gpionr, NULL);
+                       if(ret)
+                               return ret;
+
+               }
+
+                       gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+               } else {
+                       gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+                       return 0;
+               }
+
+
+               set_gpio_dir(gpionr, 0);
+               set_gpio_inen(gpionr, 1);
+
+
+               if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+                       gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+                       set_gpio_edge(gpionr, 1);
+               } else {
+                       set_gpio_edge(gpionr, 0);
+                       gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+               }
+
+               if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+                   == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+                       set_gpio_both(gpionr, 1);
+               else
+                       set_gpio_both(gpionr, 0);
+
+               if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+                       set_gpio_polar(gpionr, 1);      /* low or falling edge denoted by one */
+               else
+                       set_gpio_polar(gpionr, 0);      /* high or rising edge denoted by zero */
+
+       SSYNC();
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+               set_irq_handler(irq, handle_edge_irq);
+       else
+               set_irq_handler(irq, handle_level_irq);
+
+       return 0;
+}
+
+static struct irq_chip bf561_gpio_irqchip = {
+       .ack = bf561_gpio_ack_irq,
+       .mask = bf561_gpio_mask_irq,
+       .mask_ack = bf561_gpio_mask_ack_irq,
+       .unmask = bf561_gpio_unmask_irq,
+       .set_type = bf561_gpio_irq_type,
+       .startup = bf561_gpio_irq_startup,
+       .shutdown = bf561_gpio_irq_shutdown
+};
+
+static void bf561_demux_gpio_irq(unsigned int inta_irq,
+                                struct irq_desc *intb_desc)
+{
+       int irq, flag_d, mask;
+       u16 gpio;
+
+       switch (inta_irq) {
+       case IRQ_PROG0_INTA:
+               irq = IRQ_PF0;
+               break;
+       case IRQ_PROG1_INTA:
+               irq = IRQ_PF16;
+               break;
+       case IRQ_PROG2_INTA:
+               irq = IRQ_PF32;
+               break;
+       default:
+               dump_stack();
+               return;
+       }
+
+       gpio = irq - IRQ_PF0;
+
+               flag_d = get_gpiop_data(gpio);
+               mask = flag_d & (gpio_enabled[gpio_bank(gpio)] &
+                             get_gpiop_maska(gpio));
+
+                       do {
+                               if (mask & 1) {
+                                       struct irq_desc *desc = irq_desc + irq;
+                                       desc->handle_irq(irq, desc);
+                               }
+                               irq++;
+                               mask >>= 1;
+                       } while (mask);
+
+
+}
+
+#endif                         /* CONFIG_IRQCHIP_DEMUX_GPIO */
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the BFin IRQ handling routines.
+ */
+int __init init_arch_irq(void)
+{
+       int irq;
+       unsigned long ilat = 0;
+       /*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
+       bfin_write_SICA_IMASK0(SIC_UNMASK_ALL);
+       bfin_write_SICA_IMASK1(SIC_UNMASK_ALL);
+       SSYNC();
+
+       local_irq_disable();
+
+       init_exception_buff();
+
+#ifndef CONFIG_KGDB
+       bfin_write_EVT0(evt_emulation);
+#endif
+       bfin_write_EVT2(evt_evt2);
+       bfin_write_EVT3(trap);
+       bfin_write_EVT5(evt_ivhw);
+       bfin_write_EVT6(evt_timer);
+       bfin_write_EVT7(evt_evt7);
+       bfin_write_EVT8(evt_evt8);
+       bfin_write_EVT9(evt_evt9);
+       bfin_write_EVT10(evt_evt10);
+       bfin_write_EVT11(evt_evt11);
+       bfin_write_EVT12(evt_evt12);
+       bfin_write_EVT13(evt_evt13);
+       bfin_write_EVT14(evt14_softirq);
+       bfin_write_EVT15(evt_system_call);
+       CSYNC();
+
+       for (irq = 0; irq < SYS_IRQS; irq++) {
+               if (irq <= IRQ_CORETMR)
+                       set_irq_chip(irq, &bf561_core_irqchip);
+               else
+                       set_irq_chip(irq, &bf561_internal_irqchip);
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+               if ((irq != IRQ_PROG0_INTA) &&
+                   (irq != IRQ_PROG1_INTA) && (irq != IRQ_PROG2_INTA)) {
+#endif
+                       set_irq_handler(irq, handle_simple_irq);
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+               } else {
+                       set_irq_chained_handler(irq, bf561_demux_gpio_irq);
+               }
+#endif
+
+       }
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+       for (irq = IRQ_PF0; irq <= IRQ_PF47; irq++) {
+               set_irq_chip(irq, &bf561_gpio_irqchip);
+               /* if configured as edge, then will be changed to do_edge_IRQ */
+               set_irq_handler(irq, handle_level_irq);
+       }
+#endif
+       bfin_write_IMASK(0);
+       CSYNC();
+       ilat = bfin_read_ILAT();
+       CSYNC();
+       bfin_write_ILAT(ilat);
+       CSYNC();
+
+       printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
+       /* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
+        * local_irq_enable()
+        */
+       program_IAR();
+       /* Therefore it's better to setup IARs before interrupts enabled */
+       search_IAR();
+
+       /* Enable interrupts IVG7-15 */
+       irq_flags = irq_flags | IMASK_IVG15 |
+           IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
+           IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+
+       return 0;
+}
+
+#ifdef CONFIG_DO_IRQ_L1
+void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text));
+#endif
+
+void do_irq(int vec, struct pt_regs *fp)
+{
+       if (vec == EVT_IVTMR_P) {
+               vec = IRQ_CORETMR;
+       } else {
+               struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
+               struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
+               unsigned long sic_status0, sic_status1;
+
+               SSYNC();
+               sic_status0 = bfin_read_SICA_IMASK0() & bfin_read_SICA_ISR0();
+               sic_status1 = bfin_read_SICA_IMASK1() & bfin_read_SICA_ISR1();
+
+               for (;; ivg++) {
+                       if (ivg >= ivg_stop) {
+                               atomic_inc(&num_spurious);
+                               return;
+                       } else if ((sic_status0 & ivg->isrflag0) ||
+                                  (sic_status1 & ivg->isrflag1))
+                               break;
+               }
+               vec = ivg->irqno;
+       }
+       asm_do_IRQ(vec, fp);
+
+#ifdef CONFIG_KGDB
+       kgdb_process_breakpoint();
+#endif
+}
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c
new file mode 100644 (file)
index 0000000..34b6228
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * File:         arch/blackfin/mach-common/ints-priority-sc.c
+ * Based on:
+ * Author:
+ *
+ * Created:      ?
+ * Description:  Set up the interupt priorities
+ *
+ * Modified:
+ *               1996 Roman Zippel
+ *               1999 D. Jeff Dionne <jeff@uclinux.org>
+ *               2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
+ *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
+ *               2003 Metrowerks/Motorola
+ *               2003 Bas Vermeulen <bas@buyways.nl>
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#ifdef CONFIG_KGDB
+#include <linux/kgdb.h>
+#endif
+#include <asm/traps.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/irq_handler.h>
+
+#ifdef BF537_FAMILY
+# define BF537_GENERIC_ERROR_INT_DEMUX
+#else
+# undef BF537_GENERIC_ERROR_INT_DEMUX
+#endif
+
+/*
+ * NOTES:
+ * - we have separated the physical Hardware interrupt from the
+ * levels that the LINUX kernel sees (see the description in irq.h)
+ * -
+ */
+
+unsigned long irq_flags = 0;
+
+/* The number of spurious interrupts */
+atomic_t num_spurious;
+
+struct ivgx {
+       /* irq number for request_irq, available in mach-bf533/irq.h */
+       int irqno;
+       /* corresponding bit in the SIC_ISR register */
+       int isrflag;
+} ivg_table[NR_PERI_INTS];
+
+struct ivg_slice {
+       /* position of first irq in ivg_table for given ivg */
+       struct ivgx *ifirst;
+       struct ivgx *istop;
+} ivg7_13[IVG13 - IVG7 + 1];
+
+static void search_IAR(void);
+
+/*
+ * Search SIC_IAR and fill tables with the irqvalues
+ * and their positions in the SIC_ISR register.
+ */
+static void __init search_IAR(void)
+{
+       unsigned ivg, irq_pos = 0;
+       for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
+               int irqn;
+
+               ivg7_13[ivg].istop = ivg7_13[ivg].ifirst =
+                   &ivg_table[irq_pos];
+
+               for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
+                       int iar_shift = (irqn & 7) * 4;
+                       if (ivg ==
+                           (0xf &
+                            bfin_read32((unsigned long *) SIC_IAR0 +
+                                        (irqn >> 3)) >> iar_shift)) {
+                               ivg_table[irq_pos].irqno = IVG7 + irqn;
+                               ivg_table[irq_pos].isrflag = 1 << irqn;
+                               ivg7_13[ivg].istop++;
+                               irq_pos++;
+                       }
+               }
+       }
+}
+
+/*
+ * This is for BF533 internal IRQs
+ */
+
+static void ack_noop(unsigned int irq)
+{
+       /* Dummy function.  */
+}
+
+static void bfin_core_mask_irq(unsigned int irq)
+{
+       irq_flags &= ~(1 << irq);
+       if (!irqs_disabled())
+               local_irq_enable();
+}
+
+static void bfin_core_unmask_irq(unsigned int irq)
+{
+       irq_flags |= 1 << irq;
+       /*
+        * If interrupts are enabled, IMASK must contain the same value
+        * as irq_flags.  Make sure that invariant holds.  If interrupts
+        * are currently disabled we need not do anything; one of the
+        * callers will take care of setting IMASK to the proper value
+        * when reenabling interrupts.
+        * local_irq_enable just does "STI irq_flags", so it's exactly
+        * what we need.
+        */
+       if (!irqs_disabled())
+               local_irq_enable();
+       return;
+}
+
+static void bfin_internal_mask_irq(unsigned int irq)
+{
+       bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
+                            ~(1 << (irq - (IRQ_CORETMR + 1))));
+       SSYNC();
+}
+
+static void bfin_internal_unmask_irq(unsigned int irq)
+{
+       bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
+                            (1 << (irq - (IRQ_CORETMR + 1))));
+       SSYNC();
+}
+
+static struct irq_chip bfin_core_irqchip = {
+       .ack = ack_noop,
+       .mask = bfin_core_mask_irq,
+       .unmask = bfin_core_unmask_irq,
+};
+
+static struct irq_chip bfin_internal_irqchip = {
+       .ack = ack_noop,
+       .mask = bfin_internal_mask_irq,
+       .unmask = bfin_internal_unmask_irq,
+};
+
+#ifdef BF537_GENERIC_ERROR_INT_DEMUX
+static int error_int_mask;
+
+static void bfin_generic_error_ack_irq(unsigned int irq)
+{
+
+}
+
+static void bfin_generic_error_mask_irq(unsigned int irq)
+{
+       error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));
+
+       if (!error_int_mask) {
+               local_irq_disable();
+               bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
+                                    ~(1 <<
+                                      (IRQ_GENERIC_ERROR -
+                                       (IRQ_CORETMR + 1))));
+               SSYNC();
+               local_irq_enable();
+       }
+}
+
+static void bfin_generic_error_unmask_irq(unsigned int irq)
+{
+       local_irq_disable();
+       bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | 1 <<
+                            (IRQ_GENERIC_ERROR - (IRQ_CORETMR + 1)));
+       SSYNC();
+       local_irq_enable();
+
+       error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
+}
+
+static struct irq_chip bfin_generic_error_irqchip = {
+       .ack = bfin_generic_error_ack_irq,
+       .mask = bfin_generic_error_mask_irq,
+       .unmask = bfin_generic_error_unmask_irq,
+};
+
+static void bfin_demux_error_irq(unsigned int int_err_irq,
+                                 struct irq_desc *intb_desc)
+{
+       int irq = 0;
+
+       SSYNC();
+
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
+       if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK)
+               irq = IRQ_MAC_ERROR;
+       else
+#endif
+       if (bfin_read_SPORT0_STAT() & SPORT_ERR_MASK)
+               irq = IRQ_SPORT0_ERROR;
+       else if (bfin_read_SPORT1_STAT() & SPORT_ERR_MASK)
+               irq = IRQ_SPORT1_ERROR;
+       else if (bfin_read_PPI_STATUS() & PPI_ERR_MASK)
+               irq = IRQ_PPI_ERROR;
+       else if (bfin_read_CAN_GIF() & CAN_ERR_MASK)
+               irq = IRQ_CAN_ERROR;
+       else if (bfin_read_SPI_STAT() & SPI_ERR_MASK)
+               irq = IRQ_SPI_ERROR;
+       else if ((bfin_read_UART0_IIR() & UART_ERR_MASK_STAT1) &&
+                (bfin_read_UART0_IIR() & UART_ERR_MASK_STAT0))
+               irq = IRQ_UART0_ERROR;
+       else if ((bfin_read_UART1_IIR() & UART_ERR_MASK_STAT1) &&
+                (bfin_read_UART1_IIR() & UART_ERR_MASK_STAT0))
+               irq = IRQ_UART1_ERROR;
+
+       if (irq) {
+               if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) {
+                       struct irq_desc *desc = irq_desc + irq;
+                       desc->handle_irq(irq, desc);
+               } else {
+
+                       switch (irq) {
+                       case IRQ_PPI_ERROR:
+                               bfin_write_PPI_STATUS(PPI_ERR_MASK);
+                               break;
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
+                       case IRQ_MAC_ERROR:
+                               bfin_write_EMAC_SYSTAT(EMAC_ERR_MASK);
+                               break;
+#endif
+                       case IRQ_SPORT0_ERROR:
+                               bfin_write_SPORT0_STAT(SPORT_ERR_MASK);
+                               break;
+
+                       case IRQ_SPORT1_ERROR:
+                               bfin_write_SPORT1_STAT(SPORT_ERR_MASK);
+                               break;
+
+                       case IRQ_CAN_ERROR:
+                               bfin_write_CAN_GIS(CAN_ERR_MASK);
+                               break;
+
+                       case IRQ_SPI_ERROR:
+                               bfin_write_SPI_STAT(SPI_ERR_MASK);
+                               break;
+
+                       default:
+                               break;
+                       }
+
+                       pr_debug("IRQ %d:"
+                               " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
+                               irq);
+               }
+       } else
+               printk(KERN_ERR
+                      "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
+                      " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
+                      __FUNCTION__, __FILE__, __LINE__);
+
+
+}
+#endif                         /* BF537_GENERIC_ERROR_INT_DEMUX */
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+
+static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+static void bfin_gpio_ack_irq(unsigned int irq)
+{
+       u16 gpionr = irq - IRQ_PF0;
+
+       if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+               set_gpio_data(gpionr, 0);
+               SSYNC();
+       }
+}
+
+static void bfin_gpio_mask_ack_irq(unsigned int irq)
+{
+       u16 gpionr = irq - IRQ_PF0;
+
+       if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+               set_gpio_data(gpionr, 0);
+               SSYNC();
+       }
+
+       set_gpio_maska(gpionr, 0);
+       SSYNC();
+}
+
+static void bfin_gpio_mask_irq(unsigned int irq)
+{
+       set_gpio_maska(irq - IRQ_PF0, 0);
+       SSYNC();
+}
+
+static void bfin_gpio_unmask_irq(unsigned int irq)
+{
+       set_gpio_maska(irq - IRQ_PF0, 1);
+       SSYNC();
+}
+
+static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+{
+       unsigned int ret;
+       u16 gpionr = irq - IRQ_PF0;
+
+       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+               ret = gpio_request(gpionr, NULL);
+               if (ret)
+                       return ret;
+       }
+
+       gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+       bfin_gpio_unmask_irq(irq);
+
+       return ret;
+}
+
+static void bfin_gpio_irq_shutdown(unsigned int irq)
+{
+       bfin_gpio_mask_irq(irq);
+       gpio_free(irq - IRQ_PF0);
+       gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
+}
+
+static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+
+       unsigned int ret;
+       u16 gpionr = irq - IRQ_PF0;
+
+       if (type == IRQ_TYPE_PROBE) {
+               /* only probe unenabled GPIO interrupt lines */
+               if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+                       return 0;
+               type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+       }
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+                   IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+       {
+               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+                       ret = gpio_request(gpionr, NULL);
+                       if (ret)
+                               return ret;
+               }
+
+               gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+       } else {
+               gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+               return 0;
+       }
+
+       set_gpio_dir(gpionr, 0);
+       set_gpio_inen(gpionr, 1);
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+               gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+               set_gpio_edge(gpionr, 1);
+       } else {
+               set_gpio_edge(gpionr, 0);
+               gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+       }
+
+       if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+           == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+               set_gpio_both(gpionr, 1);
+       else
+               set_gpio_both(gpionr, 0);
+
+       if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+               set_gpio_polar(gpionr, 1);      /* low or falling edge denoted by one */
+       else
+               set_gpio_polar(gpionr, 0);      /* high or rising edge denoted by zero */
+
+       SSYNC();
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+               set_irq_handler(irq, handle_edge_irq);
+       else
+               set_irq_handler(irq, handle_level_irq);
+
+       return 0;
+}
+
+
+static struct irq_chip bfin_gpio_irqchip = {
+       .ack = bfin_gpio_ack_irq,
+       .mask = bfin_gpio_mask_irq,
+       .mask_ack = bfin_gpio_mask_ack_irq,
+       .unmask = bfin_gpio_unmask_irq,
+       .set_type = bfin_gpio_irq_type,
+       .startup = bfin_gpio_irq_startup,
+       .shutdown = bfin_gpio_irq_shutdown
+};
+
+static void bfin_demux_gpio_irq(unsigned int intb_irq,
+                                struct irq_desc *intb_desc)
+{
+       u16 i;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=16) {
+               int irq = IRQ_PF0 + i;
+               int flag_d = get_gpiop_data(i);
+               int mask =
+                       flag_d & (gpio_enabled[gpio_bank(i)] &
+                             get_gpiop_maska(i));
+
+               while (mask) {
+                       if (mask & 1) {
+                               struct irq_desc *desc = irq_desc + irq;
+                               desc->handle_irq(irq, desc);
+                       }
+                       irq++;
+                       mask >>= 1;
+               }
+       }
+}
+
+#endif                         /* CONFIG_IRQCHIP_DEMUX_GPIO */
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the BFin IRQ handling routines.
+ */
+int __init init_arch_irq(void)
+{
+       int irq;
+       unsigned long ilat = 0;
+       /*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
+       bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
+       SSYNC();
+
+       local_irq_disable();
+
+#ifndef CONFIG_KGDB
+       bfin_write_EVT0(evt_emulation);
+#endif
+       bfin_write_EVT2(evt_evt2);
+       bfin_write_EVT3(trap);
+       bfin_write_EVT5(evt_ivhw);
+       bfin_write_EVT6(evt_timer);
+       bfin_write_EVT7(evt_evt7);
+       bfin_write_EVT8(evt_evt8);
+       bfin_write_EVT9(evt_evt9);
+       bfin_write_EVT10(evt_evt10);
+       bfin_write_EVT11(evt_evt11);
+       bfin_write_EVT12(evt_evt12);
+       bfin_write_EVT13(evt_evt13);
+       bfin_write_EVT14(evt14_softirq);
+       bfin_write_EVT15(evt_system_call);
+       CSYNC();
+
+       for (irq = 0; irq < SYS_IRQS; irq++) {
+               if (irq <= IRQ_CORETMR)
+                       set_irq_chip(irq, &bfin_core_irqchip);
+               else
+                       set_irq_chip(irq, &bfin_internal_irqchip);
+#ifdef BF537_GENERIC_ERROR_INT_DEMUX
+               if (irq != IRQ_GENERIC_ERROR) {
+#endif
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+                       if ((irq != IRQ_PROG_INTA) /*PORT F & G MASK_A Interrupt*/
+# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+                               && (irq != IRQ_MAC_RX) /*PORT H MASK_A Interrupt*/
+# endif
+                           ) {
+#endif
+                               set_irq_handler(irq, handle_simple_irq);
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+                       } else {
+                               set_irq_chained_handler(irq,
+                                                       bfin_demux_gpio_irq);
+                       }
+#endif
+
+#ifdef BF537_GENERIC_ERROR_INT_DEMUX
+               } else {
+                       set_irq_handler(irq, bfin_demux_error_irq);
+               }
+#endif
+       }
+#ifdef BF537_GENERIC_ERROR_INT_DEMUX
+       for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++) {
+               set_irq_chip(irq, &bfin_generic_error_irqchip);
+               set_irq_handler(irq, handle_level_irq);
+       }
+#endif
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+       for (irq = IRQ_PF0; irq < NR_IRQS; irq++) {
+               set_irq_chip(irq, &bfin_gpio_irqchip);
+               /* if configured as edge, then will be changed to do_edge_IRQ */
+               set_irq_handler(irq, handle_level_irq);
+       }
+#endif
+       bfin_write_IMASK(0);
+       CSYNC();
+       ilat = bfin_read_ILAT();
+       CSYNC();
+       bfin_write_ILAT(ilat);
+       CSYNC();
+
+       printk(KERN_INFO
+              "Configuring Blackfin Priority Driven Interrupts\n");
+       /* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
+        * local_irq_enable()
+        */
+       program_IAR();
+       /* Therefore it's better to setup IARs before interrupts enabled */
+       search_IAR();
+
+       /* Enable interrupts IVG7-15 */
+       irq_flags = irq_flags | IMASK_IVG15 |
+           IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
+           IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 |
+           IMASK_IVGHW;
+
+       return 0;
+}
+
+#ifdef CONFIG_DO_IRQ_L1
+void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text));
+#endif
+
+void do_irq(int vec, struct pt_regs *fp)
+{
+       if (vec == EVT_IVTMR_P) {
+               vec = IRQ_CORETMR;
+       } else {
+               struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
+               struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
+               unsigned long sic_status;
+
+               SSYNC();
+               sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
+
+               for (;; ivg++) {
+                       if (ivg >= ivg_stop) {
+                               atomic_inc(&num_spurious);
+                               return;
+                       } else if (sic_status & ivg->isrflag)
+                               break;
+               }
+               vec = ivg->irqno;
+       }
+       asm_do_IRQ(vec, fp);
+
+#ifdef CONFIG_KGDB
+       kgdb_process_breakpoint();
+#endif
+}
diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c
new file mode 100644 (file)
index 0000000..f05e3da
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * File:         arch/blackfin/mach-common/irqpanic.c
+ * Based on:
+ * Author:
+ *
+ * Created:      ?
+ * Description:  panic kernel with dump information
+ *
+ * Modified:     rgetz - added cache checking code 14Feb06
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <asm/traps.h>
+#include <asm/blackfin.h>
+
+#include "../oprofile/op_blackfin.h"
+
+#ifdef CONFIG_DEBUG_ICACHE_CHECK
+#define L1_ICACHE_START 0xffa10000
+#define L1_ICACHE_END   0xffa13fff
+void irq_panic(int reason, struct pt_regs *regs) __attribute__ ((l1_text));
+#endif
+
+/*
+ * irq_panic - calls panic with string setup
+ */
+asmlinkage void irq_panic(int reason, struct pt_regs *regs)
+{
+       int sig = 0;
+       siginfo_t info;
+
+#ifdef CONFIG_DEBUG_ICACHE_CHECK
+       unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
+       unsigned short i, j, die;
+       unsigned int bad[10][6];
+
+       /* check entire cache for coherency
+        * Since printk is in cacheable memory,
+        * don't call it until you have checked everything
+       */
+
+       die = 0;
+       i = 0;
+
+       /* check icache */
+
+       for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) {
+
+               /* Grab various address bits for the itest_cmd fields                      */
+               cmd = (((ca & 0x3000) << 4) |   /* ca[13:12] for SBNK[1:0]             */
+                      ((ca & 0x0c00) << 16) |  /* ca[11:10] for WAYSEL[1:0]           */
+                      ((ca & 0x3f8)) | /* ca[09:03] for SET[4:0] and DW[1:0]  */
+                      0);      /* Access Tag, Read access             */
+
+               SSYNC();
+               bfin_write_ITEST_COMMAND(cmd);
+               SSYNC();
+               tag = bfin_read_ITEST_DATA0();
+               SSYNC();
+
+               /* if tag is marked as valid, check it */
+               if (tag & 1) {
+                       /* The icache is arranged in 4 groups of 64-bits */
+                       for (j = 0; j < 32; j += 8) {
+                               cmd = ((((ca + j) & 0x3000) << 4) |     /* ca[13:12] for SBNK[1:0]             */
+                                      (((ca + j) & 0x0c00) << 16) |    /* ca[11:10] for WAYSEL[1:0]           */
+                                      (((ca + j) & 0x3f8)) |   /* ca[09:03] for SET[4:0] and DW[1:0]  */
+                                      4);      /* Access Data, Read access             */
+
+                               SSYNC();
+                               bfin_write_ITEST_COMMAND(cmd);
+                               SSYNC();
+
+                               cache_hi = bfin_read_ITEST_DATA1();
+                               cache_lo = bfin_read_ITEST_DATA0();
+
+                               pa = ((unsigned int *)((tag & 0xffffcc00) |
+                                                      ((ca + j) & ~(0xffffcc00))));
+
+                               /*
+                                * Debugging this, enable
+                                *
+                                * printk("addr: %08x %08x%08x | %08x%08x\n",
+                                *  ((unsigned int *)((tag & 0xffffcc00)  | ((ca+j) & ~(0xffffcc00)))),
+                                *   cache_hi, cache_lo, *(pa+1), *pa);
+                                */
+
+                               if (cache_hi != *(pa + 1) || cache_lo != *pa) {
+                                       /* Since icache is not working, stay out of it, by not printing */
+                                       die = 1;
+                                       bad[i][0] = (ca + j);
+                                       bad[i][1] = cache_hi;
+                                       bad[i][2] = cache_lo;
+                                       bad[i][3] = ((tag & 0xffffcc00) |
+                                               ((ca + j) & ~(0xffffcc00)));
+                                       bad[i][4] = *(pa + 1);
+                                       bad[i][5] = *(pa);
+                                       i++;
+                               }
+                       }
+               }
+       }
+       if (die) {
+               printk(KERN_EMERG "icache coherency error\n");
+               for (j = 0; j <= i; j++) {
+                       printk(KERN_EMERG
+                           "cache address   : %08x  cache value : %08x%08x\n",
+                            bad[j][0], bad[j][1], bad[j][2]);
+                       printk(KERN_EMERG
+                           "physical address: %08x  SDRAM value : %08x%08x\n",
+                            bad[j][3], bad[j][4], bad[j][5]);
+               }
+               panic("icache coherency error");
+       } else {
+               printk(KERN_EMERG "icache checked, and OK\n");
+       }
+#endif
+
+       printk(KERN_EMERG "\n");
+       printk(KERN_EMERG "Exception: IRQ 0x%x entered\n", reason);
+       printk(KERN_EMERG " code=[0x%08lx],   stack frame=0x%08lx,  "
+           " bad PC=0x%08lx\n",
+           (unsigned long)regs->seqstat,
+           (unsigned long)regs,
+           (unsigned long)regs->pc);
+       if (reason == 0x5) {
+               printk(KERN_EMERG "----------- HARDWARE ERROR -----------\n");
+
+               /* There is only need to check for Hardware Errors, since other
+                * EXCEPTIONS are handled in TRAPS.c (MH)
+                */
+               switch (regs->seqstat & SEQSTAT_HWERRCAUSE) {
+               case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):   /* System MMR Error */
+                       info.si_code = BUS_ADRALN;
+                       sig = SIGBUS;
+                       printk(KERN_EMERG HWC_x2);
+                       break;
+               case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):  /* External Memory Addressing Error */
+                       info.si_code = BUS_ADRERR;
+                       sig = SIGBUS;
+                       printk(KERN_EMERG HWC_x3);
+                       break;
+               case (SEQSTAT_HWERRCAUSE_PERF_FLOW):    /* Performance Monitor Overflow */
+                       printk(KERN_EMERG HWC_x12);
+                       break;
+               case (SEQSTAT_HWERRCAUSE_RAISE_5):      /* RAISE 5 instruction */
+                       printk(KERN_EMERG HWC_x18);
+                       break;
+               default:        /* Reserved */
+                       printk(KERN_EMERG HWC_default);
+                       break;
+               }
+       }
+
+       regs->ipend = bfin_read_IPEND();
+       dump_bfin_regs(regs, (void *)regs->pc);
+       if (0 == (info.si_signo = sig) || 0 == user_mode(regs)) /* in kernelspace */
+               panic("Unhandled IRQ or exceptions!\n");
+       else {                  /* in userspace */
+               info.si_errno = 0;
+               info.si_addr = (void *)regs->pc;
+               force_sig_info(sig, &info, current);
+       }
+}
+
+#ifdef CONFIG_HARDWARE_PM
+/*
+ * call the handler of Performance overflow
+ */
+asmlinkage void pm_overflow(int irq, struct pt_regs *regs)
+{
+       pm_overflow_handler(irq, regs);
+}
+#endif
diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S
new file mode 100644 (file)
index 0000000..2cbb15b
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * File:         arch/blackfin/mach-common/lock.S
+ * Based on:
+ * Author:       LG Soft India
+ *
+ * Created:      ?
+ * Description:  kernel locks
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/cplb.h>
+#include <asm/blackfin.h>
+
+.text
+
+#ifdef CONFIG_BLKFIN_CACHE_LOCK
+
+/* When you come here, it is assumed that
+ * R0 - Which way to be locked
+ */
+
+ENTRY(_cache_grab_lock)
+
+       [--SP]=( R7:0,P5:0 );
+
+       P1.H = (IMEM_CONTROL >> 16);
+       P1.L = (IMEM_CONTROL & 0xFFFF);
+       P5.H = (ICPLB_ADDR0 >> 16);
+       P5.L = (ICPLB_ADDR0 & 0xFFFF);
+       P4.H = (ICPLB_DATA0 >> 16);
+       P4.L = (ICPLB_DATA0 & 0xFFFF);
+       R7 = R0;
+
+       /* If the code of interest already resides in the cache
+        * invalidate the entire cache itself.
+        * invalidate_entire_icache;
+        */
+
+       SP += -12;
+       [--SP] = RETS;
+       CALL _invalidate_entire_icache;
+       RETS = [SP++];
+       SP += 12;
+
+       /* Disable the Interrupts*/
+
+       CLI R3;
+
+.LLOCK_WAY:
+
+       /* Way0 - 0xFFA133E0
+        * Way1 - 0xFFA137E0
+        * Way2 - 0xFFA13BE0    Total Way Size = 4K
+        * Way3 - 0xFFA13FE0
+        */
+
+       /* Procedure Ex. -Set the locks for other ways by setting ILOC[3:1]
+        * Only Way0 of the instruction cache can now be
+        * replaced by a new code
+        */
+
+       R5 = R7;
+       CC = BITTST(R7,0);
+       IF CC JUMP .LCLEAR1;
+       R7 = 0;
+       BITSET(R7,0);
+       JUMP .LDONE1;
+
+.LCLEAR1:
+       R7 = 0;
+       BITCLR(R7,0);
+.LDONE1:       R4 = R7 << 3;
+       R7 = [P1];
+       R7 = R7 | R4;
+       SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
+       .align 8;
+       [P1] = R7;
+       SSYNC;
+
+       R7 = R5;
+       CC = BITTST(R7,1);
+       IF CC JUMP .LCLEAR2;
+       R7 = 0;
+       BITSET(R7,1);
+       JUMP .LDONE2;
+
+.LCLEAR2:
+       R7 = 0;
+       BITCLR(R7,1);
+.LDONE2:       R4 = R7 << 3;
+       R7 = [P1];
+       R7 = R7 | R4;
+       SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
+       .align 8;
+       [P1] = R7;
+       SSYNC;
+
+       R7 = R5;
+       CC = BITTST(R7,2);
+       IF CC JUMP .LCLEAR3;
+       R7 = 0;
+       BITSET(R7,2);
+       JUMP .LDONE3;
+.LCLEAR3:
+       R7 = 0;
+       BITCLR(R7,2);
+.LDONE3:       R4 = R7 << 3;
+       R7 = [P1];
+       R7 = R7 | R4;
+       SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
+       .align 8;
+       [P1] = R7;
+       SSYNC;
+
+
+       R7 = R5;
+       CC = BITTST(R7,3);
+       IF CC JUMP .LCLEAR4;
+       R7 = 0;
+       BITSET(R7,3);
+       JUMP .LDONE4;
+.LCLEAR4:
+       R7 = 0;
+       BITCLR(R7,3);
+.LDONE4:       R4 = R7 << 3;
+       R7 = [P1];
+       R7 = R7 | R4;
+       SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
+       .align 8;
+       [P1] = R7;
+       SSYNC;
+
+       STI R3;
+
+       ( R7:0,P5:0 ) = [SP++];
+
+       RTS;
+
+/* After the execution of critical code, the code is now locked into
+ * the cache way. Now we need to set ILOC.
+ *
+ * R0 - Which way to be locked
+ */
+
+ENTRY(_cache_lock)
+
+       [--SP]=( R7:0,P5:0 );
+
+       P1.H = (IMEM_CONTROL >> 16);
+       P1.L = (IMEM_CONTROL & 0xFFFF);
+
+       /* Disable the Interrupts*/
+       CLI R3;
+
+       R7 = [P1];
+       R2 = 0xFFFFFF87 (X);
+       R7 = R7 & R2;
+       R0 = R0 << 3;
+       R7 = R0 | R7;
+       SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
+       .align 8;
+       [P1] = R7;
+       SSYNC;
+       /* Renable the Interrupts */
+       STI R3;
+
+       ( R7:0,P5:0 ) = [SP++];
+       RTS;
+
+#endif /* BLKFIN_CACHE_LOCK */
+
+/* Return the ILOC bits of IMEM_CONTROL
+ */
+
+ENTRY(_read_iloc)
+
+       P1.H = (IMEM_CONTROL >> 16);
+       P1.L = (IMEM_CONTROL & 0xFFFF);
+       R1 = 0xF;
+       R0 = [P1];
+       R0 = R0 >> 3;
+       R0 = R0 & R1;
+
+       RTS;
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
new file mode 100644 (file)
index 0000000..deb2727
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * File:         arch/blackfin/mach-common/pm.c
+ * Based on:     arm/mach-omap/pm.c
+ * Author:       Cliff Brake <cbrake@accelent.com> Copyright (c) 2001
+ *
+ * Created:      2001
+ * Description:  Power management for the bfin
+ *
+ * Modified:     Nicolas Pitre - PXA250 support
+ *                Copyright (c) 2002 Monta Vista Software, Inc.
+ *               David Singleton - OMAP1510
+ *                Copyright (c) 2002 Monta Vista Software, Inc.
+ *               Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610
+ *                Copyright 2004
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+
+#include <asm/io.h>
+#include <asm/dpmc.h>
+#include <asm/irq.h>
+
+
+#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
+#define WAKEUP_TYPE    PM_WAKE_HIGH
+#endif
+
+#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_L
+#define WAKEUP_TYPE    PM_WAKE_LOW
+#endif
+
+#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_EDGE_F
+#define WAKEUP_TYPE    PM_WAKE_FALLING
+#endif
+
+#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_EDGE_R
+#define WAKEUP_TYPE    PM_WAKE_RISING
+#endif
+
+#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_EDGE_B
+#define WAKEUP_TYPE    PM_WAKE_BOTH_EDGES
+#endif
+
+void bfin_pm_suspend_standby_enter(void)
+{
+#ifdef CONFIG_PM_WAKEUP_BY_GPIO
+       gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
+#endif
+
+#if defined(CONFIG_PM_WAKEUP_BY_GPIO) || defined(CONFIG_PM_WAKEUP_GPIO_API)
+       {
+               u32 flags;
+
+               local_irq_save(flags);
+
+               sleep_deeper(gpio_pm_setup()); /*Goto Sleep*/
+
+               gpio_pm_restore();
+
+               bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+
+               local_irq_restore(flags);
+       }
+#endif
+
+#if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR)
+       sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR);
+       bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+#endif                         /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */
+}
+
+
+/*
+ *     bfin_pm_prepare - Do preliminary suspend work.
+ *     @state:         suspend state we're entering.
+ *
+ */
+static int bfin_pm_prepare(suspend_state_t state)
+{
+       int error = 0;
+
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               break;
+       case PM_SUSPEND_MEM:
+               return -ENOTSUPP;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+
+       default:
+               return -EINVAL;
+       }
+
+       return error;
+}
+
+/*
+ *     bfin_pm_enter - Actually enter a sleep state.
+ *     @state:         State we're entering.
+ *
+ */
+static int bfin_pm_enter(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               bfin_pm_suspend_standby_enter();
+               break;
+       case PM_SUSPEND_MEM:
+               return -ENOTSUPP;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ *     bfin_pm_finish - Finish up suspend sequence.
+ *     @state:         State we're coming out of.
+ *
+ *     This is called after we wake back up (or if entering the sleep state
+ *     failed).
+ */
+static int bfin_pm_finish(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               break;
+
+       case PM_SUSPEND_MEM:
+               return -ENOTSUPP;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+struct pm_ops bfin_pm_ops = {
+       .pm_disk_mode = PM_DISK_PLATFORM,
+       .prepare = bfin_pm_prepare,
+       .enter = bfin_pm_enter,
+       .finish = bfin_pm_finish,
+};
+
+static int __init bfin_pm_init(void)
+{
+       pm_set_ops(&bfin_pm_ops);
+       return 0;
+}
+
+__initcall(bfin_pm_init);
diff --git a/arch/blackfin/mm/Makefile b/arch/blackfin/mm/Makefile
new file mode 100644 (file)
index 0000000..2a7202c
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mm/Makefile
+#
+
+obj-y := blackfin_sram.o init.o
diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c
new file mode 100644 (file)
index 0000000..dd0c650
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * File:         arch/blackfin/mm/blackfin_sram.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  SRAM driver for Blackfin ADSP-BF5xx
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/rtc.h>
+#include <asm/blackfin.h>
+#include "blackfin_sram.h"
+
+spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
+
+#if CONFIG_L1_MAX_PIECE < 16
+#undef CONFIG_L1_MAX_PIECE
+#define CONFIG_L1_MAX_PIECE        16
+#endif
+
+#if CONFIG_L1_MAX_PIECE > 1024
+#undef CONFIG_L1_MAX_PIECE
+#define CONFIG_L1_MAX_PIECE        1024
+#endif
+
+#define SRAM_SLT_NULL      0
+#define SRAM_SLT_FREE      1
+#define SRAM_SLT_ALLOCATED 2
+
+/* the data structure for L1 scratchpad and DATA SRAM */
+struct l1_sram_piece {
+       void *paddr;
+       int size;
+       int flag;
+};
+
+static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];
+
+#if L1_DATA_A_LENGTH != 0
+static struct l1_sram_piece l1_data_A_sram[CONFIG_L1_MAX_PIECE];
+#endif
+
+#if L1_DATA_B_LENGTH != 0
+static struct l1_sram_piece l1_data_B_sram[CONFIG_L1_MAX_PIECE];
+#endif
+
+#if L1_CODE_LENGTH != 0
+static struct l1_sram_piece l1_inst_sram[CONFIG_L1_MAX_PIECE];
+#endif
+
+/* L1 Scratchpad SRAM initialization function */
+void l1sram_init(void)
+{
+       printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
+              L1_SCRATCH_LENGTH >> 10);
+
+       memset(&l1_ssram, 0x00, sizeof(l1_ssram));
+       l1_ssram[0].paddr = (void*)L1_SCRATCH_START;
+       l1_ssram[0].size = L1_SCRATCH_LENGTH;
+       l1_ssram[0].flag = SRAM_SLT_FREE;
+
+       /* mutex initialize */
+       spin_lock_init(&l1sram_lock);
+}
+
+void l1_data_sram_init(void)
+{
+#if L1_DATA_A_LENGTH != 0
+       printk(KERN_INFO "Blackfin DATA_A SRAM: %d KB\n",
+              L1_DATA_A_LENGTH >> 10);
+
+       memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
+       l1_data_A_sram[0].paddr = (void*)L1_DATA_A_START +
+               (_ebss_l1 - _sdata_l1);
+       l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
+       l1_data_A_sram[0].flag = SRAM_SLT_FREE;
+#endif
+#if L1_DATA_B_LENGTH != 0
+       printk(KERN_INFO "Blackfin DATA_B SRAM: %d KB\n",
+              L1_DATA_B_LENGTH >> 10);
+
+       memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
+       l1_data_B_sram[0].paddr = (void*)L1_DATA_B_START;
+       l1_data_B_sram[0].size = L1_DATA_B_LENGTH;
+       l1_data_B_sram[0].flag = SRAM_SLT_FREE;
+#endif
+
+       /* mutex initialize */
+       spin_lock_init(&l1_data_sram_lock);
+}
+
+void l1_inst_sram_init(void)
+{
+#if L1_CODE_LENGTH != 0
+       printk(KERN_INFO "Blackfin Instruction SRAM: %d KB\n",
+              L1_CODE_LENGTH >> 10);
+
+       memset(&l1_inst_sram, 0x00, sizeof(l1_inst_sram));
+       l1_inst_sram[0].paddr = (void*)L1_CODE_START + (_etext_l1 - _stext_l1);
+       l1_inst_sram[0].size = L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
+       l1_inst_sram[0].flag = SRAM_SLT_FREE;
+#endif
+
+       /* mutex initialize */
+       spin_lock_init(&l1_inst_sram_lock);
+}
+
+/* L1 memory allocate function */
+static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
+{
+       int i, index = 0;
+       void *addr = NULL;
+
+       if (size <= 0)
+               return NULL;
+
+       /* Align the size */
+       size = (size + 3) & ~3;
+
+       /* not use the good method to match the best slot !!! */
+       /* search an available memeory slot */
+       for (i = 0; i < count; i++) {
+               if ((pfree[i].flag == SRAM_SLT_FREE)
+                   && (pfree[i].size >= size)) {
+                       addr = pfree[i].paddr;
+                       pfree[i].flag = SRAM_SLT_ALLOCATED;
+                       index = i;
+                       break;
+               }
+       }
+       if (i >= count)
+               return NULL;
+
+       /* updated the NULL memeory slot !!! */
+       if (pfree[i].size > size) {
+               for (i = 0; i < count; i++) {
+                       if (pfree[i].flag == SRAM_SLT_NULL) {
+                               pfree[i].flag = SRAM_SLT_FREE;
+                               pfree[i].paddr = addr + size;
+                               pfree[i].size = pfree[index].size - size;
+                               pfree[index].size = size;
+                               break;
+                       }
+               }
+       }
+
+       return addr;
+}
+
+/* Allocate the largest available block.  */
+static void *_l1_sram_alloc_max(struct l1_sram_piece *pfree, int count,
+                               unsigned long *psize)
+{
+       unsigned long best = 0;
+       int i, index = -1;
+       void *addr = NULL;
+
+       /* search an available memeory slot */
+       for (i = 0; i < count; i++) {
+               if (pfree[i].flag == SRAM_SLT_FREE && pfree[i].size > best) {
+                       addr = pfree[i].paddr;
+                       index = i;
+                       best = pfree[i].size;
+               }
+       }
+       if (index < 0)
+               return NULL;
+       *psize = best;
+
+       pfree[index].flag = SRAM_SLT_ALLOCATED;
+       return addr;
+}
+
+/* L1 memory free function */
+static int _l1_sram_free(const void *addr,
+                        struct l1_sram_piece *pfree, int count)
+{
+       int i, index = 0;
+
+       /* search the relevant memory slot */
+       for (i = 0; i < count; i++) {
+               if (pfree[i].paddr == addr) {
+                       if (pfree[i].flag != SRAM_SLT_ALLOCATED) {
+                               /* error log */
+                               return -1;
+                       }
+                       index = i;
+                       break;
+               }
+       }
+       if (i >= count)
+               return -1;
+
+       pfree[index].flag = SRAM_SLT_FREE;
+
+       /* link the next address slot */
+       for (i = 0; i < count; i++) {
+               if (((pfree[index].paddr + pfree[index].size) == pfree[i].paddr)
+                   && (pfree[i].flag == SRAM_SLT_FREE)) {
+                       pfree[i].flag = SRAM_SLT_NULL;
+                       pfree[index].size += pfree[i].size;
+                       pfree[index].flag = SRAM_SLT_FREE;
+                       break;
+               }
+       }
+
+       /* link the last address slot */
+       for (i = 0; i < count; i++) {
+               if (((pfree[i].paddr + pfree[i].size) == pfree[index].paddr) &&
+                   (pfree[i].flag == SRAM_SLT_FREE)) {
+                       pfree[index].flag = SRAM_SLT_NULL;
+                       pfree[i].size += pfree[index].size;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+int sram_free(const void *addr)
+{
+       if (0) {}
+#if L1_CODE_LENGTH != 0
+       else if (addr >= (void *)L1_CODE_START
+                && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
+               return l1_inst_sram_free(addr);
+#endif
+#if L1_DATA_A_LENGTH != 0
+       else if (addr >= (void *)L1_DATA_A_START
+                && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH))
+               return l1_data_A_sram_free(addr);
+#endif
+#if L1_DATA_B_LENGTH != 0
+       else if (addr >= (void *)L1_DATA_B_START
+                && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
+               return l1_data_B_sram_free(addr);
+#endif
+       else
+               return -1;
+}
+EXPORT_SYMBOL(sram_free);
+
+void *l1_data_A_sram_alloc(size_t size)
+{
+       unsigned flags;
+       void *addr = NULL;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+#if L1_DATA_A_LENGTH != 0
+       addr = _l1_sram_alloc(size, l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+#endif
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l1_data_A_sram_alloc);
+
+int l1_data_A_sram_free(const void *addr)
+{
+       unsigned flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+#if L1_DATA_A_LENGTH != 0
+       ret = _l1_sram_free(addr,
+                          l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+#else
+       ret = -1;
+#endif
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(l1_data_A_sram_free);
+
+void *l1_data_B_sram_alloc(size_t size)
+{
+#if L1_DATA_B_LENGTH != 0
+       unsigned flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+       addr = _l1_sram_alloc(size, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+#else
+       return NULL;
+#endif
+}
+EXPORT_SYMBOL(l1_data_B_sram_alloc);
+
+int l1_data_B_sram_free(const void *addr)
+{
+#if L1_DATA_B_LENGTH != 0
+       unsigned flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+       ret = _l1_sram_free(addr, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       return ret;
+#else
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(l1_data_B_sram_free);
+
+void *l1_data_sram_alloc(size_t size)
+{
+       void *addr = l1_data_A_sram_alloc(size);
+
+       if (!addr)
+               addr = l1_data_B_sram_alloc(size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l1_data_sram_alloc);
+
+void *l1_data_sram_zalloc(size_t size)
+{
+       void *addr = l1_data_sram_alloc(size);
+
+       if (addr)
+               memset(addr, 0x00, size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l1_data_sram_zalloc);
+
+int l1_data_sram_free(const void *addr)
+{
+       int ret;
+       ret = l1_data_A_sram_free(addr);
+       if (ret == -1)
+               ret = l1_data_B_sram_free(addr);
+       return ret;
+}
+EXPORT_SYMBOL(l1_data_sram_free);
+
+void *l1_inst_sram_alloc(size_t size)
+{
+#if L1_DATA_A_LENGTH != 0
+       unsigned flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_inst_sram_lock, flags);
+
+       addr = _l1_sram_alloc(size, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
+
+       pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+#else
+       return NULL;
+#endif
+}
+EXPORT_SYMBOL(l1_inst_sram_alloc);
+
+int l1_inst_sram_free(const void *addr)
+{
+#if L1_CODE_LENGTH != 0
+       unsigned flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_inst_sram_lock, flags);
+
+       ret = _l1_sram_free(addr, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
+
+       return ret;
+#else
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(l1_inst_sram_free);
+
+/* L1 Scratchpad memory allocate function */
+void *l1sram_alloc(size_t size)
+{
+       unsigned flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1sram_lock, flags);
+
+       addr = _l1_sram_alloc(size, l1_ssram, ARRAY_SIZE(l1_ssram));
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1sram_lock, flags);
+
+       return addr;
+}
+
+/* L1 Scratchpad memory allocate function */
+void *l1sram_alloc_max(size_t *psize)
+{
+       unsigned flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1sram_lock, flags);
+
+       addr = _l1_sram_alloc_max(l1_ssram, ARRAY_SIZE(l1_ssram), psize);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1sram_lock, flags);
+
+       return addr;
+}
+
+/* L1 Scratchpad memory free function */
+int l1sram_free(const void *addr)
+{
+       unsigned flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1sram_lock, flags);
+
+       ret = _l1_sram_free(addr, l1_ssram, ARRAY_SIZE(l1_ssram));
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1sram_lock, flags);
+
+       return ret;
+}
+
+int sram_free_with_lsl(const void *addr)
+{
+       struct sram_list_struct *lsl, **tmp;
+       struct mm_struct *mm = current->mm;
+
+       for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next)
+               if ((*tmp)->addr == addr)
+                       goto found;
+       return -1;
+found:
+       lsl = *tmp;
+       sram_free(addr);
+       *tmp = lsl->next;
+       kfree(lsl);
+
+       return 0;
+}
+EXPORT_SYMBOL(sram_free_with_lsl);
+
+void *sram_alloc_with_lsl(size_t size, unsigned long flags)
+{
+       void *addr = NULL;
+       struct sram_list_struct *lsl = NULL;
+       struct mm_struct *mm = current->mm;
+
+       lsl = kmalloc(sizeof(struct sram_list_struct), GFP_KERNEL);
+       if (!lsl)
+               return NULL;
+       memset(lsl, 0, sizeof(*lsl));
+
+       if (flags & L1_INST_SRAM)
+               addr = l1_inst_sram_alloc(size);
+
+       if (addr == NULL && (flags & L1_DATA_A_SRAM))
+               addr = l1_data_A_sram_alloc(size);
+
+       if (addr == NULL && (flags & L1_DATA_B_SRAM))
+               addr = l1_data_B_sram_alloc(size);
+
+       if (addr == NULL) {
+               kfree(lsl);
+               return NULL;
+       }
+       lsl->addr = addr;
+       lsl->length = size;
+       lsl->next = mm->context.sram_list;
+       mm->context.sram_list = lsl;
+       return addr;
+}
+EXPORT_SYMBOL(sram_alloc_with_lsl);
diff --git a/arch/blackfin/mm/blackfin_sram.h b/arch/blackfin/mm/blackfin_sram.h
new file mode 100644 (file)
index 0000000..0fb73b7
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * File:         arch/blackfin/mm/blackfin_sram.h
+ * Based on:     arch/blackfin/mm/blackfin_sram.c
+ * Author:       Mike Frysinger
+ *
+ * Created:      Aug 2006
+ * Description:  Local prototypes meant for internal use only
+ *
+ * Modified:
+ *               Copyright 2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __BLACKFIN_SRAM_H__
+#define __BLACKFIN_SRAM_H__
+
+extern void l1sram_init(void);
+extern void l1_inst_sram_init(void);
+extern void l1_data_sram_init(void);
+extern void *l1sram_alloc(size_t);
+
+#endif
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
new file mode 100644 (file)
index 0000000..73f72ab
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * File:         arch/blackfin/mm/init.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/swap.h>
+#include <linux/bootmem.h>
+#include <asm/bfin-global.h>
+#include <asm/uaccess.h>
+#include <asm/l1layout.h>
+#include "blackfin_sram.h"
+
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving a inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+static unsigned long empty_bad_page_table;
+
+static unsigned long empty_bad_page;
+
+unsigned long empty_zero_page;
+
+void show_mem(void)
+{
+       unsigned long i;
+       int free = 0, total = 0, reserved = 0, shared = 0;
+
+       int cached = 0;
+       printk(KERN_INFO "Mem-info:\n");
+       show_free_areas();
+       i = max_mapnr;
+       while (i-- > 0) {
+               total++;
+               if (PageReserved(mem_map + i))
+                       reserved++;
+               else if (PageSwapCache(mem_map + i))
+                       cached++;
+               else if (!page_count(mem_map + i))
+                       free++;
+               else
+                       shared += page_count(mem_map + i) - 1;
+       }
+       printk(KERN_INFO "%d pages of RAM\n", total);
+       printk(KERN_INFO "%d free pages\n", free);
+       printk(KERN_INFO "%d reserved pages\n", reserved);
+       printk(KERN_INFO "%d pages shared\n", shared);
+       printk(KERN_INFO "%d pages swap cached\n", cached);
+}
+
+/*
+ * paging_init() continues the virtual memory environment setup which
+ * was begun by the code in arch/head.S.
+ * The parameters are pointers to where to stick the starting and ending
+ * addresses  of available kernel virtual memory.
+ */
+void paging_init(void)
+{
+       /*
+        * make sure start_mem is page aligned,  otherwise bootmem and
+        * page_alloc get different views og the world
+        */
+       unsigned long end_mem = memory_end & PAGE_MASK;
+
+       pr_debug("start_mem is %#lx   virtual_end is %#lx\n", PAGE_ALIGN(memory_start), end_mem);
+
+       /*
+        * initialize the bad page table and bad page to point
+        * to a couple of allocated pages
+        */
+       empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+       empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+       empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+       memset((void *)empty_zero_page, 0, PAGE_SIZE);
+
+       /*
+        * Set up SFC/DFC registers (user data space)
+        */
+       set_fs(KERNEL_DS);
+
+       pr_debug("free_area_init -> start_mem is %#lx   virtual_end is %#lx\n",
+               PAGE_ALIGN(memory_start), end_mem);
+
+       {
+               unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+
+               zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
+#ifdef CONFIG_HIGHMEM
+               zones_size[ZONE_HIGHMEM] = 0;
+#endif
+               free_area_init(zones_size);
+       }
+}
+
+void mem_init(void)
+{
+       unsigned int codek = 0, datak = 0, initk = 0;
+       unsigned long tmp;
+       unsigned int len = _ramend - _rambase;
+       unsigned long start_mem = memory_start;
+       unsigned long end_mem = memory_end;
+
+       end_mem &= PAGE_MASK;
+       high_memory = (void *)end_mem;
+
+       start_mem = PAGE_ALIGN(start_mem);
+       max_mapnr = num_physpages = MAP_NR(high_memory);
+       printk(KERN_INFO "Physical pages: %lx\n", num_physpages);
+
+       /* This will put all memory onto the freelists. */
+       totalram_pages = free_all_bootmem();
+
+       codek = (_etext - _stext) >> 10;
+       datak = (__bss_stop - __bss_start) >> 10;
+       initk = (__init_end - __init_begin) >> 10;
+
+       tmp = nr_free_pages() << PAGE_SHIFT;
+       printk(KERN_INFO
+            "Memory available: %luk/%uk RAM, (%uk init code, %uk kernel code, %uk data, %uk dma)\n",
+            tmp >> 10, len >> 10, initk, codek, datak, DMA_UNCACHED_REGION >> 10);
+
+       /* Initialize the blackfin L1 Memory. */
+       l1sram_init();
+       l1_data_sram_init();
+       l1_inst_sram_init();
+
+       /* Allocate this once; never free it.  We assume this gives us a
+          pointer to the start of L1 scratchpad memory; panic if it
+          doesn't.  */
+       tmp = (unsigned long)l1sram_alloc(sizeof(struct l1_scratch_task_info));
+       if (tmp != (unsigned long)L1_SCRATCH_TASK_INFO) {
+               printk(KERN_EMERG "mem_init(): Did not get the right address from l1sram_alloc: %08lx != %08lx\n",
+                       tmp, (unsigned long)L1_SCRATCH_TASK_INFO);
+               panic("No L1, time to give up\n");
+       }
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+       int pages = 0;
+       for (; start < end; start += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(start));
+               init_page_count(virt_to_page(start));
+               free_page(start);
+               totalram_pages++;
+               pages++;
+       }
+       printk(KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
+}
+#endif
+
+void free_initmem(void)
+{
+#ifdef CONFIG_RAMKERNEL
+       unsigned long addr;
+/*
+ *     the following code should be cool even if these sections
+ *     are not page aligned.
+ */
+       addr = PAGE_ALIGN((unsigned long)(__init_begin));
+       /* next to check that the page we free is not a partial page */
+       for (; addr + PAGE_SIZE < (unsigned long)(__init_end);
+            addr += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(addr));
+               init_page_count(virt_to_page(addr));
+               free_page(addr);
+               totalram_pages++;
+       }
+       printk(KERN_NOTICE
+              "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
+              (addr - PAGE_ALIGN((long)__init_begin)) >> 10,
+              (int)(PAGE_ALIGN((unsigned long)(__init_begin))),
+              (int)(addr - PAGE_SIZE));
+#endif
+}
diff --git a/arch/blackfin/oprofile/Kconfig b/arch/blackfin/oprofile/Kconfig
new file mode 100644 (file)
index 0000000..0a2fd99
--- /dev/null
@@ -0,0 +1,29 @@
+menu "Profiling support"
+depends on EXPERIMENTAL
+
+config PROFILING
+       bool "Profiling support (EXPERIMENTAL)"
+       help
+         Say Y here to enable the extended profiling support mechanisms used
+         by profilers such as OProfile.
+
+config OPROFILE
+       tristate "OProfile system profiling (EXPERIMENTAL)"
+       depends on PROFILING
+       help
+         OProfile is a profiling system capable of profiling the
+         whole system, include the kernel, kernel modules, libraries,
+         and applications.
+
+         If unsure, say N.
+
+config HARDWARE_PM
+       tristate "Hardware Performance Monitor Profiling"
+       depends on PROFILING
+       help
+         take use of hardware performance monitor to profiling the kernel
+         and application.
+
+         If unsure, say N.
+
+endmenu
diff --git a/arch/blackfin/oprofile/Makefile b/arch/blackfin/oprofile/Makefile
new file mode 100644 (file)
index 0000000..634e300
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# arch/blackfin/oprofile/Makefile
+#
+
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+               oprof.o cpu_buffer.o buffer_sync.o \
+               event_buffer.o oprofile_files.o \
+               oprofilefs.o oprofile_stats.o \
+               timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-$(CONFIG_HARDWARE_PM) += op_model_bf533.o
diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
new file mode 100644 (file)
index 0000000..009a170
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * File:         arch/blackfin/oprofile/common.c
+ * Based on:     arch/alpha/oprofile/common.c
+ * Author:       Anton Blanchard <anton@au.ibm.com>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "op_blackfin.h"
+
+#define BFIN_533_ID  0xE5040003
+#define BFIN_537_ID  0xE5040002
+
+static int pfmon_enabled;
+static struct mutex pfmon_lock;
+
+struct op_bfin533_model *model;
+
+struct op_counter_config ctr[OP_MAX_COUNTER];
+
+static int op_bfin_setup(void)
+{
+       int ret;
+
+       /* Pre-compute the values to stuff in the hardware registers.  */
+       spin_lock(&oprofilefs_lock);
+       ret = model->reg_setup(ctr);
+       spin_unlock(&oprofilefs_lock);
+
+       return ret;
+}
+
+static void op_bfin_shutdown(void)
+{
+#if 0
+       /* what is the difference between shutdown and stop? */
+#endif
+}
+
+static int op_bfin_start(void)
+{
+       int ret = -EBUSY;
+
+       printk(KERN_INFO "KSDBG:in %s\n", __FUNCTION__);
+       mutex_lock(&pfmon_lock);
+       if (!pfmon_enabled) {
+               ret = model->start(ctr);
+               pfmon_enabled = !ret;
+       }
+       mutex_unlock(&pfmon_lock);
+
+       return ret;
+}
+
+static void op_bfin_stop(void)
+{
+       mutex_lock(&pfmon_lock);
+       if (pfmon_enabled) {
+               model->stop();
+               pfmon_enabled = 0;
+       }
+       mutex_unlock(&pfmon_lock);
+}
+
+static int op_bfin_create_files(struct super_block *sb, struct dentry *root)
+{
+       int i;
+
+       for (i = 0; i < model->num_counters; ++i) {
+               struct dentry *dir;
+               char buf[3];
+               printk(KERN_INFO "Oprofile: creating files... \n");
+
+               snprintf(buf, sizeof buf, "%d", i);
+               dir = oprofilefs_mkdir(sb, root, buf);
+
+               oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
+               oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
+               oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
+               /*
+                * We dont support per counter user/kernel selection, but
+                * we leave the entries because userspace expects them
+                */
+               oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
+               oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
+               oprofilefs_create_ulong(sb, dir, "unit_mask",
+                                       &ctr[i].unit_mask);
+       }
+
+       return 0;
+}
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+#ifdef CONFIG_HARDWARE_PM
+       unsigned int dspid;
+
+       mutex_init(&pfmon_lock);
+
+       dspid = bfin_read_DSPID();
+
+       printk(KERN_INFO "Oprofile got the cpu id is 0x%x. \n", dspid);
+
+       switch (dspid) {
+       case BFIN_533_ID:
+               model = &op_model_bfin533;
+               model->num_counters = 2;
+               break;
+       case BFIN_537_ID:
+               model = &op_model_bfin533;
+               model->num_counters = 2;
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       ops->cpu_type = model->name;
+       ops->create_files = op_bfin_create_files;
+       ops->setup = op_bfin_setup;
+       ops->shutdown = op_bfin_shutdown;
+       ops->start = op_bfin_start;
+       ops->stop = op_bfin_stop;
+
+       printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+              ops->cpu_type);
+
+       return 0;
+#else
+       return -1;
+#endif
+}
+
+void oprofile_arch_exit(void)
+{
+}
diff --git a/arch/blackfin/oprofile/op_blackfin.h b/arch/blackfin/oprofile/op_blackfin.h
new file mode 100644 (file)
index 0000000..f88f446
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * File:         arch/blackfin/oprofile/op_blackfin.h
+ * Based on:
+ * Author:       Anton Blanchard <anton@au.ibm.com>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef OP_BLACKFIN_H
+#define OP_BLACKFIN_H 1
+
+#define OP_MAX_COUNTER 2
+
+#include <asm/blackfin.h>
+
+/* Per-counter configuration as set via oprofilefs.  */
+struct op_counter_config {
+       unsigned long valid;
+       unsigned long enabled;
+       unsigned long event;
+       unsigned long count;
+       unsigned long kernel;
+       unsigned long user;
+       unsigned long unit_mask;
+};
+
+/* System-wide configuration as set via oprofilefs.  */
+struct op_system_config {
+       unsigned long enable_kernel;
+       unsigned long enable_user;
+};
+
+/* Per-arch configuration */
+struct op_bfin533_model {
+       int (*reg_setup) (struct op_counter_config *);
+       int (*start) (struct op_counter_config *);
+       void (*stop) (void);
+       int num_counters;
+       char *name;
+};
+
+extern struct op_bfin533_model op_model_bfin533;
+
+static inline unsigned int ctr_read(void)
+{
+       unsigned int tmp;
+
+       tmp = bfin_read_PFCTL();
+       __builtin_bfin_csync();
+
+       return tmp;
+}
+
+static inline void ctr_write(unsigned int val)
+{
+       bfin_write_PFCTL(val);
+       __builtin_bfin_csync();
+}
+
+static inline void count_read(unsigned int *count)
+{
+       count[0] = bfin_read_PFCNTR0();
+       count[1] = bfin_read_PFCNTR1();
+       __builtin_bfin_csync();
+}
+
+static inline void count_write(unsigned int *count)
+{
+       bfin_write_PFCNTR0(count[0]);
+       bfin_write_PFCNTR1(count[1]);
+       __builtin_bfin_csync();
+}
+
+extern int pm_overflow_handler(int irq, struct pt_regs *regs);
+
+#endif
diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
new file mode 100644 (file)
index 0000000..b7a20a0
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * File:         arch/blackfin/oprofile/op_model_bf533.c
+ * Based on:
+ * Author:       Anton Blanchard <anton@au.ibm.com>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "op_blackfin.h"
+
+#define PM_ENABLE 0x01;
+#define PM_CTL1_ENABLE  0x18
+#define PM_CTL0_ENABLE  0xC000
+#define COUNT_EDGE_ONLY 0x3000000
+
+static int oprofile_running;
+
+static unsigned curr_pfctl, curr_count[2];
+
+static int bfin533_reg_setup(struct op_counter_config *ctr)
+{
+       unsigned int pfctl = ctr_read();
+       unsigned int count[2];
+
+       /* set Blackfin perf monitor regs with ctr */
+       if (ctr[0].enabled) {
+               pfctl |= (PM_CTL0_ENABLE | ((char)ctr[0].event << 5));
+               count[0] = 0xFFFFFFFF - ctr[0].count;
+               curr_count[0] = count[0];
+       }
+       if (ctr[1].enabled) {
+               pfctl |= (PM_CTL1_ENABLE | ((char)ctr[1].event << 16));
+               count[1] = 0xFFFFFFFF - ctr[1].count;
+               curr_count[1] = count[1];
+       }
+
+       pr_debug("ctr[0].enabled=%d,ctr[1].enabled=%d,ctr[0].event<<5=0x%x,ctr[1].event<<16=0x%x\n", ctr[0].enabled, ctr[1].enabled, ctr[0].event << 5, ctr[1].event << 16);
+       pfctl |= COUNT_EDGE_ONLY;
+       curr_pfctl = pfctl;
+
+       pr_debug("write 0x%x to pfctl\n", pfctl);
+       ctr_write(pfctl);
+       count_write(count);
+
+       return 0;
+}
+
+static int bfin533_start(struct op_counter_config *ctr)
+{
+       unsigned int pfctl = ctr_read();
+
+       pfctl |= PM_ENABLE;
+       curr_pfctl = pfctl;
+
+       ctr_write(pfctl);
+
+       oprofile_running = 1;
+       pr_debug("start oprofile counter \n");
+
+       return 0;
+}
+
+static void bfin533_stop(void)
+{
+       int pfctl;
+
+       pfctl = ctr_read();
+       pfctl &= ~PM_ENABLE;
+       /* freeze counters */
+       ctr_write(pfctl);
+
+       oprofile_running = 0;
+       pr_debug("stop oprofile counter \n");
+}
+
+static int get_kernel(void)
+{
+       int ipend, is_kernel;
+
+       ipend = bfin_read_IPEND();
+
+       /* test bit 15 */
+       is_kernel = ((ipend & 0x8000) != 0);
+
+       return is_kernel;
+}
+
+int pm_overflow_handler(int irq, struct pt_regs *regs)
+{
+       int is_kernel;
+       int i, cpu;
+       unsigned int pc, pfctl;
+       unsigned int count[2];
+
+       pr_debug("get interrupt in %s\n", __FUNCTION__);
+       if (oprofile_running == 0) {
+               pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
+               return -1;
+       }
+
+       is_kernel = get_kernel();
+       cpu = smp_processor_id();
+       pc = regs->pc;
+       pfctl = ctr_read();
+
+       /* read the two event counter regs */
+       count_read(count);
+
+       /* if the counter overflows, add sample to oprofile buffer */
+       for (i = 0; i < 2; ++i) {
+               if (oprofile_running) {
+                       oprofile_add_sample(regs, i);
+               }
+       }
+
+       /* reset the perfmon counter */
+       ctr_write(curr_pfctl);
+       count_write(curr_count);
+       return 0;
+}
+
+struct op_bfin533_model op_model_bfin533 = {
+       .reg_setup = bfin533_reg_setup,
+       .start = bfin533_start,
+       .stop = bfin533_stop,
+       .num_counters = 2,
+       .name = "blackfin/bf533"
+};
diff --git a/arch/blackfin/oprofile/timer_int.c b/arch/blackfin/oprofile/timer_int.c
new file mode 100644 (file)
index 0000000..8fba16c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * File:         arch/blackfin/oprofile/timer_int.c
+ * Based on:
+ * Author:       Michael Kang
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/oprofile.h>
+
+#include <asm/ptrace.h>
+
+static void enable_sys_timer0()
+{
+}
+static void disable_sys_timer0()
+{
+}
+
+static irqreturn_t sys_timer0_int_handler(int irq, void *dev_id,
+                                         struct pt_regs *regs)
+{
+       oprofile_add_sample(regs, 0);
+       return IRQ_HANDLED;
+}
+
+static int sys_timer0_start(void)
+{
+       enable_sys_timer0();
+       return request_irq(IVG11, sys_timer0_int_handler, 0, "sys_timer0", NULL);
+}
+
+static void sys_timer0_stop(void)
+{
+       disable_sys_timer();
+}
+
+int __init sys_timer0_init(struct oprofile_operations *ops)
+{
+       extern int nmi_active;
+
+       if (nmi_active <= 0)
+               return -ENODEV;
+
+       ops->start = timer_start;
+       ops->stop = timer_stop;
+       ops->cpu_type = "timer";
+       printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
+       return 0;
+}
index 5daeb6f..79e1e4c 100644 (file)
@@ -603,23 +603,8 @@ void schedule_usleep(unsigned long us)
 
 #ifdef CONFIG_PROC_FS
 static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-                       ,int *eof, void *data_unused
-#else
-                        ,int unused
-#endif
-                               );
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+                       ,int *eof, void *data_unused);
 static struct proc_dir_entry *fasttimer_proc_entry;
-#else
-static struct proc_dir_entry fasttimer_proc_entry =
-{
-  0, 9, "fasttimer",
-  S_IFREG | S_IRUGO, 1, 0, 0,
-  0, NULL /* ops -- default to array */,
-  &proc_fasttimer_read /* get_info */,
-};
-#endif
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_PROC_FS
@@ -628,12 +613,7 @@ static struct proc_dir_entry fasttimer_proc_entry =
 #define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300)
 
 static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-                       ,int *eof, void *data_unused
-#else
-                        ,int unused
-#endif
-                               )
+                       ,int *eof, void *data_unused)
 {
   unsigned long flags;
   int i = 0;
@@ -808,9 +788,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
 
   memcpy(buf, bigbuf + offset, len);
   *start = buf;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
   *eof = 1;
-#endif
 
   return len;
 }
@@ -974,12 +952,8 @@ void fast_timer_init(void)
     printk("fast_timer_init()\n");
 
 #ifdef CONFIG_PROC_FS
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
    if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
      fasttimer_proc_entry->read_proc = proc_fasttimer_read;
-#else
-    proc_register_dynamic(&proc_root, &fasttimer_proc_entry);
-#endif
 #endif /* PROC_FS */
     if(request_irq(TIMER_INTR_VECT, timer_trig_interrupt, IRQF_DISABLED,
                    "fast timer int", NULL))
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 4cfcae6..aad0a9e 100644 (file)
@@ -15,39 +15,47 @@ static int prof_running = 0;
 void
 cris_profile_sample(struct pt_regs* regs)
 {
-  if (!prof_running)
-    return;
-  if (user_mode(regs))
-    *(unsigned int*)sample_buffer_pos = current->pid;
-  else
-    *(unsigned int*)sample_buffer_pos = 0;
-  *(unsigned int*)(sample_buffer_pos + 4) = instruction_pointer(regs);
-  sample_buffer_pos += 8;
-  if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE)
-    sample_buffer_pos = sample_buffer;
+       if (!prof_running)
+               return;
+
+       if (user_mode(regs))
+               *(unsigned int*)sample_buffer_pos = current->pid;
+       else
+               *(unsigned int*)sample_buffer_pos = 0;
+
+       *(unsigned int*)(sample_buffer_pos + 4) = instruction_pointer(regs);
+       sample_buffer_pos += 8;
+
+       if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE)
+               sample_buffer_pos = sample_buffer;
 }
 
 static ssize_t
-read_cris_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+read_cris_profile(struct file *file, char __user *buf,
+                 size_t count, loff_t *ppos)
 {
-  unsigned long p = *ppos;
-  if (p > SAMPLE_BUFFER_SIZE)
-    return 0;
-  if (p + count > SAMPLE_BUFFER_SIZE)
-    count = SAMPLE_BUFFER_SIZE - p;
-  if (copy_to_user(buf, sample_buffer + p,count))
+       unsigned long p = *ppos;
+
+       if (p > SAMPLE_BUFFER_SIZE)
+               return 0;
+
+       if (p + count > SAMPLE_BUFFER_SIZE)
+               count = SAMPLE_BUFFER_SIZE - p;
+       if (copy_to_user(buf, sample_buffer + p,count))
                return -EFAULT;
-  memset(sample_buffer + p, 0, count);
-  *ppos += count;
-  return count;
+
+       memset(sample_buffer + p, 0, count);
+       *ppos += count;
+
+       return count;
 }
 
 static ssize_t
 write_cris_profile(struct file *file, const char __user *buf,
-              size_t count, loff_t *ppos)
+                  size_t count, loff_t *ppos)
 {
-  sample_buffer_pos = sample_buffer;
-  memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
+       sample_buffer_pos = sample_buffer;
+       memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
 }
 
 static const struct file_operations cris_proc_profile_operations = {
@@ -58,16 +66,23 @@ static const struct file_operations cris_proc_profile_operations = {
 static int
 __init init_cris_profile(void)
 {
-  struct proc_dir_entry *entry;
-  sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
-  sample_buffer_pos = sample_buffer;
-  entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
-  if (entry) {
-    entry->proc_fops = &cris_proc_profile_operations;
-    entry->size = SAMPLE_BUFFER_SIZE;
-  }
-  prof_running = 1;
-  return 0;
+       struct proc_dir_entry *entry;
+
+       sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
+       if (!sample_buffer) {
+               return -ENOMEM;
+       }
+
+       sample_buffer_pos = sample_buffer;
+
+       entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
+       if (entry) {
+               entry->proc_fops = &cris_proc_profile_operations;
+               entry->size = SAMPLE_BUFFER_SIZE;
+       }
+       prof_running = 1;
+
+       return 0;
 }
 
 __initcall(init_cris_profile);
index cea2374..eed6943 100644 (file)
@@ -53,6 +53,10 @@ config ARCH_HAS_ILOG2_U64
        bool
        default y
 
+config ARCH_USES_SLAB_PAGE_STRUCT
+       bool
+       default y
+
 mainmenu "Fujitsu FR-V Kernel Configuration"
 
 source "init/Kconfig"
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 9477ccc..cac2c01 100644 (file)
@@ -64,6 +64,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       /* handle MAP_FIXED */
+       if (flags & MAP_FIXED)
+               return addr;
+
        /* only honour a hint if we're not going to clobber something doing so */
        if (addr) {
                addr = PAGE_ALIGN(addr);
index 1734d96..618dbad 100644 (file)
@@ -49,10 +49,18 @@ config GENERIC_HWEIGHT
        bool
        default y
 
+config GENERIC_HARDIRQS
+       bool
+       default y
+
 config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config GENERIC_TIME
+       bool
+       default y
+
 config TIME_LOW_RES
        bool
        default y
index 40b3f56..b2d896a 100644 (file)
@@ -41,7 +41,7 @@ LDFLAGS += $(ldflags-y)
 CROSS_COMPILE = h8300-elf-
 LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(CFLAGS) -print-libgcc-file-name)
 
-head-y := arch/$(ARCH)/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o
+head-y := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o
 
 core-y += arch/$(ARCH)/kernel/ \
           arch/$(ARCH)/mm/
index 65086d9..0bb62e0 100644 (file)
@@ -1,12 +1,22 @@
 # arch/h8300/boot/Makefile
 
-targets := vmlinux.srec vmlinux.bin
+targets := vmlinux.srec vmlinux.bin zImage
+subdir- := compressed
 
 OBJCOPYFLAGS_vmlinux.srec := -Osrec
 OBJCOPYFLAGS_vmlinux.bin  := -Obinary
+OBJCOPYFLAGS_zImage := -O binary -R .note -R .comment -R .stab -R .stabstr -S
 
 $(obj)/vmlinux.srec $(obj)/vmlinux.bin:  vmlinux FORCE
        $(call if_changed,objcopy)
        @echo '  Kernel: $@ is ready'
 
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+       $(call if_changed,objcopy)
+       @echo 'Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: FORCE
+       $(Q)$(MAKE) $(build)=$(obj)/compressed $@
+
 CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec
+
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
new file mode 100644 (file)
index 0000000..71aac82
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# linux/arch/sh/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+EXTRA_AFLAGS   := -traditional
+
+OBJECTS = $(obj)/head.o $(obj)/misc.o
+
+#
+# IMAGE_OFFSET is the load offset of the compression loader
+# Assign dummy values if these 2 variables are not defined,
+# in order to suppress error message.
+#
+CONFIG_MEMORY_START     ?= 0x00400000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00400000
+IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
+
+LDFLAGS_vmlinux := -T $(obj)/vmlinux.lds
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+       $(call if_changed,ld)
+       @:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+       $(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,gzip)
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-h8300 -T
+OBJCOPYFLAGS := -O binary
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+       $(call if_changed,ld)
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
new file mode 100644 (file)
index 0000000..b8e90d1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  linux/arch/h8300/boot/compressed/head.S
+ *
+ *  Copyright (C) 2006 Yoshinori Sato
+ */
+
+.h8300h
+#include <linux/linkage.h>
+
+#define SRAM_START 0xff4000
+
+       .section        .text.startup
+       .global startup
+startup:
+       mov.l   #SRAM_START+0x8000, sp
+       mov.l   #__sbss, er0
+       mov.l   #__ebss, er1
+       sub.l   er0, er1
+       shlr    er1
+       shlr    er1
+       sub.l   er2, er2
+1:
+       mov.l   er2, @er0
+       adds    #4, er0
+       dec.l   #1, er1
+       bne     1b
+       jsr     @_decompress_kernel
+       jmp     @0x400000
+
+       .align  9
+fake_headers_as_bzImage:
+       .word   0
+       .ascii  "HdrS"          ; header signature
+       .word   0x0202          ; header version number (>= 0x0105)
+                               ; or else old loadlin-1.5 will fail)
+       .word   0               ; default_switch
+       .word   0               ; SETUPSEG
+       .word   0x1000
+       .word   0               ; pointing to kernel version string
+       .byte   0               ; = 0, old one (LILO, Loadlin,
+                               ; 0xTV: T=0 for LILO
+                               ;       V = version
+       .byte   1               ; Load flags bzImage=1
+       .word   0x8000          ; size to move, when setup is not
+       .long   0x100000        ; 0x100000 = default for big kernel
+       .long   0               ; address of loaded ramdisk image
+       .long   0               ; its size in bytes
diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c
new file mode 100644 (file)
index 0000000..8450745
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * arch/h8300/boot/compressed/misc.c
+ *
+ * This is a collection of several routines from gzip-1.0.3
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ *
+ * Adapted for h8300 by Yoshinori Sato 2006
+ */
+
+#include <asm/uaccess.h>
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#undef memset
+#undef memcpy
+#define memzero(s, n)     memset ((s), 0, (n))
+
+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 */
+
+static uch *inbuf;          /* input buffer */
+static uch window[WSIZE];    /* Sliding window 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 */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+extern 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);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+int puts(const char *);
+
+extern int _text;              /* Defined in vmlinux.lds.S */
+extern int _end;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
+
+#define HEAP_SIZE             0x10000
+
+#include "../../../../lib/inflate.c"
+
+#define SCR *((volatile unsigned char *)0xffff8a)
+#define TDR *((volatile unsigned char *)0xffff8b)
+#define SSR *((volatile unsigned char *)0xffff8c)
+
+static void *malloc(int size)
+{
+       void *p;
+
+       if (size <0) error("Malloc error");
+       if (free_mem_ptr == 0) error("Memory error");
+
+       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
+
+       p = (void *)free_mem_ptr;
+       free_mem_ptr += size;
+
+       if (free_mem_ptr >= free_mem_end_ptr)
+               error("Out of memory");
+
+       return p;
+}
+
+static void free(void *where)
+{      /* Don't care */
+}
+
+static void gzip_mark(void **ptr)
+{
+       *ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+       free_mem_ptr = (long) *ptr;
+}
+
+int puts(const char *s)
+{
+       return 0;
+}
+
+void* memset(void* s, int c, size_t n)
+{
+       int i;
+       char *ss = (char*)s;
+
+       for (i=0;i<n;i++) ss[i] = c;
+       return s;
+}
+
+void* memcpy(void* __dest, __const void* __src,
+                           size_t __n)
+{
+       int i;
+       char *d = (char *)__dest, *s = (char *)__src;
+
+       for (i=0;i<__n;i++) d[i] = s[i];
+       return __dest;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+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];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window(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 error(char *x)
+{
+       puts("\n\n");
+       puts(x);
+       puts("\n\n -- System halted");
+
+       while(1);       /* Halt */
+}
+
+#define STACK_SIZE (4096)
+long user_stack [STACK_SIZE];
+long* stack_start = &user_stack[STACK_SIZE];
+
+void decompress_kernel(void)
+{
+       output_data = 0;
+       output_ptr = (unsigned long)0x400000;
+       free_mem_ptr = (unsigned long)&_end;
+       free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+       makecrc();
+       puts("Uncompressing Linux... ");
+       gunzip();
+       puts("Ok, booting the kernel.\n");
+}
index 4edbc2e..ccc1a7f 100644 (file)
@@ -4,10 +4,8 @@
 
 extra-y := vmlinux.lds
 
-obj-y := process.o traps.o ptrace.o ints.o \
+obj-y := process.o traps.o ptrace.o irq.o \
         sys_h8300.o time.o semaphore.o signal.o \
-         setup.o gpio.o init_task.o syscalls.o devres.o
-
-devres-y = ../../../kernel/irq/devres.o
+         setup.o gpio.o init_task.o syscalls.o
 
 obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
new file mode 100644 (file)
index 0000000..43d21e9
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * linux/arch/h8300/kernel/irq.c
+ *
+ * Copyright 2007 Yoshinori Sato <ysato@users.sourceforge.jp>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/errno.h>
+
+/*#define DEBUG*/
+
+extern unsigned long *interrupt_redirect_table;
+extern const int h8300_saved_vectors[];
+extern const unsigned long h8300_trap_table[];
+int h8300_enable_irq_pin(unsigned int irq);
+void h8300_disable_irq_pin(unsigned int irq);
+
+#define CPU_VECTOR ((unsigned long *)0x000000)
+#define ADDR_MASK (0xffffff)
+
+static inline int is_ext_irq(unsigned int irq)
+{
+       return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
+}
+
+static void h8300_enable_irq(unsigned int irq)
+{
+       if (is_ext_irq(irq))
+               IER_REGS |= 1 << (irq - EXT_IRQ0);
+}
+
+static void h8300_disable_irq(unsigned int irq)
+{
+       if (is_ext_irq(irq))
+               IER_REGS &= ~(1 << (irq - EXT_IRQ0));
+}
+
+static void h8300_end_irq(unsigned int irq)
+{
+}
+
+static unsigned int h8300_startup_irq(unsigned int irq)
+{
+       if (is_ext_irq(irq))
+               return h8300_enable_irq_pin(irq);
+       else
+               return 0;
+}
+
+static void h8300_shutdown_irq(unsigned int irq)
+{
+       if (is_ext_irq(irq))
+               h8300_disable_irq_pin(irq);
+}
+
+/*
+ * h8300 interrupt controler implementation
+ */
+struct irq_chip h8300irq_chip = {
+       .name           = "H8300-INTC",
+       .startup        = h8300_startup_irq,
+       .shutdown       = h8300_shutdown_irq,
+       .enable         = h8300_enable_irq,
+       .disable        = h8300_disable_irq,
+       .ack            = NULL,
+       .end            = h8300_end_irq,
+};
+
+void ack_bad_irq(unsigned int irq)
+{
+       printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+
+#if defined(CONFIG_RAMKERNEL)
+static unsigned long __init *get_vector_address(void)
+{
+       unsigned long *rom_vector = CPU_VECTOR;
+       unsigned long base,tmp;
+       int vec_no;
+
+       base = rom_vector[EXT_IRQ0] & ADDR_MASK;
+
+       /* check romvector format */
+       for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
+               if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
+                       return NULL;
+       }
+
+       /* ramvector base address */
+       base -= EXT_IRQ0*4;
+
+       /* writerble check */
+       tmp = ~(*(volatile unsigned long *)base);
+       (*(volatile unsigned long *)base) = tmp;
+       if ((*(volatile unsigned long *)base) != tmp)
+               return NULL;
+       return (unsigned long *)base;
+}
+
+static void __init setup_vector(void)
+{
+       int i;
+       unsigned long *ramvec,*ramvec_p;
+       const unsigned long *trap_entry;
+       const int *saved_vector;
+
+       ramvec = get_vector_address();
+       if (ramvec == NULL)
+               panic("interrupt vector serup failed.");
+       else
+               printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
+
+       /* create redirect table */
+       ramvec_p = ramvec;
+       trap_entry = h8300_trap_table;
+       saved_vector = h8300_saved_vectors;
+       for ( i = 0; i < NR_IRQS; i++) {
+               if (i == *saved_vector) {
+                       ramvec_p++;
+                       saved_vector++;
+               } else {
+                       if ( i < NR_TRAPS ) {
+                               if (*trap_entry)
+                                       *ramvec_p = VECTOR(*trap_entry);
+                               ramvec_p++;
+                               trap_entry++;
+                       } else
+                               *ramvec_p++ = REDIRECT(interrupt_entry);
+               }
+       }
+       interrupt_redirect_table = ramvec;
+#ifdef DEBUG
+       ramvec_p = ramvec;
+       for (i = 0; i < NR_IRQS; i++) {
+               if ((i % 8) == 0)
+                       printk(KERN_DEBUG "\n%p: ",ramvec_p);
+               printk(KERN_DEBUG "%p ",*ramvec_p);
+               ramvec_p++;
+       }
+       printk(KERN_DEBUG "\n");
+#endif
+}
+#else
+#define setup_vector() do { } while(0)
+#endif
+
+void __init init_IRQ(void)
+{
+       int c;
+
+       setup_vector();
+
+       for (c = 0; c < NR_IRQS; c++) {
+               irq_desc[c].status = IRQ_DISABLED;
+               irq_desc[c].action = NULL;
+               irq_desc[c].depth = 1;
+               irq_desc[c].chip = &h8300irq_chip;
+       }
+}
+
+asmlinkage void do_IRQ(int irq)
+{
+       irq_enter();
+       __do_IRQ(irq);
+       irq_exit();
+}
+
+#if defined(CONFIG_PROC_FS)
+int show_interrupts(struct seq_file *p, void *v)
+{
+       int i = *(loff_t *) v, j;
+       struct irqaction * action;
+       unsigned long flags;
+
+       if (i == 0)
+               seq_puts(p, "           CPU0");
+
+       if (i < NR_IRQS) {
+               spin_lock_irqsave(&irq_desc[i].lock, flags);
+               action = irq_desc[i].action;
+               if (!action)
+                       goto unlock;
+               seq_printf(p, "%3d: ",i);
+               seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+               seq_printf(p, " %14s", irq_desc[i].chip->name);
+               seq_printf(p, "-%-8s", irq_desc[i].name);
+               seq_printf(p, "  %s", action->name);
+
+               for (action=action->next; action; action = action->next)
+                       seq_printf(p, ", %s", action->name);
+               seq_putc(p, '\n');
+unlock:
+               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+       }
+       return 0;
+}
+#endif
index 313cd80..b2e86d0 100644 (file)
 
 #include <asm/setup.h>
 #include <asm/irq.h>
-
-#ifdef CONFIG_BLK_DEV_INITRD
 #include <asm/pgtable.h>
-#endif
 
 #if defined(__H8300H__)
 #define CPU "H8/300H"
index d1ef615..3306382 100644 (file)
@@ -44,7 +44,7 @@ static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
-       profile_tick(CPU_PROFILING, regs);
+       profile_tick(CPU_PROFILING);
 }
 
 void time_init(void)
@@ -66,55 +66,3 @@ void time_init(void)
 
        platform_timer_setup(timer_interrupt);
 }
-
-/*
- * This version of gettimeofday has near microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
-       unsigned long flags;
-       unsigned long usec, sec;
-
-       read_lock_irqsave(&xtime_lock, flags);
-       usec = 0;
-       sec = xtime.tv_sec;
-       usec += (xtime.tv_nsec / 1000);
-       read_unlock_irqrestore(&xtime_lock, flags);
-
-       while (usec >= 1000000) {
-               usec -= 1000000;
-               sec++;
-       }
-
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_lock_irq(&xtime_lock);
-       /* This is revolting. We need to set the xtime.tv_usec
-        * correctly. However, the value in this location is
-        * is value at the last tick.
-        * Discover what correction gettimeofday
-        * would have done, and then undo it!
-        */
-       while (tv->tv_nsec < 0) {
-               tv->tv_nsec += NSEC_PER_SEC;
-               tv->tv_sec--;
-       }
-
-       xtime.tv_sec = tv->tv_sec;
-       xtime.tv_nsec = tv->tv_nsec;
-       ntp_clear();
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
-       return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
index 26ab172..5c7af09 100644 (file)
 
 #undef DEBUG
 
+#define VIRT_OFFSET (0x01000000)
+
 /*
  * Map some physical address range into the kernel address space.
  */
 void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
 {
-       return (void *)physaddr;
+       return (void *)(physaddr + VIRT_OFFSET);
 }
 
 /*
index 5d42c77..b24ea08 100644 (file)
@@ -4,4 +4,4 @@
 # Reuse any files we can from the H8/300H
 #
 
-obj-y := entry.o ints_h8300h.o ptrace_h8300h.o
+obj-y := entry.o irq_pin.o ptrace_h8300h.o
index d2dea24..f86ac3b 100644 (file)
        mov.l   er0,@-sp
 
        stc     ccr,r0l                         /* check kernel mode */
-       orc     #0x10,ccr
        btst    #4,r0l
        bne     5f
 
        mov.l   sp,@SYMBOL_NAME(sw_usp)         /* user mode */
        mov.l   @sp,er0
+       orc     #0x10,ccr
        mov.l   @SYMBOL_NAME(sw_ksp),sp
        sub.l   #(LRET-LORIG),sp                /* allocate LORIG - LRET */ 
        mov.l   er0,@-sp
@@ -165,7 +165,7 @@ SYMBOL_NAME_LABEL(interrupt_entry)
        dec.l   #1,er0
        mov.l   sp,er1
        subs    #4,er1                          /* adjust ret_pc */
-       jsr     @SYMBOL_NAME(process_int)
+       jsr     @SYMBOL_NAME(do_IRQ)
        mov.l   @SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
        beq     1f
        jsr     @SYMBOL_NAME(do_softirq)
index b6ea768..32b964a 100644 (file)
@@ -2,5 +2,5 @@
 # Makefile for the linux kernel.
 #
 
+extra-y :=  crt0_$(MODEL).o
 obj-y := timer.o
-extra-y =  crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8300h/ints_h8300h.c b/arch/h8300/platform/h8300h/ints_h8300h.c
deleted file mode 100644 (file)
index f177711..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8300h/ints_h8300h.c
- * Interrupt handling CPU variants
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/gpio.h>
-#include <asm/regs306x.h>
-
-/* saved vector list */
-const int __initdata h8300_saved_vectors[]={
-#if defined(CONFIG_GDB_DEBUG)
-       TRAP3_VEC,
-#endif
-       -1
-};
-
-/* trap entry table */
-const unsigned long __initdata h8300_trap_table[NR_TRAPS]={
-       0,0,0,0,0,0,0,0,
-       (unsigned long)system_call,  /* TRAPA #0 */
-       0,0,
-       (unsigned long)trace_break,  /* TRAPA #3 */
-};
-
-int h8300_enable_irq_pin(unsigned int irq)
-{
-       int bitmask;
-       if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
-               return 0;
-
-       /* initialize IRQ pin */
-       bitmask = 1 << (irq - EXT_IRQ0);
-       switch(irq) {
-       case EXT_IRQ0:
-       case EXT_IRQ1:
-       case EXT_IRQ2:
-       case EXT_IRQ3:
-               if (H8300_GPIO_RESERVE(H8300_GPIO_P8, bitmask) == 0)
-                       return -EBUSY;
-               H8300_GPIO_DDR(H8300_GPIO_P8, bitmask, H8300_GPIO_INPUT);
-               break;
-       case EXT_IRQ4:
-       case EXT_IRQ5:
-               if (H8300_GPIO_RESERVE(H8300_GPIO_P9, bitmask) == 0)
-                       return -EBUSY;
-               H8300_GPIO_DDR(H8300_GPIO_P9, bitmask, H8300_GPIO_INPUT);
-               break;
-       }
-
-       return 0;
-}
-
-void h8300_disable_irq_pin(unsigned int irq)
-{
-       int bitmask;
-       if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
-               return;
-
-       /* disable interrupt & release IRQ pin */
-       bitmask = 1 << (irq - EXT_IRQ0);
-       switch(irq) {
-       case EXT_IRQ0:
-       case EXT_IRQ1:
-       case EXT_IRQ2:
-       case EXT_IRQ3:
-               *(volatile unsigned char *)IER &= ~bitmask;
-               H8300_GPIO_FREE(H8300_GPIO_P8, bitmask);
-               break ;
-       case EXT_IRQ4:
-       case EXT_IRQ5:
-               *(volatile unsigned char *)IER &= ~bitmask;
-               H8300_GPIO_FREE(H8300_GPIO_P9, bitmask);
-               break;
-       }
-}
index aeb2e9f..f3d6b8e 100644 (file)
        mov.l   er0,@-sp
 
        stc     ccr,r0l                         /* check kernel mode */
-       orc     #0x10,ccr
        btst    #4,r0l
        bne     5f
 
-       mov.l   sp,@SYMBOL_NAME(sw_usp)         /* user mode */
-       mov.l   @sp,er0
+       /* user mode */
+       mov.l   sp,@SYMBOL_NAME(sw_usp)
+       mov.l   @sp,er0                         /* restore saved er0 */
+       orc     #0x10,ccr                       /* switch kernel stack */
        mov.l   @SYMBOL_NAME(sw_ksp),sp
        sub.l   #(LRET-LORIG),sp                /* allocate LORIG - LRET */ 
        stm.l   er0-er3,@-sp
@@ -55,8 +56,9 @@
        mov.l   er0,@(LER0-LER3:16,sp)          /* copy ER0 */
        bra     6f
 5:
-       mov.l   @sp,er0                         /* kernel mode */
-       subs    #2,sp                           /* dummy ccr */
+       /* kernel mode */
+       mov.l   @sp,er0                         /* restore saved er0 */
+       subs    #2,sp                           /* set dummy ccr */
        stm.l   er0-er3,@-sp
        mov.w   @(LRET-LER3:16,sp),r1           /* copy old ccr */
        mov.b   r1h,r1l
@@ -94,6 +96,7 @@
        mov.l   @sp+,er1
        add.l   #(LRET-LER1),sp                 /* remove LORIG - LRET */ 
        mov.l   sp,@SYMBOL_NAME(sw_ksp)
+       andc    #0xef,ccr                       /* switch to user mode */
        mov.l   er0,sp
        bra     8f
 7:
@@ -173,9 +176,6 @@ SYMBOL_NAME_LABEL(interrupt_entry)
 SYMBOL_NAME_LABEL(system_call)
        subs    #4,sp                           /* dummy LVEC */
        SAVE_ALL
-       mov.w   @(LCCR:16,sp),r1
-       bset    #4,r1l
-       ldc     r1l,ccr                         /* restore ccr */
        mov.l   er0,er4
        mov.l   #-ENOSYS,er0
        mov.l   er0,@(LER0:16,sp)
@@ -198,6 +198,7 @@ SYMBOL_NAME_LABEL(system_call)
        mov.l   @(LER1:16,sp),er0
        mov.l   @(LER2:16,sp),er1
        mov.l   @(LER3:16,sp),er2
+       andc    #0x7f,ccr
        jsr     @er4
        mov.l   er0,@(LER0:16,sp)                       /* save the return value */
 #if defined(CONFIG_SYSCALL_PRINT)
index 53d6237..64ad10f 100644 (file)
@@ -79,6 +79,10 @@ config ARCH_MAY_HAVE_PC_FDC
        bool
        default y
 
+config ARCH_USES_SLAB_PAGE_STRUCT
+       bool
+       default y
+
 config DMI
        bool
        default y
@@ -220,7 +224,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 +575,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 +585,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 +923,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 +982,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 +993,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 +1010,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 +1021,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 +1032,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 +1044,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 +1061,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..d8cda14 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);
+                               (unsigned long)__smp_locks,
+                               (unsigned long)__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 34728e4..6272a4f 100644 (file)
@@ -367,6 +367,12 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       if (flags & MAP_FIXED) {
+               if (prepare_hugepage_range(addr, len, pgoff))
+                       return -EINVAL;
+               return addr;
+       }
+
        if (addr) {
                addr = ALIGN(addr, HPAGE_SIZE);
                vma = find_vma(mm, addr);
index ae43688..1a7197e 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.
@@ -780,7 +849,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
                free_page(addr);
                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)
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..e23af4b 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
@@ -438,6 +439,16 @@ config IA64_PALINFO
          To use this option, you have to ensure that the "/proc file system
          support" (CONFIG_PROC_FS) is enabled, too.
 
+config IA64_MC_ERR_INJECT
+       tristate "MC error injection support"
+       help
+         Selets whether support for MC error injection. By enabling the
+         support, kernel provide sysfs interface for user application to
+         call MC error injection PAL procedure to inject various errors.
+         This is a useful tool for MCA testing.
+
+         If you're unsure, do not select this option.
+
 config SGI_SN
        def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
 
index 153bfdc..90bd960 100644 (file)
@@ -164,6 +164,7 @@ CONFIG_COMPAT=y
 CONFIG_IA64_MCA_RECOVERY=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+# CONFIG_MC_ERR_INJECT is not set
 CONFIG_SGI_SN=y
 # CONFIG_IA64_ESI is not set
 
index 098ee60..33e5a59 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
 obj-$(CONFIG_AUDIT)            += audit.o
 obj-$(CONFIG_PCI_MSI)          += msi_ia64.o
 mca_recovery-y                 += mca_drv.o mca_drv_asm.o
+obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
 
 obj-$(CONFIG_IA64_ESI)         += esi.o
 ifneq ($(CONFIG_IA64_ESI),)
index f45f91d..78d29b7 100644 (file)
@@ -660,6 +660,29 @@ efi_memory_descriptor (unsigned long phys_addr)
        return NULL;
 }
 
+static int
+efi_memmap_intersects (unsigned long phys_addr, unsigned long size)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+       unsigned long end;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       end = phys_addr + size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               if (md->phys_addr < end && efi_md_end(md) > phys_addr)
+                       return 1;
+       }
+       return 0;
+}
+
 u32
 efi_mem_type (unsigned long phys_addr)
 {
@@ -766,11 +789,28 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
 int
 valid_mmap_phys_addr_range (unsigned long pfn, unsigned long size)
 {
+       unsigned long phys_addr = pfn << PAGE_SHIFT;
+       u64 attr;
+
+       attr = efi_mem_attribute(phys_addr, size);
+
        /*
-        * MMIO regions are often missing from the EFI memory map.
-        * We must allow mmap of them for programs like X, so we
-        * currently can't do any useful validation.
+        * /dev/mem mmap uses normal user pages, so we don't need the entire
+        * granule, but the entire region we're mapping must support the same
+        * attribute.
         */
+       if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
+               return 1;
+
+       /*
+        * Intel firmware doesn't tell us about all the MMIO regions, so
+        * in general we have to allow mmap requests.  But if EFI *does*
+        * tell us about anything inside this region, we should deny it.
+        * The user can always map a smaller region to avoid the overlap.
+        */
+       if (efi_memmap_intersects(phys_addr, size))
+               return 0;
+
        return 1;
 }
 
index e7873ee..55fd2d5 100644 (file)
@@ -767,7 +767,7 @@ ENTRY(ia64_leave_syscall)
        ld8.fill r15=[r3]                       // M0|1 restore r15
        mov b6=r18                              // I0   restore b6
 
-       addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A
+       LOAD_PHYS_STACK_REG_SIZE(r17)
        mov f9=f0                                       // F    clear f9
 (pKStk) br.cond.dpnt.many skip_rbs_switch              // B
 
@@ -775,7 +775,6 @@ ENTRY(ia64_leave_syscall)
        shr.u r18=r19,16                // I0|1 get byte size of existing "dirty" partition
        cover                           // B    add current frame into dirty partition & set cr.ifs
        ;;
-(pUStk) ld4 r17=[r17]                  // M0|1 r17 = cpu_data->phys_stacked_size_p8
        mov r19=ar.bsp                  // M2   get new backing store pointer
        mov f10=f0                      // F    clear f10
 
@@ -953,9 +952,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
        shr.u r18=r19,16        // get byte size of existing "dirty" partition
        ;;
        mov r16=ar.bsp          // get existing backing store pointer
-       addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
-       ;;
-       ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
+       LOAD_PHYS_STACK_REG_SIZE(r17)
 (pKStk)        br.cond.dpnt skip_rbs_switch
 
        /*
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
new file mode 100644 (file)
index 0000000..d3e9f33
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * err_inject.c -
+ *     1.) Inject errors to a processor.
+ *     2.) Query error injection capabilities.
+ * This driver along with user space code can be acting as an error
+ * injection tool.
+ *
+ * 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.
+ *
+ * Written by: Fenghua Yu <fenghua.yu@intel.com>, Intel Corporation
+ * Copyright (C) 2006, Intel Corp.  All rights reserved.
+ *
+ */
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+
+#define ERR_INJ_DEBUG
+
+#define ERR_DATA_BUFFER_SIZE 3                 // Three 8-byte;
+
+#define define_one_ro(name)                                            \
+static SYSDEV_ATTR(name, 0444, show_##name, NULL)
+
+#define define_one_rw(name)                                            \
+static SYSDEV_ATTR(name, 0644, show_##name, store_##name)
+
+static u64 call_start[NR_CPUS];
+static u64 phys_addr[NR_CPUS];
+static u64 err_type_info[NR_CPUS];
+static u64 err_struct_info[NR_CPUS];
+static struct {
+       u64 data1;
+       u64 data2;
+       u64 data3;
+} __attribute__((__aligned__(16))) err_data_buffer[NR_CPUS];
+static s64 status[NR_CPUS];
+static u64 capabilities[NR_CPUS];
+static u64 resources[NR_CPUS];
+
+#define show(name)                                                     \
+static ssize_t                                                                 \
+show_##name(struct sys_device *dev, char *buf)                         \
+{                                                                      \
+       u32 cpu=dev->id;                                                \
+       return sprintf(buf, "%lx\n", name[cpu]);                        \
+}
+
+#define store(name)                                                    \
+static ssize_t                                                                 \
+store_##name(struct sys_device *dev, const char *buf, size_t size)     \
+{                                                                      \
+       unsigned int cpu=dev->id;                                       \
+       name[cpu] = simple_strtoull(buf, NULL, 16);                     \
+       return size;                                                    \
+}
+
+show(call_start)
+
+/* It's user's responsibility to call the PAL procedure on a specific
+ * processor. The cpu number in driver is only used for storing data.
+ */
+static ssize_t
+store_call_start(struct sys_device *dev, const char *buf, size_t size)
+{
+       unsigned int cpu=dev->id;
+       unsigned long call_start = simple_strtoull(buf, NULL, 16);
+
+#ifdef ERR_INJ_DEBUG
+       printk(KERN_DEBUG "pal_mc_err_inject for cpu%d:\n", cpu);
+       printk(KERN_DEBUG "err_type_info=%lx,\n", err_type_info[cpu]);
+       printk(KERN_DEBUG "err_struct_info=%lx,\n", err_struct_info[cpu]);
+       printk(KERN_DEBUG "err_data_buffer=%lx, %lx, %lx.\n",
+                         err_data_buffer[cpu].data1,
+                         err_data_buffer[cpu].data2,
+                         err_data_buffer[cpu].data3);
+#endif
+       switch (call_start) {
+           case 0: /* Do nothing. */
+               break;
+           case 1: /* Call pal_mc_error_inject in physical mode. */
+               status[cpu]=ia64_pal_mc_error_inject_phys(err_type_info[cpu],
+                                       err_struct_info[cpu],
+                                       ia64_tpa(&err_data_buffer[cpu]),
+                                       &capabilities[cpu],
+                                       &resources[cpu]);
+               break;
+           case 2: /* Call pal_mc_error_inject in virtual mode. */
+               status[cpu]=ia64_pal_mc_error_inject_virt(err_type_info[cpu],
+                                       err_struct_info[cpu],
+                                       ia64_tpa(&err_data_buffer[cpu]),
+                                       &capabilities[cpu],
+                                       &resources[cpu]);
+               break;
+           default:
+               status[cpu] = -EINVAL;
+               break;
+       }
+
+#ifdef ERR_INJ_DEBUG
+       printk(KERN_DEBUG "Returns: status=%d,\n", (int)status[cpu]);
+       printk(KERN_DEBUG "capapbilities=%lx,\n", capabilities[cpu]);
+       printk(KERN_DEBUG "resources=%lx\n", resources[cpu]);
+#endif
+       return size;
+}
+
+show(err_type_info)
+store(err_type_info)
+
+static ssize_t
+show_virtual_to_phys(struct sys_device *dev, char *buf)
+{
+       unsigned int cpu=dev->id;
+       return sprintf(buf, "%lx\n", phys_addr[cpu]);
+}
+
+static ssize_t
+store_virtual_to_phys(struct sys_device *dev, const char *buf, size_t size)
+{
+       unsigned int cpu=dev->id;
+       u64 virt_addr=simple_strtoull(buf, NULL, 16);
+       int ret;
+
+        ret = get_user_pages(current, current->mm, virt_addr,
+                        1, VM_READ, 0, NULL, NULL);
+       if (ret<=0) {
+#ifdef ERR_INJ_DEBUG
+               printk("Virtual address %lx is not existing.\n",virt_addr);
+#endif
+               return -EINVAL;
+       }
+
+       phys_addr[cpu] = ia64_tpa(virt_addr);
+       return size;
+}
+
+show(err_struct_info)
+store(err_struct_info)
+
+static ssize_t
+show_err_data_buffer(struct sys_device *dev, char *buf)
+{
+       unsigned int cpu=dev->id;
+
+       return sprintf(buf, "%lx, %lx, %lx\n",
+                       err_data_buffer[cpu].data1,
+                       err_data_buffer[cpu].data2,
+                       err_data_buffer[cpu].data3);
+}
+
+static ssize_t
+store_err_data_buffer(struct sys_device *dev, const char *buf, size_t size)
+{
+       unsigned int cpu=dev->id;
+       int ret;
+
+#ifdef ERR_INJ_DEBUG
+       printk("write err_data_buffer=[%lx,%lx,%lx] on cpu%d\n",
+                err_data_buffer[cpu].data1,
+                err_data_buffer[cpu].data2,
+                err_data_buffer[cpu].data3,
+                cpu);
+#endif
+       ret=sscanf(buf, "%lx, %lx, %lx",
+                       &err_data_buffer[cpu].data1,
+                       &err_data_buffer[cpu].data2,
+                       &err_data_buffer[cpu].data3);
+       if (ret!=ERR_DATA_BUFFER_SIZE)
+               return -EINVAL;
+
+       return size;
+}
+
+show(status)
+show(capabilities)
+show(resources)
+
+define_one_rw(call_start);
+define_one_rw(err_type_info);
+define_one_rw(err_struct_info);
+define_one_rw(err_data_buffer);
+define_one_rw(virtual_to_phys);
+define_one_ro(status);
+define_one_ro(capabilities);
+define_one_ro(resources);
+
+static struct attribute *default_attrs[] = {
+       &attr_call_start.attr,
+       &attr_virtual_to_phys.attr,
+       &attr_err_type_info.attr,
+       &attr_err_struct_info.attr,
+       &attr_err_data_buffer.attr,
+       &attr_status.attr,
+       &attr_capabilities.attr,
+       &attr_resources.attr,
+       NULL
+};
+
+static struct attribute_group err_inject_attr_group = {
+       .attrs = default_attrs,
+       .name = "err_inject"
+};
+/* Add/Remove err_inject interface for CPU device */
+static int __cpuinit err_inject_add_dev(struct sys_device * sys_dev)
+{
+       return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group);
+}
+
+static int __cpuinit err_inject_remove_dev(struct sys_device * sys_dev)
+{
+       sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
+       return 0;
+}
+static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb,
+               unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct sys_device *sys_dev;
+
+       sys_dev = get_cpu_sysdev(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+               err_inject_add_dev(sys_dev);
+               break;
+       case CPU_DEAD:
+               err_inject_remove_dev(sys_dev);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata err_inject_cpu_notifier =
+{
+       .notifier_call = err_inject_cpu_callback,
+};
+
+static int __init
+err_inject_init(void)
+{
+       int i;
+
+#ifdef ERR_INJ_DEBUG
+       printk(KERN_INFO "Enter error injection driver.\n");
+#endif
+       for_each_online_cpu(i) {
+               err_inject_cpu_callback(&err_inject_cpu_notifier, CPU_ONLINE,
+                               (void *)(long)i);
+       }
+
+       register_hotcpu_notifier(&err_inject_cpu_notifier);
+
+       return 0;
+}
+
+static void __exit
+err_inject_exit(void)
+{
+       int i;
+       struct sys_device *sys_dev;
+
+#ifdef ERR_INJ_DEBUG
+       printk(KERN_INFO "Exit error injection driver.\n");
+#endif
+       for_each_online_cpu(i) {
+               sys_dev = get_cpu_sysdev(i);
+               sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
+       }
+       unregister_hotcpu_notifier(&err_inject_cpu_notifier);
+}
+
+module_init(err_inject_init);
+module_exit(err_inject_exit);
+
+MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
+MODULE_DESCRIPTION("MC error injection kenrel sysfs interface");
+MODULE_LICENSE("GPL");
index 6b7fcbd..34f44d8 100644 (file)
@@ -374,6 +374,7 @@ ENTRY(alt_dtlb_miss)
        movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
        mov r21=cr.ipsr
        mov r31=pr
+       mov r24=PERCPU_ADDR
        ;;
 #ifdef CONFIG_DISABLE_VHPT
        shr.u r22=r16,61                        // get the region number into r21
@@ -386,22 +387,30 @@ ENTRY(alt_dtlb_miss)
 (p8)   mov r29=b0                              // save b0
 (p8)   br.cond.dptk dtlb_fault
 #endif
+       cmp.ge p10,p11=r16,r24                  // access to per_cpu_data?
+       tbit.z p12,p0=r16,61                    // access to region 6?
+       mov r25=PERCPU_PAGE_SHIFT << 2
+       mov r26=PERCPU_PAGE_SIZE
+       nop.m 0
+       nop.b 0
+       ;;
+(p10)  mov r19=IA64_KR(PER_CPU_DATA)
+(p11)  and r19=r19,r16                         // clear non-ppn fields
        extr.u r23=r21,IA64_PSR_CPL0_BIT,2      // extract psr.cpl
        and r22=IA64_ISR_CODE_MASK,r20          // get the isr.code field
        tbit.nz p6,p7=r20,IA64_ISR_SP_BIT       // is speculation bit on?
-       shr.u r18=r16,57                        // move address bit 61 to bit 4
-       and r19=r19,r16                         // clear ed, reserved bits, and PTE control bits
        tbit.nz p9,p0=r20,IA64_ISR_NA_BIT       // is non-access bit on?
        ;;
-       andcm r18=0x10,r18      // bit 4=~address-bit(61)
+(p10)  sub r19=r19,r26
+(p10)  mov cr.itir=r25
        cmp.ne p8,p0=r0,r23
 (p9)   cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22  // check isr.code field
+(p12)  dep r17=-1,r17,4,1                      // set ma=UC for region 6 addr
 (p8)   br.cond.spnt page_fault
 
        dep r21=-1,r21,IA64_PSR_ED_BIT,1
-       or r19=r19,r17          // insert PTE control bits into r19
        ;;
-       or r19=r19,r18          // set bit 4 (uncached) if the access was to region 6
+       or r19=r19,r17          // insert PTE control bits into r19
 (p6)   mov cr.ipsr=r21
        ;;
 (p7)   itc.d r19               // insert the TLB entry
index c6b607c..8c9c26a 100644 (file)
@@ -101,14 +101,6 @@ ia64_do_tlb_purge:
        ;;
        srlz.d
        ;;
-       // 2. Purge DTR for PERCPU data.
-       movl r16=PERCPU_ADDR
-       mov r18=PERCPU_PAGE_SHIFT<<2
-       ;;
-       ptr.d r16,r18
-       ;;
-       srlz.d
-       ;;
        // 3. Purge ITR for PAL code.
        GET_THIS_PADDR(r2, ia64_mca_pal_base)
        ;;
@@ -196,22 +188,6 @@ ia64_reload_tr:
        srlz.i
        srlz.d
        ;;
-       // 2. Reload DTR register for PERCPU data.
-       GET_THIS_PADDR(r2, ia64_mca_per_cpu_pte)
-       ;;
-       movl r16=PERCPU_ADDR            // vaddr
-       movl r18=PERCPU_PAGE_SHIFT<<2
-       ;;
-       mov cr.itir=r18
-       mov cr.ifa=r16
-       ;;
-       ld8 r18=[r2]                    // load per-CPU PTE
-       mov r16=IA64_TR_PERCPU_DATA;
-       ;;
-       itr.d dtr[r16]=r18
-       ;;
-       srlz.d
-       ;;
        // 3. Reload ITR for PAL code.
        GET_THIS_PADDR(r2, ia64_mca_pal_pte)
        ;;
index bc11bb0..e796e29 100644 (file)
@@ -195,3 +195,23 @@ ia64_patch_gate (void)
        ia64_patch_vtop(START(vtop), END(vtop));
        ia64_patch_mckinley_e9(START(mckinley_e9), END(mckinley_e9));
 }
+
+void ia64_patch_phys_stack_reg(unsigned long val)
+{
+       s32 * offp = (s32 *) __start___phys_stack_reg_patchlist;
+       s32 * end = (s32 *) __end___phys_stack_reg_patchlist;
+       u64 ip, mask, imm;
+
+       /* see instruction format A4: adds r1 = imm13, r3 */
+       mask = (0x3fUL << 27) | (0x7f << 13);
+       imm = (((val >> 7) & 0x3f) << 27) | (val & 0x7f) << 13;
+
+       while (offp < end) {
+               ip = (u64) offp + *offp;
+               ia64_patch(ip, mask, imm);
+               ia64_fc(ip);
+               ++offp;
+       }
+       ia64_sync_i();
+       ia64_srlz_i();
+}
index dc7dd76..6e19da1 100644 (file)
@@ -75,7 +75,6 @@ extern void ia64_setup_printk_clock(void);
 
 DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
 DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
-DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8);
 unsigned long ia64_cycles_per_usec;
 struct ia64_boot_param *ia64_boot_param;
 struct screen_info screen_info;
@@ -869,6 +868,7 @@ void __cpuinit
 cpu_init (void)
 {
        extern void __cpuinit ia64_mmu_init (void *);
+       static unsigned long max_num_phys_stacked = IA64_NUM_PHYS_STACK_REG;
        unsigned long num_phys_stacked;
        pal_vm_info_2_u_t vmi;
        unsigned int max_ctx;
@@ -982,7 +982,10 @@ cpu_init (void)
                num_phys_stacked = 96;
        }
        /* size of physical stacked register partition plus 8 bytes: */
-       __get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8;
+       if (num_phys_stacked > max_num_phys_stacked) {
+               ia64_patch_phys_stack_reg(num_phys_stacked*8 + 8);
+               max_num_phys_stacked = num_phys_stacked;
+       }
        platform_cpu_init();
        pm_idle = default_idle;
 }
index 9ef62a3..2fcaa20 100644 (file)
@@ -33,6 +33,13 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
        if (len > RGN_MAP_LIMIT)
                return -ENOMEM;
 
+       /* handle fixed mapping: prevent overlap with huge pages */
+       if (flags & MAP_FIXED) {
+               if (is_hugepage_only_range(mm, addr, len))
+                       return -EINVAL;
+               return addr;
+       }
+
 #ifdef CONFIG_HUGETLB_PAGE
        if (REGION_NUMBER(addr) == RGN_HPAGE)
                addr = 0;
index 25dd55e..6923826 100644 (file)
@@ -78,6 +78,13 @@ SECTIONS
          __stop___mca_table = .;
        }
 
+  .data.patch.phys_stack_reg : AT(ADDR(.data.patch.phys_stack_reg) - LOAD_OFFSET)
+       {
+         __start___phys_stack_reg_patchlist = .;
+         *(.data.patch.phys_stack_reg)
+         __end___phys_stack_reg_patchlist = .;
+       }
+
   /* Global data */
   _data = .;
 
index 0c7e94e..c7c90f4 100644 (file)
@@ -148,6 +148,14 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
                return -ENOMEM;
        if (len & ~HPAGE_MASK)
                return -EINVAL;
+
+       /* Handle MAP_FIXED */
+       if (flags & MAP_FIXED) {
+               if (prepare_hugepage_range(addr, len, pgoff))
+                       return -EINVAL;
+               return addr;
+       }
+
        /* This code assumes that RGN_HPAGE != 0. */
        if ((REGION_NUMBER(addr) != RGN_HPAGE) || (addr & (HPAGE_SIZE - 1)))
                addr = HPAGE_REGION_BASE;
index 4f36987..cffb1e8 100644 (file)
@@ -121,7 +121,7 @@ lazy_mmu_prot_update (pte_t pte)
                return;                         /* i-cache is already coherent with d-cache */
 
        if (PageCompound(page)) {
-               order = (unsigned long) (page[1].lru.prev);
+               order = compound_order(page);
                flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
        }
        else
@@ -355,7 +355,7 @@ setup_gate (void)
 void __devinit
 ia64_mmu_init (void *my_cpu_data)
 {
-       unsigned long psr, pta, impl_va_bits;
+       unsigned long pta, impl_va_bits;
        extern void __devinit tlb_init (void);
 
 #ifdef CONFIG_DISABLE_VHPT
@@ -364,15 +364,6 @@ ia64_mmu_init (void *my_cpu_data)
 #      define VHPT_ENABLE_BIT  1
 #endif
 
-       /* Pin mapping for percpu area into TLB */
-       psr = ia64_clear_ic();
-       ia64_itr(0x2, IA64_TR_PERCPU_DATA, PERCPU_ADDR,
-                pte_val(pfn_pte(__pa(my_cpu_data) >> PAGE_SHIFT, PAGE_KERNEL)),
-                PERCPU_PAGE_SHIFT);
-
-       ia64_set_psr(psr);
-       ia64_srlz_i();
-
        /*
         * Check if the virtually mapped linear page table (VMLPT) overlaps with a mapped
         * address space.  The IA-64 architecture guarantees that at least 50 bits of
index 4280c07..2a14062 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (c) Copyright 2006 Hewlett-Packard Development Company, L.P.
+ * (c) Copyright 2006, 2007 Hewlett-Packard Development Company, L.P.
  *     Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
  * This program is free software; you can redistribute it and/or modify
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/efi.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/meminit.h>
 
 static inline void __iomem *
-__ioremap (unsigned long offset, unsigned long size)
+__ioremap (unsigned long phys_addr)
 {
-       return (void __iomem *) (__IA64_UNCACHED_OFFSET | offset);
+       return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr);
 }
 
 void __iomem *
-ioremap (unsigned long offset, unsigned long size)
+ioremap (unsigned long phys_addr, unsigned long size)
 {
+       void __iomem *addr;
+       struct vm_struct *area;
+       unsigned long offset;
+       pgprot_t prot;
        u64 attr;
        unsigned long gran_base, gran_size;
+       unsigned long page_base;
 
        /*
         * For things in kern_memmap, we must use the same attribute
         * as the rest of the kernel.  For more details, see
         * Documentation/ia64/aliasing.txt.
         */
-       attr = kern_mem_attribute(offset, size);
+       attr = kern_mem_attribute(phys_addr, size);
        if (attr & EFI_MEMORY_WB)
-               return (void __iomem *) phys_to_virt(offset);
+               return (void __iomem *) phys_to_virt(phys_addr);
        else if (attr & EFI_MEMORY_UC)
-               return __ioremap(offset, size);
+               return __ioremap(phys_addr);
 
        /*
         * Some chipsets don't support UC access to memory.  If
         * WB is supported for the whole granule, we prefer that.
         */
-       gran_base = GRANULEROUNDDOWN(offset);
-       gran_size = GRANULEROUNDUP(offset + size) - gran_base;
+       gran_base = GRANULEROUNDDOWN(phys_addr);
+       gran_size = GRANULEROUNDUP(phys_addr + size) - gran_base;
        if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
-               return (void __iomem *) phys_to_virt(offset);
+               return (void __iomem *) phys_to_virt(phys_addr);
 
-       return __ioremap(offset, size);
+       /*
+        * WB is not supported for the whole granule, so we can't use
+        * the region 7 identity mapping.  If we can safely cover the
+        * area with kernel page table mappings, we can use those
+        * instead.
+        */
+       page_base = phys_addr & PAGE_MASK;
+       size = PAGE_ALIGN(phys_addr + size) - page_base;
+       if (efi_mem_attribute(page_base, size) & EFI_MEMORY_WB) {
+               prot = PAGE_KERNEL;
+
+               /*
+                * Mappings have to be page-aligned
+                */
+               offset = phys_addr & ~PAGE_MASK;
+               phys_addr &= PAGE_MASK;
+
+               /*
+                * Ok, go for it..
+                */
+               area = get_vm_area(size, VM_IOREMAP);
+               if (!area)
+                       return NULL;
+
+               area->phys_addr = phys_addr;
+               addr = (void __iomem *) area->addr;
+               if (ioremap_page_range((unsigned long) addr,
+                               (unsigned long) addr + size, phys_addr, prot)) {
+                       vunmap((void __force *) addr);
+                       return NULL;
+               }
+
+               return (void __iomem *) (offset + (char __iomem *)addr);
+       }
+
+       return __ioremap(phys_addr);
 }
 EXPORT_SYMBOL(ioremap);
 
 void __iomem *
-ioremap_nocache (unsigned long offset, unsigned long size)
+ioremap_nocache (unsigned long phys_addr, unsigned long size)
 {
-       if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
+       if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
                return NULL;
 
-       return __ioremap(offset, size);
+       return __ioremap(phys_addr);
 }
 EXPORT_SYMBOL(ioremap_nocache);
+
+void
+iounmap (volatile void __iomem *addr)
+{
+       if (REGION_NUMBER(addr) == RGN_GATE)
+               vunmap((void *) ((unsigned long) addr & PAGE_MASK));
+}
+EXPORT_SYMBOL(iounmap);
index 0e83f3b..9f63589 100644 (file)
@@ -659,8 +659,6 @@ pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma)
                return -EINVAL;
        prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
                                    vma->vm_page_prot);
-       if (pgprot_val(prot) != pgprot_val(pgprot_noncached(vma->vm_page_prot)))
-               return -EINVAL;
 
        addr = pci_get_legacy_mem(bus);
        if (IS_ERR(addr))
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 28d95cf..907a553 100644 (file)
@@ -54,7 +54,7 @@ static irqreturn_t ami_int5(int irq, void *dev_id);
 
 static struct irq_controller amiga_irq_controller = {
        .name           = "amiga",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock),
        .enable         = amiga_enable_irq,
        .disable        = amiga_disable_irq,
 };
index 7a20058..c4a4ffd 100644 (file)
@@ -123,7 +123,7 @@ static void cia_disable_irq(unsigned int irq)
 
 static struct irq_controller cia_irq_controller = {
        .name           = "cia",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock),
        .enable         = cia_enable_irq,
        .disable        = cia_disable_irq,
 };
@@ -160,7 +160,7 @@ static void auto_disable_irq(unsigned int irq)
 
 static struct irq_controller auto_irq_controller = {
        .name           = "auto",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
        .enable         = auto_enable_irq,
        .disable        = auto_disable_irq,
 };
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 4274af1..13bd41b 100644 (file)
@@ -31,7 +31,7 @@ void apollo_irq_shutdown(unsigned int irq)
 
 static struct irq_controller apollo_irq_controller = {
        .name           = "apollo",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock),
        .startup        = apollo_irq_startup,
        .shutdown       = apollo_irq_shutdown,
 };
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
index 7f81264..b85ca22 100644 (file)
@@ -339,7 +339,7 @@ static void atari_shutdown_irq(unsigned int irq)
 
 static struct irq_controller atari_irq_controller = {
        .name           = "atari",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock),
        .startup        = atari_startup_irq,
        .shutdown       = atari_shutdown_irq,
        .enable         = atari_enable_irq,
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;
+}
diff --git a/arch/m68k/atari/atasound.h b/arch/m68k/atari/atasound.h
deleted file mode 100644 (file)
index 1362762..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Minor numbers for the sound driver.
- *
- * Unfortunately Creative called the codec chip of SB as a DSP. For this
- * reason the /dev/dsp is reserved for digitized audio use. There is a
- * device for true DSP processors but it will be called something else.
- * In v3.0 it's /dev/sndproc but this could be a temporary solution.
- */
-
-#define SND_NDEVS      256     /* Number of supported devices */
-#define SND_DEV_CTL    0       /* Control port /dev/mixer */
-#define SND_DEV_SEQ    1       /* Sequencer output /dev/sequencer (FM
-                                  synthesizer and MIDI output) */
-#define SND_DEV_MIDIN  2       /* Raw midi access */
-#define SND_DEV_DSP    3       /* Digitized voice /dev/dsp */
-#define SND_DEV_AUDIO  4       /* Sparc compatible /dev/audio */
-#define SND_DEV_DSP16  5       /* Like /dev/dsp but 16 bits/sample */
-#define SND_DEV_STATUS 6       /* /dev/sndstat */
-/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
-#define SND_DEV_SEQ2   8       /* /dev/sequencer, level 2 interface */
-#define SND_DEV_SNDPROC 9      /* /dev/sndproc for programmable devices */
-#define SND_DEV_PSS    SND_DEV_SNDPROC
-
-#define DSP_DEFAULT_SPEED      8000
-
-#define ON             1
-#define OFF            0
-
-#define MAX_AUDIO_DEV  5
-#define MAX_MIXER_DEV  2
-#define MAX_SYNTH_DEV  3
-#define MAX_MIDI_DEV   6
-#define MAX_TIMER_DEV  3
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 b66c97c..60d4d75 100644 (file)
@@ -59,14 +59,14 @@ static int m68k_first_user_vec;
 
 static struct irq_controller auto_irq_controller = {
        .name           = "auto",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
        .startup        = m68k_irq_startup,
        .shutdown       = m68k_irq_shutdown,
 };
 
 static struct irq_controller user_irq_controller = {
        .name           = "user",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(user_irq_controller.lock),
        .startup        = m68k_irq_startup,
        .shutdown       = m68k_irq_shutdown,
 };
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 f6fcd75..0fc72d8 100644 (file)
@@ -219,7 +219,7 @@ static void mac_disable_irq(unsigned int irq);
 
 static struct irq_controller mac_irq_controller = {
        .name           = "mac",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock),
        .enable         = mac_enable_irq,
        .disable        = mac_disable_irq,
 };
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 31cc07d..2fb25ae 100644 (file)
@@ -59,7 +59,7 @@ static void q40_irq_shutdown(unsigned int irq)
 
 static struct irq_controller q40_irq_controller = {
        .name           = "q40",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
        .startup        = q40_irq_startup,
        .shutdown       = q40_irq_shutdown,
        .enable         = q40_enable_irq,
index baf74e8..50df34b 100644 (file)
@@ -90,7 +90,7 @@ static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
 
 static struct irq_controller sun3_irq_controller = {
        .name           = "sun3",
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock),
        .startup        = m68k_irq_startup,
        .shutdown       = m68k_irq_shutdown,
        .enable         = sun3_enable_irq,
@@ -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 130d825..7441a2c 100644 (file)
@@ -1042,6 +1042,9 @@ config SOC_AU1X00
        select SYS_SUPPORTS_APM_EMULATION
        select SYS_SUPPORTS_KGDB
 
+config SERIAL_RM9000
+       bool
+
 config PNX8550
        bool
        select SOC_PNX8550
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>
 
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c
new file mode 100644 (file)
index 0000000..c41b53f
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * The setup file for serial related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2005 PMC-Sierra, 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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/serial.h>
+
+#include <msp_prom.h>
+#include <msp_int.h>
+#include <msp_regs.h>
+
+#ifdef CONFIG_KGDB
+/*
+ * kgdb uses serial port 1 so the console can remain on port 0.
+ * To use port 0 change the definition to read as follows:
+ * #define DEBUG_PORT_BASE KSEG1ADDR(MSP_UART0_BASE)
+ */
+#define DEBUG_PORT_BASE KSEG1ADDR(MSP_UART1_BASE)
+
+int putDebugChar(char c)
+{
+       volatile uint32_t *uart = (volatile uint32_t *)DEBUG_PORT_BASE;
+       uint32_t val = (uint32_t)c;
+
+       local_irq_disable();
+       while( !(uart[5] & 0x20) ); /* Wait for TXRDY */
+       uart[0] = val;
+       while( !(uart[5] & 0x20) ); /* Wait for TXRDY */
+       local_irq_enable();
+
+       return 1;
+}
+
+char getDebugChar(void)
+{
+       volatile uint32_t *uart = (volatile uint32_t *)DEBUG_PORT_BASE;
+       uint32_t val;
+
+       while( !(uart[5] & 0x01) ); /* Wait for RXRDY */
+       val = uart[0];
+
+       return (char)val;
+}
+
+void initDebugPort(unsigned int uartclk, unsigned int baudrate)
+{
+       unsigned int baud_divisor = (uartclk + 8 * baudrate)/(16 * baudrate);
+
+       /* Enable FIFOs */
+       writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+                       UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_4,
+               (char *)DEBUG_PORT_BASE + (UART_FCR * 4));
+
+       /* Select brtc divisor */
+       writeb(UART_LCR_DLAB, (char *)DEBUG_PORT_BASE + (UART_LCR * 4));
+
+       /* Store divisor lsb */
+       writeb(baud_divisor, (char *)DEBUG_PORT_BASE + (UART_TX * 4));
+
+       /* Store divisor msb */
+       writeb(baud_divisor >> 8, (char *)DEBUG_PORT_BASE + (UART_IER * 4));
+
+       /* Set 8N1 mode */
+       writeb(UART_LCR_WLEN8, (char *)DEBUG_PORT_BASE + (UART_LCR * 4));
+
+       /* Disable flow control */
+       writeb(0, (char *)DEBUG_PORT_BASE + (UART_MCR * 4));
+
+       /* Disable receive interrupt(!) */
+       writeb(0, (char *)DEBUG_PORT_BASE + (UART_IER * 4));
+}
+#endif
+
+void __init msp_serial_setup(void)
+{
+       char    *s;
+       char    *endp;
+       struct uart_port up;
+       unsigned int uartclk;
+
+       memset(&up, 0, sizeof(up));
+
+       /* Check if clock was specified in environment */
+       s = prom_getenv("uartfreqhz");
+       if(!(s && *s && (uartclk = simple_strtoul(s, &endp, 10)) && *endp == 0))
+               uartclk = MSP_BASE_BAUD;
+       ppfinit("UART clock set to %d\n", uartclk);
+
+       /* Initialize first serial port */
+       up.mapbase      = MSP_UART0_BASE;
+       up.membase      = ioremap_nocache(up.mapbase,MSP_UART_REG_LEN);
+       up.irq          = MSP_INT_UART0;
+       up.uartclk      = uartclk;
+       up.regshift     = 2;
+       up.iotype       = UPIO_DWAPB; /* UPIO_MEM like */
+       up.flags        = STD_COM_FLAGS;
+       up.type         = PORT_16550A;
+       up.line         = 0;
+       up.private_data         = (void*)UART0_STATUS_REG;
+       if (early_serial_setup(&up))
+               printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+       /* Initialize the second serial port, if one exists */
+       switch (mips_machtype) {
+               case MACH_MSP4200_EVAL:
+               case MACH_MSP4200_GW:
+               case MACH_MSP4200_FPGA:
+               case MACH_MSP7120_EVAL:
+               case MACH_MSP7120_GW:
+               case MACH_MSP7120_FPGA:
+                       /* Enable UART1 on MSP4200 and MSP7120 */
+                       *GPIO_CFG2_REG = 0x00002299;
+
+#ifdef CONFIG_KGDB
+                       /* Initialize UART1 for kgdb since PMON doesn't */
+                       if( DEBUG_PORT_BASE == KSEG1ADDR(MSP_UART1_BASE) ) {
+                               if( mips_machtype == MACH_MSP4200_FPGA
+                                || mips_machtype == MACH_MSP7120_FPGA )
+                                       initDebugPort(uartclk,19200);
+                               else
+                                       initDebugPort(uartclk,57600);
+                       }
+#endif
+                       break;
+
+               default:
+                       return; /* No second serial port, good-bye. */
+       }
+
+       up.mapbase      = MSP_UART1_BASE;
+       up.membase      = ioremap_nocache(up.mapbase,MSP_UART_REG_LEN);
+       up.irq          = MSP_INT_UART1;
+       up.line         = 1;
+       up.private_data         = (void*)UART1_STATUS_REG;
+       if (early_serial_setup(&up))
+               printk(KERN_ERR "Early serial init of port 1 failed\n");
+}
index 512642d..6fed080 100644 (file)
@@ -106,6 +106,11 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 {
        if (len > TASK_SIZE)
                return -ENOMEM;
+       /* Might want to check for cache aliasing issues for MAP_FIXED case
+        * like ARM or MIPS ??? --BenH.
+        */
+       if (flags & MAP_FIXED)
+               return addr;
        if (!addr)
                addr = TASK_UNMAPPED_BASE;
 
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 a54a9a2..8de5f9f 100644 (file)
@@ -117,6 +117,19 @@ config GENERIC_BUG
        default y
        depends on BUG
 
+#
+# Powerpc uses the slab allocator to manage its ptes and the
+# page structs of ptes are used for splitting the page table
+# lock for configurations supporting more than SPLIT_PTLOCK_CPUS.
+#
+# In that special configuration the page structs of slabs are modified.
+# This setting disables the selection of SLUB as a slab allocator.
+#
+config ARCH_USES_SLAB_PAGE_STRUCT
+       bool
+       default y
+       depends on SPLIT_PTLOCK_CPUS <= NR_CPUS
+
 config DEFAULT_UIMAGE
        bool
        help
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 63dd2c3..ae4836e 100644 (file)
@@ -115,7 +115,8 @@ static int __init add_legacy_soc_port(struct device_node *np,
 {
        u64 addr;
        const u32 *addrp;
-       upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+       upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ
+               | UPF_FIXED_PORT;
        struct device_node *tsi = of_get_parent(np);
 
        /* We only support ports that have a clock frequency properly
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 8508f97..1f07f70 100644 (file)
@@ -566,6 +566,13 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       /* handle fixed mapping: prevent overlap with huge pages */
+       if (flags & MAP_FIXED) {
+               if (is_hugepage_only_range(mm, addr, len))
+                       return -EINVAL;
+               return addr;
+       }
+
        if (addr) {
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
@@ -641,6 +648,13 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       /* handle fixed mapping: prevent overlap with huge pages */
+       if (flags & MAP_FIXED) {
+               if (is_hugepage_only_range(mm, addr, len))
+                       return -EINVAL;
+               return addr;
+       }
+
        /* dont allow allocations above current base */
        if (mm->free_area_cache > base)
                mm->free_area_cache = base;
@@ -823,6 +837,13 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
        /* Paranoia, caller should have dealt with this */
        BUG_ON((addr + len)  < addr);
 
+       /* Handle MAP_FIXED */
+       if (flags & MAP_FIXED) {
+               if (prepare_hugepage_range(addr, len, pgoff))
+                       return -EINVAL;
+               return addr;
+       }
+
        if (test_thread_flag(TIF_32BIT)) {
                curareas = current->mm->context.low_htlb_areas;
 
@@ -1057,8 +1078,7 @@ static int __init hugetlbpage_init(void)
        huge_pgtable_cache = kmem_cache_create("hugepte_cache",
                                               HUGEPTE_TABLE_SIZE,
                                               HUGEPTE_TABLE_SIZE,
-                                              SLAB_HWCACHE_ALIGN |
-                                              SLAB_MUST_HWCACHE_ALIGN,
+                                              0,
                                               zero_ctor, NULL);
        if (! huge_pgtable_cache)
                panic("hugetlbpage_init(): could not create hugepte cache\n");
index d12a87e..4416d51 100644 (file)
@@ -183,8 +183,7 @@ void pgtable_cache_init(void)
                    "for size: %08x...\n", name, i, size);
                pgtable_cache[i] = kmem_cache_create(name,
                                                     size, size,
-                                                    SLAB_HWCACHE_ALIGN |
-                                                    SLAB_MUST_HWCACHE_ALIGN,
+                                                    0,
                                                     zero_ctor,
                                                     NULL);
                if (! pgtable_cache[i])
index 13e4f70..a93f328 100644 (file)
@@ -71,8 +71,7 @@ spufs_init_once(void *p, struct kmem_cache * cachep, unsigned long flags)
 {
        struct spufs_inode_info *ei = p;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&ei->vfs_inode);
        }
 }
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 e6ec418..1a84719 100644 (file)
@@ -49,6 +49,9 @@ config GENERIC_BUG
 config NO_IOMEM
        def_bool y
 
+config NO_DMA
+       def_bool y
+
 mainmenu "Linux Kernel Configuration"
 
 config S390
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 4d16d89..d74eb12 100644 (file)
@@ -22,6 +22,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config GENERIC_BUG
+       def_bool y
+       depends on BUG
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
@@ -88,6 +92,14 @@ config SH_SOLUTION_ENGINE
          Select SolutionEngine if configuring for a Hitachi SH7709
          or SH7750 evaluation board.
 
+config SH_7722_SOLUTION_ENGINE
+       bool "SolutionEngine7722"
+       select SOLUTION_ENGINE
+       select CPU_SUBTYPE_SH7722
+       help
+         Select 7722 SolutionEngine if configuring for a Hitachi SH772
+         evaluation board.
+
 config SH_7751_SOLUTION_ENGINE
        bool "SolutionEngine7751"
        select SOLUTION_ENGINE
@@ -95,6 +107,14 @@ config SH_7751_SOLUTION_ENGINE
        help
          Select 7751 SolutionEngine if configuring for a Hitachi SH7751
          evaluation board.
+         
+config SH_7780_SOLUTION_ENGINE
+       bool "SolutionEngine7780"
+       select SOLUTION_ENGINE
+       select CPU_SUBTYPE_SH7780
+       help
+         Select 7780 SolutionEngine if configuring for a Renesas SH7780
+         evaluation board.
 
 config SH_7300_SOLUTION_ENGINE
        bool "SolutionEngine7300"
@@ -193,12 +213,8 @@ config SH_RTS7751R2D
          Select RTS7751R2D if configuring for a Renesas Technology
          Sales SH-Graphics board.
 
-config SH_R7780RP
-       bool "R7780RP-1"
-       select CPU_SUBTYPE_SH7780
-       help
-         Select R7780RP-1 if configuring for a Renesas Solutions
-         HIGHLANDER board.
+config SH_HIGHLANDER
+       bool "Highlander"
 
 config SH_EDOSK7705
        bool "EDOSK7705"
@@ -243,6 +259,12 @@ config SH_7619_SOLUTION_ENGINE
        help
          Select 7619 SolutionEngine if configuring for a Hitachi SH7619
          evaluation board.
+       
+config SH_LBOX_RE2
+       bool "L-BOX RE2"
+       select CPU_SUBTYPE_SH7751R
+       help
+         Select L-BOX RE2 if configuring for the NTT COMWARE L-BOX RE2.
 
 config SH_UNKNOWN
        bool "BareCPU"
@@ -258,6 +280,10 @@ config SH_UNKNOWN
 
 endchoice
 
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+source "arch/sh/boards/renesas/r7780rp/Kconfig"
+
 source "arch/sh/mm/Kconfig"
 
 config CF_ENABLER
@@ -366,6 +392,16 @@ config SH_STORE_QUEUES
          Selecting this option will enable an in-kernel API for manipulating
          the store queues integrated in the SH-4 processors.
 
+config SPECULATIVE_EXECUTION
+       bool "Speculative subroutine return"
+       depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL
+       help
+         This enables support for a speculative instruction fetch for
+         subroutine return. There are various pitfalls associated with
+         this, as outlined in the SH7780 hardware manual.
+
+         If unsure, say N.
+
 config CPU_HAS_INTEVT
        bool
 
@@ -398,8 +434,9 @@ config CPU_HAS_PTEA
 
 endmenu
 
-menu "Timer support"
-depends on !GENERIC_TIME
+menu "Timer and clock configuration"
+
+if !GENERIC_TIME
 
 config SH_TMU
        bool "TMU timer support"
@@ -422,17 +459,11 @@ config SH_MTU2
        help
          This enables the use of the MTU2 as the system timer.
 
-endmenu
-
-source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
-
-source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
-
-source "arch/sh/boards/renesas/r7780rp/Kconfig"
+endif
 
 config SH_TIMER_IRQ
        int
-       default "28" if CPU_SUBTYPE_SH7780
+       default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
        default "86" if CPU_SUBTYPE_SH7619
        default "140" if CPU_SUBTYPE_SH7206
        default "16"
@@ -462,7 +493,8 @@ config SH_PCLK_FREQ
        default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
                              CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
                              CPU_SUBTYPE_SH7206
-       default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
+       default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 || \
+                             CPU_SUBTYPE_SH7785
        default "60000000" if CPU_SUBTYPE_SH7751
        default "66000000" if CPU_SUBTYPE_SH4_202
        help
@@ -477,6 +509,8 @@ config SH_CLK_MD
        help
          MD2 - MD0 pin setting.
 
+endmenu
+
 menu "CPU Frequency scaling"
 
 source "drivers/cpufreq/Kconfig"
@@ -495,21 +529,6 @@ config SH_CPU_FREQ
 
 endmenu
 
-source "arch/sh/drivers/dma/Kconfig"
-
-source "arch/sh/cchips/Kconfig"
-
-config HEARTBEAT
-       bool "Heartbeat LED"
-       depends on SH_MPC1211 || SH_SH03 || \
-                  SOLUTION_ENGINE || \
-                  SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK || \
-                  SH_R7780RP
-       help
-         Use the power-on LED on your machine as a load meter.  The exact
-         behavior is platform-dependent, but normally the flash frequency is
-         a hyperbolic function of the 5-minute load average.
-
 source "arch/sh/drivers/Kconfig"
 
 endmenu
@@ -540,6 +559,20 @@ config KEXEC
          support.  As of this writing the exact hardware interface is
          strongly in flux, so no good recommendation can be made.
 
+config CRASH_DUMP
+       bool "kernel crash dumps (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         Generate crash dump after being started by kexec.
+         This should be normally only set in special crash dump kernels
+         which are loaded in the main kernel with kexec-tools into
+         a specially reserved region and then later executed after
+         a crash by kdump/kexec. The crash dump kernel must be compiled
+         to a memory address not used by the main kernel using
+         MEMORY_START.
+
+         For more details see Documentation/kdump/kdump.txt
+
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
index 87902e0..b563072 100644 (file)
@@ -33,6 +33,7 @@ config EARLY_SCIF_CONSOLE_PORT
        default "0xffe00000" if CPU_SUBTYPE_SH7780
        default "0xfffe9800" if CPU_SUBTYPE_SH7206
        default "0xf8420000" if CPU_SUBTYPE_SH7619
+       default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705
        default "0xffe80000" if CPU_SH4
 
 config EARLY_PRINTK
@@ -77,16 +78,17 @@ config 4KSTACKS
          on the VM subsystem for higher order allocations. This option
          will also use IRQ stacks to compensate for the reduced stackspace.
 
-config KGDB
+config SH_KGDB
        bool "Include KGDB kernel debugger"
        select FRAME_POINTER
+       select DEBUG_INFO
        help
          Include in-kernel hooks for kgdb, the Linux kernel source level
          debugger.  See <http://kgdb.sourceforge.net/> for more information.
          Unless you are intending to debug the kernel, say N here.
 
 menu "KGDB configuration options"
-       depends on KGDB
+       depends on SH_KGDB
 
 config MORE_COMPILE_OPTIONS
        bool "Add any additional compile options"
@@ -103,22 +105,16 @@ config KGDB_NMI
        bool "Enter KGDB on NMI"
        default n
 
-config KGDB_THREAD
-       bool "Include KGDB thread support"
-       default y
-
 config SH_KGDB_CONSOLE
        bool "Console messages through GDB"
+       depends on !SERIAL_SH_SCI_CONSOLE
+       select SERIAL_CORE_CONSOLE
        default n
 
 config KGDB_SYSRQ
        bool "Allow SysRq 'G' to enter KGDB"
        default y
 
-config KGDB_KERNEL_ASSERTS
-       bool "Include KGDB kernel assertions"
-       default n
-
 comment "Serial port setup"
 
 config KGDB_DEFPORT
@@ -131,7 +127,7 @@ config KGDB_DEFBAUD
 
 choice
        prompt "Parity"
-       depends on KGDB
+       depends on SH_KGDB
        default KGDB_DEFPARITY_N
 
 config KGDB_DEFPARITY_N
@@ -147,7 +143,7 @@ endchoice
 
 choice
        prompt "Data bits"
-       depends on KGDB
+       depends on SH_KGDB
        default KGDB_DEFBITS_8
 
 config KGDB_DEFBITS_8
index bd9b172..7b11224 100644 (file)
@@ -47,7 +47,6 @@ cflags-$(CONFIG_CPU_LITTLE_ENDIAN)    += -ml
 cflags-y       += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
 
 cflags-$(CONFIG_SH_DSP)                        += -Wa,-dsp
-cflags-$(CONFIG_SH_KGDB)               += -g
 
 cflags-$(CONFIG_MORE_COMPILE_OPTIONS)  += \
        $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
@@ -89,7 +88,9 @@ core-$(CONFIG_SH_FPU_EMU)     += arch/sh/math-emu/
 
 # Boards
 machdir-$(CONFIG_SH_SOLUTION_ENGINE)           := se/770x
+machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE)      := se/7722
 machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)      := se/7751
+machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE)      := se/7780
 machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)      := se/7300
 machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)      := se/7343
 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)     := se/73180
@@ -103,7 +104,7 @@ machdir-$(CONFIG_SH_HS7751RVOIP)            := renesas/hs7751rvoip
 machdir-$(CONFIG_SH_RTS7751R2D)                        := renesas/rts7751r2d
 machdir-$(CONFIG_SH_7751_SYSTEMH)              := renesas/systemh
 machdir-$(CONFIG_SH_EDOSK7705)                 := renesas/edosk7705
-machdir-$(CONFIG_SH_R7780RP)                   := renesas/r7780rp
+machdir-$(CONFIG_SH_HIGHLANDER)                        := renesas/r7780rp
 machdir-$(CONFIG_SH_7710VOIPGW)                        := renesas/sh7710voipgw
 machdir-$(CONFIG_SH_SH4202_MICRODEV)           := superh/microdev
 machdir-$(CONFIG_SH_LANDISK)                   := landisk
@@ -111,6 +112,7 @@ machdir-$(CONFIG_SH_TITAN)                  := titan
 machdir-$(CONFIG_SH_SHMIN)                     := shmin
 machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE)      := se/7206
 machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE)      := se/7619
+machdir-$(CONFIG_SH_LBOX_RE2)                  := lboxre2
 machdir-$(CONFIG_SH_UNKNOWN)                   := unknown
 
 incdir-y                       := $(notdir $(machdir-y))
index ff1b7f5..b312427 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for the HP6xx specific parts of the kernel
 #
 
-obj-y                  := setup.o
+obj-y                  := setup.o
 obj-$(CONFIG_PM)       += pm.o pm_wakeup.o
-obj-$(CONFIG_APM)      += hp6xx_apm.o
+obj-$(CONFIG_APM_EMULATION)    += hp6xx_apm.o
index b5a9664..6aeee85 100644 (file)
@@ -2,6 +2,7 @@
  * linux/arch/sh/boards/hp6xx/setup.c
  *
  * Copyright (C) 2002 Andriy Skulysh
+ * Copyright (C) 2007 Kristoffer Ericson <Kristoffer_e1@hotmail.com>
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
@@ -10,6 +11,7 @@
  */
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/hd64461.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #define        SCPCR   0xa4000116
 #define SCPDR  0xa4000136
 
+/* CF Slot */
+static struct resource cf_ide_resources[] = {
+       [0] = {
+               .start = 0x15000000 + 0x1f0,
+               .end   = 0x15000000 + 0x1f0 + 0x08 - 0x01,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = 0x15000000 + 0x1fe,
+               .end   = 0x15000000 + 0x1fe + 0x01,
+               .flags = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start = 93,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_ide_device = {
+       .name           =  "pata_platform",
+       .id             =  -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+};
+
+static struct platform_device *hp6xx_devices[] __initdata = {
+       &cf_ide_device,
+};
+
+static int __init hp6xx_devices_setup(void)
+{
+       return platform_add_devices(hp6xx_devices, ARRAY_SIZE(hp6xx_devices));
+}
+
 static void __init hp6xx_setup(char **cmdline_p)
 {
        u8 v8;
@@ -60,41 +96,12 @@ static void __init hp6xx_setup(char **cmdline_p)
        v |= SCPCR_TS_ENABLE;
        ctrl_outw(v, SCPCR);
 }
+device_initcall(hp6xx_devices_setup);
 
-/*
- * XXX: This is stupid, we should have a generic machine vector for the cchips
- * and just wrap the platform setup code in to this, as it's the only thing
- * that ends up being different.
- */
 struct sh_machine_vector mv_hp6xx __initmv = {
        .mv_name = "hp6xx",
        .mv_setup = hp6xx_setup,
        .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
-
-       .mv_inb = hd64461_inb,
-       .mv_inw = hd64461_inw,
-       .mv_inl = hd64461_inl,
-       .mv_outb = hd64461_outb,
-       .mv_outw = hd64461_outw,
-       .mv_outl = hd64461_outl,
-
-       .mv_inb_p = hd64461_inb_p,
-       .mv_inw_p = hd64461_inw,
-       .mv_inl_p = hd64461_inl,
-       .mv_outb_p = hd64461_outb_p,
-       .mv_outw_p = hd64461_outw,
-       .mv_outl_p = hd64461_outl,
-
-       .mv_insb = hd64461_insb,
-       .mv_insw = hd64461_insw,
-       .mv_insl = hd64461_insl,
-       .mv_outsb = hd64461_outsb,
-       .mv_outsw = hd64461_outsw,
-       .mv_outsl = hd64461_outsl,
-
-       .mv_readw = hd64461_readw,
-       .mv_writew = hd64461_writew,
-
        .mv_irq_demux = hd64461_irq_demux,
 };
 ALIAS_MV(hp6xx)
index 89e4beb..a696b42 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
 #
 
-obj-y   := setup.o io.o irq.o rtc.o landisk_pwb.o
+obj-y   := setup.o irq.o psw.o gio.o
diff --git a/arch/sh/boards/landisk/gio.c b/arch/sh/boards/landisk/gio.c
new file mode 100644 (file)
index 0000000..50d38be
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * arch/sh/boards/landisk/gio.c - driver for landisk
+ *
+ * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
+ * LANDISK and USL-5P Button, LED and GIO driver drive function.
+ *
+ *   Copylight (C) 2006 kogiidena
+ *   Copylight (C) 2002 Atom Create Engineering Co., Ltd. *
+ *
+ * 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/init.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/landisk/gio.h>
+#include <asm/landisk/iodata_landisk.h>
+
+#define DEVCOUNT                4
+#define GIO_MINOR              2       /* GIO minor no. */
+
+static dev_t dev;
+static struct cdev *cdev_p;
+static int openCnt;
+
+static int gio_open(struct inode *inode, struct file *filp)
+{
+       int minor;
+
+       minor = MINOR(inode->i_rdev);
+       if (minor < DEVCOUNT) {
+               if (openCnt > 0) {
+                       return -EALREADY;
+               } else {
+                       openCnt++;
+                       return 0;
+               }
+       }
+       return -ENOENT;
+}
+
+static int gio_close(struct inode *inode, struct file *filp)
+{
+       int minor;
+
+       minor = MINOR(inode->i_rdev);
+       if (minor < DEVCOUNT) {
+               openCnt--;
+       }
+       return 0;
+}
+
+static int gio_ioctl(struct inode *inode, struct file *filp,
+                            unsigned int cmd, unsigned long arg)
+{
+       unsigned int data;
+       static unsigned int addr = 0;
+
+       if (cmd & 0x01) {       /* write */
+               if (copy_from_user(&data, (int *)arg, sizeof(int))) {
+                       return -EFAULT;
+               }
+       }
+
+       switch (cmd) {
+       case GIODRV_IOCSGIOSETADDR:     /* addres set */
+               addr = data;
+               break;
+
+       case GIODRV_IOCSGIODATA1:       /* write byte */
+               ctrl_outb((unsigned char)(0x0ff & data), addr);
+               break;
+
+       case GIODRV_IOCSGIODATA2:       /* write word */
+               if (addr & 0x01) {
+                       return -EFAULT;
+               }
+               ctrl_outw((unsigned short int)(0x0ffff & data), addr);
+               break;
+
+       case GIODRV_IOCSGIODATA4:       /* write long */
+               if (addr & 0x03) {
+                       return -EFAULT;
+               }
+               ctrl_outl(data, addr);
+               break;
+
+       case GIODRV_IOCGGIODATA1:       /* read byte */
+               data = ctrl_inb(addr);
+               break;
+
+       case GIODRV_IOCGGIODATA2:       /* read word */
+               if (addr & 0x01) {
+                       return -EFAULT;
+               }
+               data = ctrl_inw(addr);
+               break;
+
+       case GIODRV_IOCGGIODATA4:       /* read long */
+               if (addr & 0x03) {
+                       return -EFAULT;
+               }
+               data = ctrl_inl(addr);
+               break;
+       default:
+               return -EFAULT;
+               break;
+       }
+
+       if ((cmd & 0x01) == 0) {        /* read */
+               if (copy_to_user((int *)arg, &data, sizeof(int))) {
+                       return -EFAULT;
+               }
+       }
+       return 0;
+}
+
+static struct file_operations gio_fops = {
+       .owner = THIS_MODULE,
+       .open = gio_open,       /* open */
+       .release = gio_close,   /* release */
+       .ioctl = gio_ioctl,     /* ioctl */
+};
+
+static int __init gio_init(void)
+{
+       int error;
+
+       printk(KERN_INFO "gio: driver initialized\n");
+
+       openCnt = 0;
+
+       if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "gio")) < 0) {
+               printk(KERN_ERR
+                      "gio: Couldn't alloc_chrdev_region, error=%d\n",
+                      error);
+               return 1;
+       }
+
+       cdev_p = cdev_alloc();
+       cdev_p->ops = &gio_fops;
+       error = cdev_add(cdev_p, dev, DEVCOUNT);
+       if (error) {
+               printk(KERN_ERR
+                      "gio: Couldn't cdev_add, error=%d\n", error);
+               return 1;
+       }
+
+       return 0;
+}
+
+static void __exit gio_exit(void)
+{
+       cdev_del(cdev_p);
+       unregister_chrdev_region(dev, DEVCOUNT);
+}
+
+module_init(gio_init);
+module_exit(gio_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/sh/boards/landisk/io.c b/arch/sh/boards/landisk/io.c
deleted file mode 100644 (file)
index 92498b4..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * arch/sh/boards/landisk/io.c
- *
- * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
- * Based largely on io_se.c.
- *
- * I/O routine for I-O Data Device, Inc. LANDISK.
- *
- * Initial version only to support LAN access; some
- * placeholder code from io_landisk.c left in with the
- * expectation of later SuperIO and PCMCIA access.
- */
-/*
- * modifed by kogiidena
- * 2005.03.03
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <asm/landisk/iodata_landisk.h>
-#include <asm/addrspace.h>
-#include <asm/io.h>
-
-extern void *area5_io_base;    /* Area 5 I/O Base address */
-extern void *area6_io_base;    /* Area 6 I/O Base address */
-
-static inline unsigned long port2adr(unsigned int port)
-{
-       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-               if (port == 0x3f6)
-                       return ((unsigned long)area5_io_base + 0x2c);
-               else
-                       return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
-                               ((port - 0x1f0) << 1));
-       else if ((0x170 <= port && port < 0x178) || port == 0x376)
-               if (port == 0x376)
-                       return ((unsigned long)area6_io_base + 0x2c);
-               else
-                       return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
-                               ((port - 0x170) << 1));
-       else
-               maybebadio((unsigned long)port);
-
-       return port;
-}
-
-/*
- * General outline: remap really low stuff [eventually] to SuperIO,
- * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
- * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
- * should be way beyond the window, and is used  w/o translation for
- * compatibility.
- */
-u8 landisk_inb(unsigned long port)
-{
-       if (PXSEG(port))
-               return ctrl_inb(port);
-       else if (is_pci_ioaddr(port))
-               return ctrl_inb(pci_ioaddr(port));
-
-       return ctrl_inw(port2adr(port)) & 0xff;
-}
-
-u8 landisk_inb_p(unsigned long port)
-{
-       u8 v;
-
-       if (PXSEG(port))
-               v = ctrl_inb(port);
-       else if (is_pci_ioaddr(port))
-               v = ctrl_inb(pci_ioaddr(port));
-       else
-               v = ctrl_inw(port2adr(port)) & 0xff;
-
-       ctrl_delay();
-
-       return v;
-}
-
-u16 landisk_inw(unsigned long port)
-{
-       if (PXSEG(port))
-               return ctrl_inw(port);
-       else if (is_pci_ioaddr(port))
-               return ctrl_inw(pci_ioaddr(port));
-       else
-               maybebadio(port);
-
-       return 0;
-}
-
-u32 landisk_inl(unsigned long port)
-{
-       if (PXSEG(port))
-               return ctrl_inl(port);
-       else if (is_pci_ioaddr(port))
-               return ctrl_inl(pci_ioaddr(port));
-       else
-               maybebadio(port);
-
-       return 0;
-}
-
-void landisk_outb(u8 value, unsigned long port)
-{
-       if (PXSEG(port))
-               ctrl_outb(value, port);
-       else if (is_pci_ioaddr(port))
-               ctrl_outb(value, pci_ioaddr(port));
-       else
-               ctrl_outw(value, port2adr(port));
-}
-
-void landisk_outb_p(u8 value, unsigned long port)
-{
-       if (PXSEG(port))
-               ctrl_outb(value, port);
-       else if (is_pci_ioaddr(port))
-               ctrl_outb(value, pci_ioaddr(port));
-       else
-               ctrl_outw(value, port2adr(port));
-       ctrl_delay();
-}
-
-void landisk_outw(u16 value, unsigned long port)
-{
-       if (PXSEG(port))
-               ctrl_outw(value, port);
-       else if (is_pci_ioaddr(port))
-               ctrl_outw(value, pci_ioaddr(port));
-       else
-               maybebadio(port);
-}
-
-void landisk_outl(u32 value, unsigned long port)
-{
-       if (PXSEG(port))
-               ctrl_outl(value, port);
-       else if (is_pci_ioaddr(port))
-               ctrl_outl(value, pci_ioaddr(port));
-       else
-               maybebadio(port);
-}
-
-void landisk_insb(unsigned long port, void *dst, unsigned long count)
-{
-        volatile u16 *p;
-        u8 *buf = dst;
-
-        if (PXSEG(port)) {
-                while (count--)
-                        *buf++ = *(volatile u8 *)port;
-       } else if (is_pci_ioaddr(port)) {
-                volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
-
-                while (count--)
-                        *buf++ = *bp;
-       } else {
-                p = (volatile u16 *)port2adr(port);
-                while (count--)
-                        *buf++ = *p & 0xff;
-       }
-}
-
-void landisk_insw(unsigned long port, void *dst, unsigned long count)
-{
-        volatile u16 *p;
-        u16 *buf = dst;
-
-       if (PXSEG(port))
-               p = (volatile u16 *)port;
-       else if (is_pci_ioaddr(port))
-               p = (volatile u16 *)pci_ioaddr(port);
-       else
-               p = (volatile u16 *)port2adr(port);
-       while (count--)
-               *buf++ = *p;
-}
-
-void landisk_insl(unsigned long port, void *dst, unsigned long count)
-{
-        u32 *buf = dst;
-
-       if (is_pci_ioaddr(port)) {
-                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
-
-                while (count--)
-                        *buf++ = *p;
-       } else
-               maybebadio(port);
-}
-
-void landisk_outsb(unsigned long port, const void *src, unsigned long count)
-{
-        volatile u16 *p;
-        const u8 *buf = src;
-
-       if (PXSEG(port))
-                while (count--)
-                        ctrl_outb(*buf++, port);
-       else if (is_pci_ioaddr(port)) {
-                volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
-
-                while (count--)
-                        *bp = *buf++;
-       } else {
-                p = (volatile u16 *)port2adr(port);
-                while (count--)
-                        *p = *buf++;
-       }
-}
-
-void landisk_outsw(unsigned long port, const void *src, unsigned long count)
-{
-        volatile u16 *p;
-        const u16 *buf = src;
-
-       if (PXSEG(port))
-                p = (volatile u16 *)port;
-       else if (is_pci_ioaddr(port))
-                p = (volatile u16 *)pci_ioaddr(port);
-       else
-                p = (volatile u16 *)port2adr(port);
-
-        while (count--)
-                *p = *buf++;
-}
-
-void landisk_outsl(unsigned long port, const void *src, unsigned long count)
-{
-        const u32 *buf = src;
-
-       if (is_pci_ioaddr(port)) {
-                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
-
-                while (count--)
-                        *p = *buf++;
-       } else
-               maybebadio(port);
-}
-
-void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
-{
-        if (PXSEG(port))
-                return (void __iomem *)port;
-        else if (is_pci_ioaddr(port))
-                return (void __iomem *)pci_ioaddr(port);
-
-        return (void __iomem *)port2adr(port);
-}
index 3eba6d0..2586494 100644 (file)
@@ -1,18 +1,16 @@
 /*
  * arch/sh/boards/landisk/irq.c
  *
+ * I-O DATA Device, Inc. LANDISK Support
+ *
+ * Copyright (C) 2005-2007 kogiidena
+ *
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  *
- * I/O routine for I-O Data Device, Inc. LANDISK.
- *
- * Initial version only to support LAN access; some
- * placeholder code from io_landisk.c left in with the
- * expectation of later SuperIO and PCMCIA access.
- */
-/*
- * modified by kogiidena
- * 2005.03.03
+ * 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/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/landisk/iodata_landisk.h>
 
-static void enable_landisk_irq(unsigned int irq);
-static void disable_landisk_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_landisk_irq disable_landisk_irq
-
-static void ack_landisk_irq(unsigned int irq);
-static void end_landisk_irq(unsigned int irq);
-
-static unsigned int startup_landisk_irq(unsigned int irq)
-{
-       enable_landisk_irq(irq);
-       return 0;               /* never anything pending */
-}
-
 static void disable_landisk_irq(unsigned int irq)
 {
-       unsigned char val;
        unsigned char mask = 0xff ^ (0x01 << (irq - 5));
 
-       /* Set the priority in IPR to 0 */
-       val = ctrl_inb(PA_IMASK);
-       val &= mask;
-       ctrl_outb(val, PA_IMASK);
+       ctrl_outb(ctrl_inb(PA_IMASK) & mask, PA_IMASK);
 }
 
 static void enable_landisk_irq(unsigned int irq)
 {
-       unsigned char val;
        unsigned char value = (0x01 << (irq - 5));
 
-       /* Set priority in IPR back to original value */
-       val = ctrl_inb(PA_IMASK);
-       val |= value;
-       ctrl_outb(val, PA_IMASK);
-}
-
-static void ack_landisk_irq(unsigned int irq)
-{
-       disable_landisk_irq(irq);
-}
-
-static void end_landisk_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               enable_landisk_irq(irq);
+       ctrl_outb(ctrl_inb(PA_IMASK) | value, PA_IMASK);
 }
 
-static struct hw_interrupt_type landisk_irq_type = {
-       .typename = "LANDISK IRQ",
-       .startup = startup_landisk_irq,
-       .shutdown = shutdown_landisk_irq,
-       .enable = enable_landisk_irq,
-       .disable = disable_landisk_irq,
-       .ack = ack_landisk_irq,
-       .end = end_landisk_irq
+static struct irq_chip landisk_irq_chip __read_mostly = {
+       .name           = "LANDISK",
+       .mask           = disable_landisk_irq,
+       .unmask         = enable_landisk_irq,
+       .mask_ack       = disable_landisk_irq,
 };
 
-static void make_landisk_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &landisk_irq_type;
-       disable_landisk_irq(irq);
-}
-
 /*
  * Initialize IRQ setting
  */
@@ -92,6 +46,11 @@ void __init init_landisk_IRQ(void)
 {
        int i;
 
-       for (i = 5; i < 14; i++)
-               make_landisk_irq(i);
+       for (i = 5; i < 14; i++) {
+               disable_irq_nosync(i);
+               set_irq_chip_and_handler_name(i, &landisk_irq_chip,
+                                             handle_level_irq, "level");
+               enable_landisk_irq(i);
+       }
+       ctrl_outb(0x00, PA_PWRINT_CLR);
 }
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
deleted file mode 100644 (file)
index 47a63c6..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * arch/sh/boards/landisk/landisk_pwb.c -- driver for the Power control switch.
- *
- * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
- *
- * 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.
- *
- * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
- *
- * LED control drive function added by kogiidena
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/major.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/landisk/iodata_landisk.h>
-
-#define SHUTDOWN_BTN_MINOR     1       /* Shutdown button device minor no. */
-#define LED_MINOR             21       /* LED minor no. */
-#define BTN_MINOR             22       /* BUTTON minor no. */
-#define GIO_MINOR             40       /* GIO minor no. */
-
-static int openCnt;
-static int openCntLED;
-static int openCntGio;
-static int openCntBtn;
-static int landisk_btn;
-static int landisk_btnctrlpid;
-/*
- * Functions prototypes
- */
-
-static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-                    unsigned long arg);
-
-static int swdrv_open(struct inode *inode, struct file *filp)
-{
-       int minor;
-
-       minor = MINOR(inode->i_rdev);
-       filp->private_data = (void *)minor;
-
-       if (minor == SHUTDOWN_BTN_MINOR) {
-               if (openCnt > 0) {
-                       return -EALREADY;
-               } else {
-                       openCnt++;
-                       return 0;
-               }
-       } else if (minor == LED_MINOR) {
-               if (openCntLED > 0) {
-                       return -EALREADY;
-               } else {
-                       openCntLED++;
-                       return 0;
-               }
-       } else if (minor == BTN_MINOR) {
-               if (openCntBtn > 0) {
-                       return -EALREADY;
-               } else {
-                       openCntBtn++;
-                       return 0;
-               }
-       } else if (minor == GIO_MINOR) {
-               if (openCntGio > 0) {
-                       return -EALREADY;
-               } else {
-                       openCntGio++;
-                       return 0;
-               }
-       }
-       return -ENOENT;
-
-}
-
-static int swdrv_close(struct inode *inode, struct file *filp)
-{
-       int minor;
-
-       minor = MINOR(inode->i_rdev);
-       if (minor == SHUTDOWN_BTN_MINOR) {
-               openCnt--;
-       } else if (minor == LED_MINOR) {
-               openCntLED--;
-       } else if (minor == BTN_MINOR) {
-               openCntBtn--;
-       } else if (minor == GIO_MINOR) {
-               openCntGio--;
-       }
-       return 0;
-}
-
-static int swdrv_read(struct file *filp, char *buff, size_t count,
-                     loff_t * ppos)
-{
-       int minor;
-       minor = (int)(filp->private_data);
-
-       if (!access_ok(VERIFY_WRITE, (void *)buff, count))
-               return -EFAULT;
-
-       if (minor == SHUTDOWN_BTN_MINOR) {
-               if (landisk_btn & 0x10) {
-                       put_user(1, buff);
-                       return 1;
-               } else {
-                       return 0;
-               }
-       }
-       return 0;
-}
-
-static int swdrv_write(struct file *filp, const char *buff, size_t count,
-                      loff_t * ppos)
-{
-       int minor;
-       minor = (int)(filp->private_data);
-
-       if (minor == SHUTDOWN_BTN_MINOR) {
-               return count;
-       }
-       return count;
-}
-
-static irqreturn_t sw_interrupt(int irq, void *dev_id)
-{
-       landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
-       disable_irq(IRQ_BUTTON);
-       disable_irq(IRQ_POWER);
-       ctrl_outb(0x00, PA_PWRINT_CLR);
-
-       if (landisk_btnctrlpid != 0) {
-               kill_proc(landisk_btnctrlpid, SIGUSR1, 1);
-               landisk_btnctrlpid = 0;
-       }
-
-       return IRQ_HANDLED;
-}
-
-static const struct file_operations swdrv_fops = {
-       .read = swdrv_read,     /* read */
-       .write = swdrv_write,   /* write */
-       .open = swdrv_open,     /* open */
-       .release = swdrv_close, /* release */
-       .ioctl = gio_ioctl,     /* ioctl */
-
-};
-
-static char banner[] __initdata =
-    KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
-
-int __init swdrv_init(void)
-{
-       int error;
-
-       printk("%s", banner);
-
-       openCnt = 0;
-       openCntLED = 0;
-       openCntBtn = 0;
-       openCntGio = 0;
-       landisk_btn = 0;
-       landisk_btnctrlpid = 0;
-
-       if ((error = register_chrdev(SHUTDOWN_BTN_MAJOR, "swdrv", &swdrv_fops))) {
-               printk(KERN_ERR
-                      "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
-                      error);
-               return 1;
-       }
-
-       if (request_irq(IRQ_POWER, sw_interrupt, 0, "SHUTDOWNSWITCH", NULL)) {
-               printk(KERN_ERR "Unable to get IRQ 11.\n");
-               return 1;
-       }
-       if (request_irq(IRQ_BUTTON, sw_interrupt, 0, "USL-5P BUTTON", NULL)) {
-               printk(KERN_ERR "Unable to get IRQ 12.\n");
-               return 1;
-       }
-       ctrl_outb(0x00, PA_PWRINT_CLR);
-
-       return 0;
-}
-
-module_init(swdrv_init);
-
-/*
- * gio driver
- *
- */
-
-#include <asm/landisk/gio.h>
-
-static int gio_ioctl(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
-{
-       int minor;
-       unsigned int data, mask;
-       static unsigned int addr = 0;
-
-       minor = (int)(filp->private_data);
-
-       /* access control */
-       if (minor == GIO_MINOR) {
-               ;
-       } else if (minor == LED_MINOR) {
-               if (((cmd & 0x0ff) >= 9) && ((cmd & 0x0ff) < 20)) {
-                       ;
-               } else {
-                       return -EINVAL;
-               }
-       } else if (minor == BTN_MINOR) {
-               if (((cmd & 0x0ff) >= 20) && ((cmd & 0x0ff) < 30)) {
-                       ;
-               } else {
-                       return -EINVAL;
-               }
-       } else {
-               return -EINVAL;
-       }
-
-       if (cmd & 0x01) {       /* write */
-               if (copy_from_user(&data, (int *)arg, sizeof(int))) {
-                       return -EFAULT;
-               }
-       }
-
-       switch (cmd) {
-       case GIODRV_IOCSGIOSETADDR:     /* addres set */
-               addr = data;
-               break;
-
-       case GIODRV_IOCSGIODATA1:       /* write byte */
-               ctrl_outb((unsigned char)(0x0ff & data), addr);
-               break;
-
-       case GIODRV_IOCSGIODATA2:       /* write word */
-               if (addr & 0x01) {
-                       return -EFAULT;
-               }
-               ctrl_outw((unsigned short int)(0x0ffff & data), addr);
-               break;
-
-       case GIODRV_IOCSGIODATA4:       /* write long */
-               if (addr & 0x03) {
-                       return -EFAULT;
-               }
-               ctrl_outl(data, addr);
-               break;
-
-       case GIODRV_IOCGGIODATA1:       /* read byte */
-               data = ctrl_inb(addr);
-               break;
-
-       case GIODRV_IOCGGIODATA2:       /* read word */
-               if (addr & 0x01) {
-                       return -EFAULT;
-               }
-               data = ctrl_inw(addr);
-               break;
-
-       case GIODRV_IOCGGIODATA4:       /* read long */
-               if (addr & 0x03) {
-                       return -EFAULT;
-               }
-               data = ctrl_inl(addr);
-               break;
-       case GIODRV_IOCSGIO_LED:        /* write */
-               mask = ((data & 0x00ffffff) << 8)
-                   | ((data & 0x0000ffff) << 16)
-                   | ((data & 0x000000ff) << 24);
-               landisk_ledparam = data & (~mask);
-               if (landisk_arch == 0) {        /* arch == landisk */
-                       landisk_ledparam &= 0x03030303;
-                       mask = (~(landisk_ledparam >> 22)) & 0x000c;
-                       landisk_ledparam |= mask;
-               } else {                        /* arch == usl-5p */
-                       mask = (landisk_ledparam >> 24) & 0x0001;
-                       landisk_ledparam |= mask;
-                       landisk_ledparam &= 0x007f7f7f;
-               }
-               landisk_ledparam |= 0x80;
-               break;
-       case GIODRV_IOCGGIO_LED:        /* read */
-               data = landisk_ledparam;
-               if (landisk_arch == 0) {        /* arch == landisk */
-                       data &= 0x03030303;
-               } else {                        /* arch == usl-5p */
-                       ;
-               }
-               data &= (~0x080);
-               break;
-       case GIODRV_IOCSGIO_BUZZER:     /* write */
-               landisk_buzzerparam = data;
-               landisk_ledparam |= 0x80;
-               break;
-       case GIODRV_IOCGGIO_LANDISK:    /* read */
-               data = landisk_arch & 0x01;
-               break;
-       case GIODRV_IOCGGIO_BTN:        /* read */
-               data = (0x0ff & ctrl_inb(PA_PWRINT_CLR));
-               data <<= 8;
-               data |= (0x0ff & ctrl_inb(PA_IMASK));
-               data <<= 8;
-               data |= (0x0ff & landisk_btn);
-               data <<= 8;
-               data |= (0x0ff & (~ctrl_inb(PA_STATUS)));
-               break;
-       case GIODRV_IOCSGIO_BTNPID:     /* write */
-               landisk_btnctrlpid = data;
-               landisk_btn = 0;
-               if (irq_desc[IRQ_BUTTON].depth) {
-                       enable_irq(IRQ_BUTTON);
-               }
-               if (irq_desc[IRQ_POWER].depth) {
-                       enable_irq(IRQ_POWER);
-               }
-               break;
-       case GIODRV_IOCGGIO_BTNPID:     /* read */
-               data = landisk_btnctrlpid;
-               break;
-       default:
-               return -EFAULT;
-               break;
-       }
-
-       if ((cmd & 0x01) == 0) {        /* read */
-               if (copy_to_user((int *)arg, &data, sizeof(int))) {
-                       return -EFAULT;
-               }
-       }
-       return 0;
-}
diff --git a/arch/sh/boards/landisk/psw.c b/arch/sh/boards/landisk/psw.c
new file mode 100644 (file)
index 0000000..5a9b70b
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * arch/sh/boards/landisk/psw.c
+ *
+ * push switch support for LANDISK and USL-5P
+ *
+ * Copyright (C) 2006-2007  Paul Mundt
+ * Copyright (C) 2007  kogiidena
+ *
+ * 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/io.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/push-switch.h>
+
+static irqreturn_t psw_irq_handler(int irq, void *arg)
+{
+       struct platform_device *pdev = arg;
+       struct push_switch *psw = platform_get_drvdata(pdev);
+       struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
+       unsigned int sw_value;
+       int ret = 0;
+
+       sw_value = (0x0ff & (~ctrl_inb(PA_STATUS)));
+
+       /* Nothing to do if there's no state change */
+       if (psw->state) {
+               ret = 1;
+               goto out;
+       }
+
+       /* Figure out who raised it */
+       if (sw_value & (1 << psw_info->bit)) {
+               psw->state = 1;
+               mod_timer(&psw->debounce, jiffies + 50);
+               ret = 1;
+       }
+
+out:
+       /* Clear the switch IRQs */
+       ctrl_outb(0x00, PA_PWRINT_CLR);
+
+       return IRQ_RETVAL(ret);
+}
+
+static struct resource psw_power_resources[] = {
+       [0] = {
+               .start = IRQ_POWER,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource psw_usl5p_resources[] = {
+       [0] = {
+               .start = IRQ_BUTTON,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct push_switch_platform_info psw_power_platform_data = {
+       .name           = "psw_power",
+       .bit            = 4,
+       .irq_flags      = IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct push_switch_platform_info psw1_platform_data = {
+       .name           = "psw1",
+       .bit            = 0,
+       .irq_flags      = IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct push_switch_platform_info psw2_platform_data = {
+       .name           = "psw2",
+       .bit            = 2,
+       .irq_flags      = IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct push_switch_platform_info psw3_platform_data = {
+       .name           = "psw3",
+       .bit            = 1,
+       .irq_flags      = IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct platform_device psw_power_switch_device = {
+       .name           = "push-switch",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(psw_power_resources),
+       .resource       = psw_power_resources,
+       .dev            = {
+               .platform_data = &psw_power_platform_data,
+       },
+};
+
+static struct platform_device psw1_switch_device = {
+       .name           = "push-switch",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(psw_usl5p_resources),
+       .resource       = psw_usl5p_resources,
+       .dev            = {
+               .platform_data = &psw1_platform_data,
+       },
+};
+
+static struct platform_device psw2_switch_device = {
+       .name           = "push-switch",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(psw_usl5p_resources),
+       .resource       = psw_usl5p_resources,
+       .dev            = {
+               .platform_data = &psw2_platform_data,
+       },
+};
+
+static struct platform_device psw3_switch_device = {
+       .name           = "push-switch",
+       .id             = 3,
+       .num_resources  = ARRAY_SIZE(psw_usl5p_resources),
+       .resource       = psw_usl5p_resources,
+       .dev = {
+               .platform_data = &psw3_platform_data,
+       },
+};
+
+static struct platform_device *psw_devices[] = {
+       &psw_power_switch_device,
+       &psw1_switch_device,
+       &psw2_switch_device,
+       &psw3_switch_device,
+};
+
+static int __init psw_init(void)
+{
+       return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
+}
+module_init(psw_init);
diff --git a/arch/sh/boards/landisk/rtc.c b/arch/sh/boards/landisk/rtc.c
deleted file mode 100644 (file)
index 0a9a2a2..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * arch/sh/boards/landisk/rtc.c --  RTC support
- *
- *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- */
-/*
- * modifed by kogiidena
- * 2005.09.16
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/bcd.h>
-#include <asm/rtc.h>
-
-extern spinlock_t rtc_lock;
-
-extern void
-rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
-                     unsigned int BCD_day, unsigned int BCD_hr,
-                     unsigned int BCD_min, unsigned int BCD_sec);
-
-extern unsigned long
-rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
-                     unsigned int *BCD_day, unsigned int *BCD_hr,
-                     unsigned int *BCD_min, unsigned int *BCD_sec);
-
-void landisk_rtc_gettimeofday(struct timespec *tv)
-{
-       unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       tv->tv_sec = rs5c313_get_cmos_time
-           (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
-       tv->tv_nsec = 0;
-       spin_unlock_irqrestore(&rtc_lock, flags);
-}
-
-int landisk_rtc_settimeofday(const time_t secs)
-{
-       int retval = 0;
-       int real_seconds, real_minutes, cmos_minutes;
-       unsigned long flags;
-       unsigned long nowtime = secs;
-       unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-
-       rs5c313_get_cmos_time
-         (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
-       cmos_minutes = BCD_min;
-       BCD_TO_BIN(cmos_minutes);
-
-       /*
-        * since we're only adjusting minutes and seconds,
-        * don't interfere with hour overflow. This avoids
-        * messing with unknown time zones but requires your
-        * RTC not to be off by more than 15 minutes
-        */
-       real_seconds = nowtime % 60;
-       real_minutes = nowtime / 60;
-       if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
-               real_minutes += 30;     /* correct for half hour time zone */
-       real_minutes %= 60;
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               BIN_TO_BCD(real_seconds);
-               BIN_TO_BCD(real_minutes);
-               rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
-                                     real_minutes, real_seconds);
-       } else {
-               printk(KERN_WARNING
-                      "set_rtc_time: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
-       }
-
-       spin_unlock_irqrestore(&rtc_lock, flags);
-       return retval;
-}
-
-void landisk_time_init(void)
-{
-       rtc_sh_get_time = landisk_rtc_gettimeofday;
-       rtc_sh_set_time = landisk_rtc_settimeofday;
-}
index 122d699..a83a5d9 100644 (file)
 /*
  * arch/sh/boards/landisk/setup.c
  *
- * Copyright (C) 2000 Kazumoto Kojima
- * Copyright (C) 2002 Paul Mundt
- *
  * I-O DATA Device, Inc. LANDISK Support.
  *
- * Modified for LANDISK by
- * Atom Create Engineering Co., Ltd. 2002.
- *
- * modifed by kogiidena
- * 2005.09.16
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2002 Paul Mundt
+ * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2005-2007 kogiidena
  *
  * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/pata_platform.h>
 #include <linux/pm.h>
 #include <linux/mm.h>
 #include <asm/machvec.h>
-#include <asm/rtc.h>
 #include <asm/landisk/iodata_landisk.h>
 #include <asm/io.h>
 
-void landisk_time_init(void);
 void init_landisk_IRQ(void);
 
-int landisk_ledparam;
-int landisk_buzzerparam;
-int landisk_arch;
-
-/* cycle the led's in the clasic knightrider/sun pattern */
-static void heartbeat_landisk(void)
-{
-       static unsigned int cnt = 0, blink = 0x00, period = 25;
-        volatile u8 *p = (volatile u8 *)PA_LED;
-       char data;
-
-        if ((landisk_ledparam & 0x080) == 0)
-               return;
-
-       cnt += 1;
-
-        if (cnt < period)
-               return;
-
-       cnt = 0;
-       blink++;
-
-       data = (blink & 0x01) ? (landisk_ledparam >> 16) : 0;
-       data |= (blink & 0x02) ? (landisk_ledparam >> 8) : 0;
-       data |= landisk_ledparam;
-
-       /* buzzer */
-       if (landisk_buzzerparam & 0x1) {
-               data |= 0x80;
-       } else {
-               data &= 0x7f;
-       }
-       *p = data;
-
-        if (((landisk_ledparam & 0x007f7f00) == 0) &&
-             (landisk_buzzerparam == 0))
-               landisk_ledparam &= (~0x0080);
-
-       landisk_buzzerparam >>= 1;
-}
-
 static void landisk_power_off(void)
 {
         ctrl_outb(0x01, PA_SHUTDOWN);
 }
 
-static void check_usl5p(void)
-{
-        volatile u8 *p = (volatile u8 *)PA_LED;
-        u8 tmp1, tmp2;
+static struct resource cf_ide_resources[3];
 
-        tmp1 = *p;
-        *p = 0x40;
-        tmp2 = *p;
-        *p = tmp1;
+static struct pata_platform_info pata_info = {
+       .ioport_shift   = 1,
+};
 
-        landisk_arch = (tmp2 == 0x40);
-        if (landisk_arch == 1) {
-                /* arch == usl-5p */
-                landisk_ledparam = 0x00000380;
-                landisk_ledparam |= (tmp1 & 0x07c);
-        } else {
-                /* arch == landisk */
-                landisk_ledparam = 0x02000180;
-                landisk_ledparam |= 0x04;
-        }
-}
+static struct platform_device cf_ide_device = {
+       .name           = "pata_platform",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+       .dev            = {
+               .platform_data = &pata_info,
+       },
+};
 
-void *area5_io_base;
-void *area6_io_base;
+static struct platform_device *landisk_devices[] __initdata = {
+       &cf_ide_device,
+};
 
-static int __init landisk_cf_init(void)
+static int __init landisk_devices_setup(void)
 {
        pgprot_t prot;
-       unsigned long paddrbase, psize;
+       unsigned long paddrbase;
+       void *cf_ide_base;
 
        /* open I/O area window */
        paddrbase = virt_to_phys((void *)PA_AREA5_IO);
-       psize = PAGE_SIZE;
        prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
-       area5_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
-       if (!area5_io_base) {
+       cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
+       if (!cf_ide_base) {
                printk("allocate_cf_area : can't open CF I/O window!\n");
                return -ENOMEM;
        }
 
-       paddrbase = virt_to_phys((void *)PA_AREA6_IO);
-       psize = PAGE_SIZE;
-       prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
-       area6_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
-       if (!area6_io_base) {
-               printk("allocate_cf_area : can't open HDD I/O window!\n");
-               return -ENOMEM;
-       }
-
-       printk(KERN_INFO "Allocate Area5/6 success.\n");
-
-       /* XXX : do we need attribute and common-memory area also? */
-
-       return 0;
+       /* IDE cmd address : 0x1f0-0x1f7 and 0x3f6 */
+       cf_ide_resources[0].start = (unsigned long)cf_ide_base + 0x40;
+       cf_ide_resources[0].end   = (unsigned long)cf_ide_base + 0x40 + 0x0f;
+       cf_ide_resources[0].flags = IORESOURCE_IO;
+       cf_ide_resources[1].start = (unsigned long)cf_ide_base + 0x2c;
+       cf_ide_resources[1].end   = (unsigned long)cf_ide_base + 0x2c + 0x03;
+       cf_ide_resources[1].flags = IORESOURCE_IO;
+       cf_ide_resources[2].start = IRQ_FATA;
+       cf_ide_resources[2].flags = IORESOURCE_IRQ;
+
+       return platform_add_devices(landisk_devices,
+                                   ARRAY_SIZE(landisk_devices));
 }
 
+__initcall(landisk_devices_setup);
+
 static void __init landisk_setup(char **cmdline_p)
 {
-       device_initcall(landisk_cf_init);
-
-       landisk_buzzerparam = 0;
-       check_usl5p();
+        /* LED ON */
+       ctrl_outb(ctrl_inb(PA_LED) | 0x03, PA_LED);
 
        printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
-
-       board_time_init = landisk_time_init;
        pm_power_off = landisk_power_off;
 }
 
@@ -148,29 +94,6 @@ static void __init landisk_setup(char **cmdline_p)
 struct sh_machine_vector mv_landisk __initmv = {
        .mv_name = "LANDISK",
        .mv_setup = landisk_setup,
-       .mv_nr_irqs = 72,
-       .mv_inb = landisk_inb,
-       .mv_inw = landisk_inw,
-       .mv_inl = landisk_inl,
-       .mv_outb = landisk_outb,
-       .mv_outw = landisk_outw,
-       .mv_outl = landisk_outl,
-       .mv_inb_p = landisk_inb_p,
-       .mv_inw_p = landisk_inw,
-       .mv_inl_p = landisk_inl,
-       .mv_outb_p = landisk_outb_p,
-       .mv_outw_p = landisk_outw,
-       .mv_outl_p = landisk_outl,
-       .mv_insb = landisk_insb,
-       .mv_insw = landisk_insw,
-       .mv_insl = landisk_insl,
-       .mv_outsb = landisk_outsb,
-       .mv_outsw = landisk_outsw,
-       .mv_outsl = landisk_outsl,
-       .mv_ioport_map = landisk_ioport_map,
        .mv_init_irq = init_landisk_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat = heartbeat_landisk,
-#endif
 };
 ALIAS_MV(landisk)
diff --git a/arch/sh/boards/lboxre2/Makefile b/arch/sh/boards/lboxre2/Makefile
new file mode 100644 (file)
index 0000000..e9ed140
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the L-BOX RE2 specific parts of the kernel
+# Copyright (c) 2007 Nobuhiro Iwamatsu
+
+obj-y   := setup.o irq.o
diff --git a/arch/sh/boards/lboxre2/irq.c b/arch/sh/boards/lboxre2/irq.c
new file mode 100644 (file)
index 0000000..5a1c3bb
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/sh/boards/lboxre2/irq.c
+ *
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ * NTT COMWARE L-BOX RE2 Support.
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/lboxre2.h>
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_lboxre2_IRQ(void)
+{
+       make_imask_irq(IRQ_CF1);
+       make_imask_irq(IRQ_CF0);
+       make_imask_irq(IRQ_INTD);
+       make_imask_irq(IRQ_ETH1);
+       make_imask_irq(IRQ_ETH0);
+       make_imask_irq(IRQ_INTA);
+}
diff --git a/arch/sh/boards/lboxre2/setup.c b/arch/sh/boards/lboxre2/setup.c
new file mode 100644 (file)
index 0000000..4e20f7c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * linux/arch/sh/boards/lbox/setup.c
+ *
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ * NTT COMWARE L-BOX RE2 Support
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/pata_platform.h>
+#include <asm/machvec.h>
+#include <asm/addrspace.h>
+#include <asm/lboxre2.h>
+#include <asm/io.h>
+
+static struct resource cf_ide_resources[] = {
+       [0] = {
+               .start  = 0x1f0,
+               .end    = 0x1f0 + 8 ,
+               .flags  = IORESOURCE_IO,
+       },
+       [1] = {
+               .start  = 0x1f0 + 0x206,
+               .end    = 0x1f0 +8 + 0x206 + 8,
+               .flags  = IORESOURCE_IO,
+       },
+       [2] = {
+               .start  = IRQ_CF0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_ide_device  = {
+       .name           = "pata_platform",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+};
+
+static struct platform_device *lboxre2_devices[] __initdata = {
+       &cf_ide_device,
+};
+
+static int __init lboxre2_devices_setup(void)
+{
+       u32 cf0_io_base;        /* Boot CF base address */
+       pgprot_t prot;
+       unsigned long paddrbase, psize;
+
+       /* open I/O area window */
+       paddrbase = virt_to_phys((void*)PA_AREA5_IO);
+       psize = PAGE_SIZE;
+       prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16);
+       cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot.pgprot);
+       if (!cf0_io_base) {
+               printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ );
+               return -ENOMEM;
+       }
+
+       cf_ide_resources[0].start += cf0_io_base ;
+       cf_ide_resources[0].end   += cf0_io_base ;
+       cf_ide_resources[1].start += cf0_io_base ;
+       cf_ide_resources[1].end   += cf0_io_base ;
+
+       return platform_add_devices(lboxre2_devices,
+                       ARRAY_SIZE(lboxre2_devices));
+
+}
+device_initcall(lboxre2_devices_setup);
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_lboxre2 __initmv = {
+       .mv_name                = "L-BOX RE2",
+       .mv_nr_irqs             = 72,
+       .mv_init_irq            = init_lboxre2_IRQ,
+};
+ALIAS_MV(lboxre2)
index c26d981..9fb1164 100644 (file)
@@ -1,14 +1,24 @@
-if SH_R7780RP
+if SH_HIGHLANDER
 
-menu "R7780RP options"
+choice
+       prompt "Highlander options"
+       default SH_R7780MP
+
+config SH_R7780RP
+       bool "R7780RP-1 board support"
+       select CPU_SUBTYPE_SH7780
 
 config SH_R7780MP
        bool "R7780MP board support"
-       default y
+       select CPU_SUBTYPE_SH7780
        help
          Selecting this option will enable support for the mass-production
          version of the R7780RP. If in doubt, say Y.
 
-endmenu
+config SH_R7785RP
+       bool "R7785RP board support"
+       select CPU_SUBTYPE_SH7785
+
+endchoice
 
 endif
index ed5f5a9..609e5d5 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for the R7780RP-1 specific parts of the kernel
 #
-
-obj-y   := setup.o irq.o
-
+irqinit-y                      := irq-r7780rp.o
+irqinit-$(CONFIG_SH_R7785RP)   := irq-r7785rp.o
 obj-$(CONFIG_PUSH_SWITCH)      += psw.o
+obj-y                          := setup.o irq.o $(irqinit-y)
diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c
new file mode 100644 (file)
index 0000000..f5f3587
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2006  Paul Mundt
+ *
+ * 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/init.h>
+#include <asm/io.h>
+#include <asm/r7780rp.h>
+
+void __init highlander_init_irq(void)
+{
+       int i;
+
+       for (i = 0; i < 15; i++)
+               make_r7780rp_irq(i);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c b/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c
new file mode 100644 (file)
index 0000000..dd6ec4c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2006  Paul Mundt
+ *
+ * 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/init.h>
+#include <asm/io.h>
+#include <asm/r7780rp.h>
+
+void __init highlander_init_irq(void)
+{
+       ctrl_outw(0x0000, PA_IRLSSR1);  /* FPGA IRLSSR1(CF_CD clear) */
+
+       /* Setup the FPGA IRL */
+       ctrl_outw(0x0000, PA_IRLPRA);   /* FPGA IRLA */
+       ctrl_outw(0xe598, PA_IRLPRB);   /* FPGA IRLB */
+       ctrl_outw(0x7060, PA_IRLPRC);   /* FPGA IRLC */
+       ctrl_outw(0x0000, PA_IRLPRD);   /* FPGA IRLD */
+       ctrl_outw(0x4321, PA_IRLPRE);   /* FPGA IRLE */
+       ctrl_outw(0x0000, PA_IRLPRF);   /* FPGA IRLF */
+
+       make_r7780rp_irq(1);    /* CF card */
+       make_r7780rp_irq(10);   /* On-board ethernet */
+}
index cc381e1..e0b8eb5 100644 (file)
 #include <linux/io.h>
 #include <asm/r7780rp.h>
 
-#ifdef CONFIG_SH_R7780MP
-static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
-#else
+#ifdef CONFIG_SH_R7780RP
 static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0};
+#elif defined(CONFIG_SH_R7780MP)
+static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
+#elif defined(CONFIG_SH_R7785RP)
+static int mask_pos[] = {2, 11, 2, 2, 2, 2, 9, 8, 7, 5, 10, 2, 2, 2, 2, 2};
 #endif
 
 static void enable_r7780rp_irq(unsigned int irq)
@@ -40,17 +42,10 @@ static struct irq_chip r7780rp_irq_chip __read_mostly = {
        .mask_ack       = disable_r7780rp_irq,
 };
 
-/*
- * Initialize IRQ setting
- */
-void __init init_r7780rp_IRQ(void)
+void make_r7780rp_irq(unsigned int irq)
 {
-       int i;
-
-       for (i = 0; i < 15; i++) {
-               disable_irq_nosync(i);
-               set_irq_chip_and_handler_name(i, &r7780rp_irq_chip,
-                                             handle_level_irq, "level");
-               enable_r7780rp_irq(i);
-       }
+       disable_irq_nosync(irq);
+       set_irq_chip_and_handler_name(irq, &r7780rp_irq_chip,
+                                     handle_level_irq, "level");
+       enable_r7780rp_irq(irq);
 }
index 2faba66..0727ef9 100644 (file)
@@ -1,10 +1,13 @@
 /*
  * arch/sh/boards/renesas/r7780rp/setup.c
  *
+ * Renesas Solutions Highlander Support.
+ *
  * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
  * Copyright (C) 2005 - 2007 Paul Mundt
  *
- * Renesas Solutions Highlander R7780RP-1 Support.
+ * This contains support for the R7780RP-1, R7780MP, and R7785RP
+ * Highlander modules.
  *
  * 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
 #include <asm/clock.h>
 #include <asm/io.h>
 
-extern void init_r7780rp_IRQ(void);
-
-static struct resource m66596_usb_host_resources[] = {
-       [0] = {
-               .start  = 0xa4800000,
-               .end    = 0xa4ffffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = 6,            /* irq number */
-               .end    = 6,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device m66596_usb_host_device = {
-       .name           = "m66596-hcd",
-       .id             = 0,
-       .dev = {
-               .dma_mask               = NULL,         /* don't use dma */
-               .coherent_dma_mask      = 0xffffffff,
-       },
-       .num_resources  = ARRAY_SIZE(m66596_usb_host_resources),
-       .resource       = m66596_usb_host_resources,
-};
-
 static struct resource cf_ide_resources[] = {
        [0] = {
                .start  = PA_AREA5_IO + 0x1000,
@@ -56,10 +33,10 @@ static struct resource cf_ide_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-#ifdef CONFIG_SH_R7780MP
-               .start  = 1,
-#else
+#ifdef CONFIG_SH_R7780RP
                .start  = 4,
+#else
+               .start  = 1,
 #endif
                .flags  = IORESOURCE_IRQ,
        },
@@ -92,15 +69,18 @@ static struct resource heartbeat_resources[] = {
 static struct platform_device heartbeat_device = {
        .name           = "heartbeat",
        .id             = -1,
+
+       /* R7785RP has a slightly more sensible FPGA.. */
+#ifndef CONFIG_SH_R7785RP
        .dev    = {
                .platform_data  = heartbeat_bit_pos,
        },
+#endif
        .num_resources  = ARRAY_SIZE(heartbeat_resources),
        .resource       = heartbeat_resources,
 };
 
 static struct platform_device *r7780rp_devices[] __initdata = {
-       &m66596_usb_host_device,
        &cf_ide_device,
        &heartbeat_device,
 };
@@ -110,18 +90,19 @@ static int __init r7780rp_devices_setup(void)
        return platform_add_devices(r7780rp_devices,
                                    ARRAY_SIZE(r7780rp_devices));
 }
+device_initcall(r7780rp_devices_setup);
 
 /*
  * Platform specific clocks
  */
 static void ivdr_clk_enable(struct clk *clk)
 {
-       ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << 8), PA_IVDRCTL);
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << IVDR_CK_ON), PA_IVDRCTL);
 }
 
 static void ivdr_clk_disable(struct clk *clk)
 {
-       ctrl_outw(ctrl_inw(PA_IVDRCTL) & ~(1 << 8), PA_IVDRCTL);
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) & ~(1 << IVDR_CK_ON), PA_IVDRCTL);
 }
 
 static struct clk_ops ivdr_clk_ops = {
@@ -140,22 +121,22 @@ static struct clk *r7780rp_clocks[] = {
 
 static void r7780rp_power_off(void)
 {
-#ifdef CONFIG_SH_R7780MP
-       ctrl_outw(0x0001, PA_POFF);
-#endif
+       if (mach_is_r7780mp() || mach_is_r7785rp())
+               ctrl_outw(0x0001, PA_POFF);
 }
 
 /*
  * Initialize the board
  */
-static void __init r7780rp_setup(char **cmdline_p)
+static void __init highlander_setup(char **cmdline_p)
 {
        u16 ver = ctrl_inw(PA_VERREG);
        int i;
 
-       device_initcall(r7780rp_devices_setup);
-
-       printk(KERN_INFO "Renesas Solutions Highlander R7780RP-1 support.\n");
+       printk(KERN_INFO "Renesas Solutions Highlander %s support.\n",
+                        mach_is_r7780rp() ? "R7780RP-1" :
+                        mach_is_r7780mp() ? "R7780MP"   :
+                                            "R7785RP");
 
        printk(KERN_INFO "Board version: %d (revision %d), "
                         "FPGA version: %d (revision %d)\n",
@@ -173,9 +154,10 @@ static void __init r7780rp_setup(char **cmdline_p)
        }
 
        ctrl_outw(0x0000, PA_OBLED);    /* Clear LED. */
-#ifndef CONFIG_SH_R7780MP
-       ctrl_outw(0x0001, PA_SDPOW);    /* SD Power ON */
-#endif
+
+       if (mach_is_r7780rp())
+               ctrl_outw(0x0001, PA_SDPOW);    /* SD Power ON */
+
        ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);     /* Si13112 */
 
        pm_power_off = r7780rp_power_off;
@@ -184,10 +166,10 @@ static void __init r7780rp_setup(char **cmdline_p)
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_r7780rp __initmv = {
-       .mv_name                = "Highlander R7780RP-1",
-       .mv_setup               = r7780rp_setup,
+struct sh_machine_vector mv_highlander __initmv = {
+       .mv_name                = "Highlander",
        .mv_nr_irqs             = 109,
-       .mv_init_irq            = init_r7780rp_IRQ,
+       .mv_setup               = highlander_setup,
+       .mv_init_irq            = highlander_init_irq,
 };
-ALIAS_MV(r7780rp)
+ALIAS_MV(highlander)
index 9941949..c455047 100644 (file)
@@ -27,6 +27,8 @@ int sh_pcic_io_dummy;
 static inline volatile __u16 *
 port2adr(unsigned int port)
 {
+       if (port & 0xff000000)
+               return ( volatile __u16 *) port;
        if (port >= 0x2000)
                return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
        else if (port >= 0x1000)
index 307ca5d..c8eccff 100644 (file)
@@ -55,23 +55,34 @@ void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
 }
 
 static struct ipr_data se770x_ipr_map[] = {
+       /*
+       * Super I/O (Just mimic PC):
+       *  1: keyboard
+       *  3: serial 0
+       *  4: serial 1
+       *  5: printer
+       *  6: floppy
+       *  8: rtc
+       * 12: mouse
+       * 14: ide0
+       */
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
        /* This is default value */
-       { 0xf-0x2, 0, 8,  0x2 , BCR_ILCRA},
-       { 0xf-0xa, 0, 4,  0xa , BCR_ILCRA},
-       { 0xf-0x5, 0, 0,  0x5 , BCR_ILCRB},
-       { 0xf-0x8, 0, 4,  0x8 , BCR_ILCRC},
-       { 0xf-0xc, 0, 0,  0xc , BCR_ILCRC},
-       { 0xf-0xe, 0, 12, 0xe , BCR_ILCRD},
-       { 0xf-0x3, 0, 4,  0x3 , BCR_ILCRD}, /* LAN */
-       { 0xf-0xd, 0, 8,  0xd , BCR_ILCRE},
-       { 0xf-0x9, 0, 4,  0x9 , BCR_ILCRE},
-       { 0xf-0x1, 0, 0,  0x1 , BCR_ILCRE},
-       { 0xf-0xf, 0, 12, 0xf , BCR_ILCRF},
-       { 0xf-0xb, 0, 4,  0xb , BCR_ILCRF},
-       { 0xf-0x7, 0, 12, 0x7 , BCR_ILCRG},
-       { 0xf-0x6, 0, 8,  0x6 , BCR_ILCRG},
-       { 0xf-0x4, 0, 4,  0x4 , BCR_ILCRG},
+       { 13, 0, 8,  0x0f-13 ,BCR_ILCRA},
+       { 5 , 0, 4,  0x0f- 5 ,BCR_ILCRA},
+       { 10, 0, 0,  0x0f-10, BCR_ILCRB},
+       { 7 , 0, 4,  0x0f- 7, BCR_ILCRC},
+       { 3 , 0, 0,  0x0f- 3, BCR_ILCRC},
+       { 1 , 0, 12, 0x0f- 1, BCR_ILCRD},
+       { 12, 0, 4,  0x0f-12, BCR_ILCRD}, /* LAN */
+       { 2 , 0, 8,  0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */
+       { 6 , 0, 4,  0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */
+       { 14, 0, 0,  0x0f-14, BCR_ILCRE}, /* PCIRQ0 */
+       { 0 , 0, 12, 0x0f   , BCR_ILCRF}, 
+       { 4 , 0, 4,  0x0f- 4, BCR_ILCRF},
+       { 8 , 0, 12, 0x0f- 8, BCR_ILCRG},
+       { 9 , 0, 8,  0x0f- 9, BCR_ILCRG},
+       { 11, 0, 4,  0x0f-11, BCR_ILCRG},
 #else
        { 14, 0,  8, 0x0f-14 ,BCR_ILCRA},
        { 12, 0,  4, 0x0f-12 ,BCR_ILCRA},
@@ -81,8 +92,10 @@ static struct ipr_data se770x_ipr_map[] = {
        {  4, 0,  4, 0x0f- 4 ,BCR_ILCRC},
        {  3, 0,  0, 0x0f- 3 ,BCR_ILCRC},
        {  1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
+#if defined(CONFIG_STNIC)
        /* ST NIC */
        { 10, 0,  4, 0x0f-10 ,BCR_ILCRD},       /* LAN */
+#endif
        /* MRSHPC IRQs setting */
        {  0, 0, 12, 0x0f- 0 ,BCR_ILCRE},       /* PCIRQ3 */
        { 11, 0,  8, 0x0f-11 ,BCR_ILCRE},       /* PCIRQ2 */
@@ -100,18 +113,6 @@ static struct ipr_data se770x_ipr_map[] = {
  */
 void __init init_se_IRQ(void)
 {
-        /*
-         * Super I/O (Just mimic PC):
-         *  1: keyboard
-         *  3: serial 0
-         *  4: serial 1
-         *  5: printer
-         *  6: floppy
-         *  8: rtc
-         * 12: mouse
-         * 14: ide0
-         */
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
        /* Disable all interrupts */
        ctrl_outw(0, BCR_ILCRA);
        ctrl_outw(0, BCR_ILCRB);
@@ -120,6 +121,6 @@ void __init init_se_IRQ(void)
        ctrl_outw(0, BCR_ILCRE);
        ctrl_outw(0, BCR_ILCRF);
        ctrl_outw(0, BCR_ILCRG);
-#endif
+
        make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
 }
index 45cbc36..17a2631 100644 (file)
@@ -63,6 +63,31 @@ static void __init smsc_setup(char **cmdline_p)
        outb_p(CONFIG_EXIT, CONFIG_PORT);
 }
 
+
+static struct resource cf_ide_resources[] = {
+       [0] = {
+               .start  = PA_MRSHPC_IO + 0x1f0,
+               .end    = PA_MRSHPC_IO + 0x1f0 + 8,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = PA_MRSHPC_IO + 0x1f0 + 0x206,
+               .end    = PA_MRSHPC_IO + 0x1f0 +8 + 0x206 + 8,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start  = IRQ_CFCARD,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_ide_device  = {
+       .name           = "pata_platform",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+};
+
 static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
 
 static struct resource heartbeat_resources[] = {
@@ -85,13 +110,14 @@ static struct platform_device heartbeat_device = {
 
 static struct platform_device *se_devices[] __initdata = {
        &heartbeat_device,
+       &cf_ide_device,
 };
 
 static int __init se_devices_setup(void)
 {
        return platform_add_devices(se_devices, ARRAY_SIZE(se_devices));
 }
-__initcall(se_devices_setup);
+device_initcall(se_devices_setup);
 
 /*
  * The Machine Vector
@@ -107,6 +133,8 @@ struct sh_machine_vector mv_se __initmv = {
        .mv_nr_irqs             = 61,
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705)
        .mv_nr_irqs             = 86,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
+       .mv_nr_irqs             = 104,
 #endif
 
        .mv_inb                 = se_inb,
diff --git a/arch/sh/boards/se/7722/Makefile b/arch/sh/boards/se/7722/Makefile
new file mode 100644 (file)
index 0000000..8694373
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the HITACHI UL SolutionEngine 7722 specific parts of the kernel
+#
+# 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.
+#
+#
+
+obj-y   := setup.o irq.o
diff --git a/arch/sh/boards/se/7722/irq.c b/arch/sh/boards/se/7722/irq.c
new file mode 100644 (file)
index 0000000..099e5de
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * linux/arch/sh/boards/se/7722/irq.c
+ *
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7722 Support.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/se7722.h>
+
+#define INTC_INTMSK0             0xFFD00044
+#define INTC_INTMSKCLR0          0xFFD00064
+
+static void disable_se7722_irq(unsigned int irq)
+{
+       struct ipr_data *p = get_irq_chip_data(irq);
+       ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
+}
+
+static void enable_se7722_irq(unsigned int irq)
+{
+       struct ipr_data *p = get_irq_chip_data(irq);
+       ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
+}
+
+static struct irq_chip se7722_irq_chip __read_mostly = {
+       .name           = "SE7722",
+       .mask           = disable_se7722_irq,
+       .unmask         = enable_se7722_irq,
+       .mask_ack       = disable_se7722_irq,
+};
+
+static struct ipr_data ipr_irq_table[] = {
+       /* irq        ,idx,sft, priority     , addr   */
+       { MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
+       { MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
+       { MRSHPC_IRQ2 , 0 , 0 , MRSHPC_BIT2 , IRQ01_MASK } ,
+       { MRSHPC_IRQ3 , 0 , 0 , MRSHPC_BIT3 , IRQ01_MASK } ,
+       { SMC_IRQ     , 0 , 0 , SMC_BIT     , IRQ01_MASK } ,
+       { EXT_IRQ     , 0 , 0 , EXT_BIT     , IRQ01_MASK } ,
+};
+
+int se7722_irq_demux(int irq)
+{
+
+       if ((irq == IRQ0_IRQ)||(irq == IRQ1_IRQ)) {
+               volatile unsigned short intv =
+                       *(volatile unsigned short *)IRQ01_STS;
+               if (irq == IRQ0_IRQ){
+                       if(intv & SMC_BIT ) {
+                               return SMC_IRQ;
+                       } else if(intv & USB_BIT) {
+                               return USB_IRQ;
+                       } else {
+                               printk("intv =%04x\n", intv);
+                               return SMC_IRQ;
+                       }
+               } else if(irq == IRQ1_IRQ){
+                       if(intv & MRSHPC_BIT0) {
+                               return MRSHPC_IRQ0;
+                       } else if(intv & MRSHPC_BIT1) {
+                               return MRSHPC_IRQ1;
+                       } else if(intv & MRSHPC_BIT2) {
+                               return MRSHPC_IRQ2;
+                       } else if(intv & MRSHPC_BIT3) {
+                               return MRSHPC_IRQ3;
+                       } else {
+                               printk("BIT_EXTENTION =%04x\n", intv);
+                               return EXT_IRQ;
+                       }
+               }
+       }
+       return irq;
+
+}
+/*
+ * Initialize IRQ setting
+ */
+void __init init_se7722_IRQ(void)
+{
+       int i = 0;
+       ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+       ctrl_outl((3 << ((7 - 0) * 4))|(3 << ((7 - 1) * 4)), INTC_INTPRI0);     /* irq0 pri=3,irq1,pri=3 */
+       ctrl_outw((2 << ((7 - 0) * 2))|(2 << ((7 - 1) * 2)), INTC_ICR1);        /* irq0,1 low-level irq */
+
+       for (i = 0; i < ARRAY_SIZE(ipr_irq_table); i++) {
+               disable_irq_nosync(ipr_irq_table[i].irq);
+               set_irq_chip_and_handler_name( ipr_irq_table[i].irq, &se7722_irq_chip,
+                       handle_level_irq, "level");
+               set_irq_chip_data( ipr_irq_table[i].irq, &ipr_irq_table[i] );
+               disable_se7722_irq(ipr_irq_table[i].irq);
+       }
+}
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
new file mode 100644 (file)
index 0000000..636ca6c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * linux/arch/sh/boards/se/7722/setup.c
+ *
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7722 Support.
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/pata_platform.h>
+#include <asm/machvec.h>
+#include <asm/se7722.h>
+#include <asm/io.h>
+
+/* Heartbeat */
+static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+/* SMC91x */
+static struct resource smc91x_eth_resources[] = {
+       [0] = {
+               .name   = "smc91x-regs" ,
+               .start  = PA_LAN + 0x300,
+               .end    = PA_LAN + 0x300 + 0x10 ,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = SMC_IRQ,
+               .end    = SMC_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_eth_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /* don't use dma */
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(smc91x_eth_resources),
+       .resource       = smc91x_eth_resources,
+};
+
+static struct resource cf_ide_resources[] = {
+       [0] = {
+               .start  = PA_MRSHPC_IO + 0x1f0,
+               .end    = PA_MRSHPC_IO + 0x1f0 + 8 ,
+               .flags  = IORESOURCE_IO,
+       },
+       [1] = {
+               .start  = PA_MRSHPC_IO + 0x1f0 + 0x206,
+               .end    = PA_MRSHPC_IO + 0x1f0 +8 + 0x206 + 8,
+               .flags  = IORESOURCE_IO,
+       },
+       [2] = {
+               .start  = MRSHPC_IRQ0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_ide_device  = {
+       .name           = "pata_platform",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+};
+
+static struct platform_device *se7722_devices[] __initdata = {
+       &heartbeat_device,
+       &smc91x_eth_device,
+       &cf_ide_device,
+};
+
+static int __init se7722_devices_setup(void)
+{
+       return platform_add_devices(se7722_devices,
+               ARRAY_SIZE(se7722_devices));
+}
+device_initcall(se7722_devices_setup);
+
+static void __init se7722_setup(char **cmdline_p)
+{
+       ctrl_outw(0x010D, FPGA_OUT);    /* FPGA */
+
+       ctrl_outl(0x00051001, MSTPCR0);
+       ctrl_outl(0x00000000, MSTPCR1);
+       /* KEYSC, VOU, BEU, CEU, VEU, VPU, LCDC */
+       ctrl_outl(0xffffbfC0, MSTPCR2); 
+
+       ctrl_outw(0x0000, PORT_PECR);   /* PORT E 1 = IRQ5 ,E 0 = BS */
+       ctrl_outw(0x1000, PORT_PJCR);   /* PORT J 1 = IRQ1,J 0 =IRQ0 */
+
+       /* LCDC I/O */
+       ctrl_outw(0x0020, PORT_PSELD);
+
+       /* SIOF1*/
+       ctrl_outw(0x0003, PORT_PSELB);
+       ctrl_outw(0xe000, PORT_PSELC);
+       ctrl_outw(0x0000, PORT_PKCR);
+
+       /* LCDC */
+       ctrl_outw(0x4020, PORT_PHCR);
+       ctrl_outw(0x0000, PORT_PLCR);
+       ctrl_outw(0x0000, PORT_PMCR);
+       ctrl_outw(0x0002, PORT_PRCR);
+       ctrl_outw(0x0000, PORT_PXCR);   /* LCDC,CS6A */
+
+       /* KEYSC */
+       ctrl_outw(0x0A10, PORT_PSELA); /* BS,SHHID2 */
+       ctrl_outw(0x0000, PORT_PYCR);
+       ctrl_outw(0x0000, PORT_PZCR);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_se7722 __initmv = {
+       .mv_name                = "Solution Engine 7722" ,
+       .mv_setup               = se7722_setup ,
+       .mv_nr_irqs             = 109 ,
+       .mv_init_irq            = init_se7722_IRQ,
+       .mv_irq_demux           = se7722_irq_demux,
+
+};
+ALIAS_MV(se7722)
index e3feae6..770defe 100644 (file)
 #include <asm/se7751.h>
 #include <asm/io.h>
 
-void init_7751se_IRQ(void);
-
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-static int kgdb_uart_setup(void);
-static struct kgdb_sermap kgdb_uart_sermap = 
-{ "ttyS", 0, kgdb_uart_setup, NULL };
-#endif
-/*
- * Initialize the board
- */
-static void __init sh7751se_setup(char **cmdline_p)
-{
-       /* Call init_smsc() replacement to set up SuperIO. */
-       /* XXX: RTC setting comes here */
-#ifdef CONFIG_SH_KGDB
-       kgdb_register_sermap(&kgdb_uart_sermap);
-#endif
-}
-
-/*********************************************************************
- * Currently a hack (e.g. does not interact well w/serial.c, lots of *
- * hardcoded stuff) but may be useful if SCI/F needs debugging.      *
- * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and  *
- * arch/i386/lib/kgdb_serial.c).                                     *
- *********************************************************************/
-
-#ifdef CONFIG_SH_KGDB
-#include <linux/types.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-
-#define COM1_PORT 0x3f8  /* Base I/O address */
-#define COM1_IRQ  4      /* IRQ not used yet */
-#define COM2_PORT 0x2f8  /* Base I/O address */
-#define COM2_IRQ  3      /* IRQ not used yet */
-
-#define SB_CLOCK 1843200 /* Serial baud clock */
-#define SB_BASE (SB_CLOCK/16)
-#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
-
-struct uart_port {
-       int base;
-};
-#define UART_NPORTS 2
-struct uart_port uart_ports[] = {
-       { COM1_PORT },
-       { COM2_PORT },
-};
-struct uart_port *kgdb_uart_port;
-
-#define UART_IN(reg)   inb_p(kgdb_uart_port->base + reg)
-#define UART_OUT(reg,v)        outb_p((v), kgdb_uart_port->base + reg)
-
-/* Basic read/write functions for the UART */
-#define UART_LSR_RXCERR    (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
-static int kgdb_uart_getchar(void)
-{
-       int lsr;
-       int c = -1;
-
-       while (c == -1) {
-               lsr = UART_IN(UART_LSR);
-               if (lsr & UART_LSR_DR) 
-                       c = UART_IN(UART_RX);
-               if ((lsr & UART_LSR_RXCERR))
-                       c = -1;
-       }
-       return c;
-}
-
-static void kgdb_uart_putchar(int c)
-{
-       while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
-               ;
-       UART_OUT(UART_TX, c);
-}
-
-/*
- * Initialize UART to configured/requested values.
- * (But we don't interrupts yet, or interact w/serial.c)
- */
-static int kgdb_uart_setup(void)
-{
-       int port;
-       int lcr = 0;
-       int bdiv = 0;
-
-       if (kgdb_portnum >= UART_NPORTS) {
-               KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
-               return -1;
-       }
-
-       kgdb_uart_port = &uart_ports[kgdb_portnum];
-
-       /* Init sequence from gdb_hook_interrupt */
-       UART_IN(UART_RX);
-       UART_OUT(UART_IER, 0);
-
-       UART_IN(UART_RX);       /* Serial driver comments say */
-       UART_IN(UART_IIR);      /* this clears interrupt regs */
-       UART_IN(UART_MSR);
-
-       /* Figure basic LCR values */
-       switch (kgdb_bits) {
-       case '7':
-               lcr |= UART_LCR_WLEN7;
-               break;
-       default: case '8': 
-               lcr |= UART_LCR_WLEN8;
-               break;
-       }
-       switch (kgdb_parity) {
-       case 'O':
-               lcr |= UART_LCR_PARITY;
-               break;
-       case 'E':
-               lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
-               break;
-       default: break;
-       }
-
-       /* Figure the baud rate divisor */
-       bdiv = (SB_BASE/kgdb_baud);
-       
-       /* Set the baud rate and LCR values */
-       UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
-       UART_OUT(UART_DLL, (bdiv & 0xff));
-       UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
-       UART_OUT(UART_LCR, lcr);
-
-       /* Set the MCR */
-       UART_OUT(UART_MCR, SB_MCR);
-
-       /* Turn off FIFOs for now */
-       UART_OUT(UART_FCR, 0);
-
-       /* Setup complete: initialize function pointers */
-       kgdb_getchar = kgdb_uart_getchar;
-       kgdb_putchar = kgdb_uart_putchar;
-
-       return 0;
-}
-#endif /* CONFIG_SH_KGDB */
-
 static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
 
 static struct resource heartbeat_resources[] = {
@@ -197,7 +50,6 @@ __initcall(se7751_devices_setup);
  */
 struct sh_machine_vector mv_7751se __initmv = {
        .mv_name                = "7751 SolutionEngine",
-       .mv_setup               = sh7751se_setup,
        .mv_nr_irqs             = 72,
 
        .mv_inb                 = sh7751se_inb,
diff --git a/arch/sh/boards/se/7780/Makefile b/arch/sh/boards/se/7780/Makefile
new file mode 100644 (file)
index 0000000..6b88ada
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the HITACHI UL SolutionEngine 7780 specific parts of the kernel
+#
+# 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.
+#
+#
+
+obj-y   := setup.o irq.o
diff --git a/arch/sh/boards/se/7780/irq.c b/arch/sh/boards/se/7780/irq.c
new file mode 100644 (file)
index 0000000..3d0625c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/sh/boards/se/7780/irq.c
+ *
+ * Copyright (C) 2006,2007  Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7780 Support.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/se7780.h>
+
+#define INTC_INTMSK0             0xFFD00044
+#define INTC_INTMSKCLR0          0xFFD00064
+
+static void disable_se7780_irq(unsigned int irq)
+{
+       struct intc2_data *p = get_irq_chip_data(irq);
+       ctrl_outl(1 << p->msk_shift, INTC_INTMSK0 + p->msk_offset);
+}
+
+static void enable_se7780_irq(unsigned int irq)
+{
+       struct intc2_data *p = get_irq_chip_data(irq);
+       ctrl_outl(1 << p->msk_shift, INTC_INTMSKCLR0 + p->msk_offset);
+}
+
+static struct irq_chip se7780_irq_chip __read_mostly = {
+       .name           = "SE7780",
+       .mask           = disable_se7780_irq,
+       .unmask         = enable_se7780_irq,
+       .mask_ack       = disable_se7780_irq,
+};
+
+static struct intc2_data intc2_irq_table[] = {
+       { 2,  0, 31, 0, 31, 3 }, /* daughter board EXTINT1 */
+       { 4,  0, 30, 0, 30, 3 }, /* daughter board EXTINT2 */
+       { 6,  0, 29, 0, 29, 3 }, /* daughter board EXTINT3 */
+       { 8,  0, 28, 0, 28, 3 }, /* SMC 91C111 (LAN) */
+       { 10, 0, 27, 0, 27, 3 }, /* daughter board EXTINT4 */
+       { 4,  0, 30, 0, 30, 3 }, /* daughter board EXTINT5 */
+       { 2,  0, 31, 0, 31, 3 }, /* daughter board EXTINT6 */
+       { 2,  0, 31, 0, 31, 3 }, /* daughter board EXTINT7 */
+       { 2,  0, 31, 0, 31, 3 }, /* daughter board EXTINT8 */
+       { 0 , 0, 24, 0, 24, 3 }, /* SM501 */
+};
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_se7780_IRQ(void)
+{
+       int i ;
+
+       /* enable all interrupt at FPGA */
+       ctrl_outw(0, FPGA_INTMSK1);
+       /* mask SM501 interrupt */
+       ctrl_outw((ctrl_inw(FPGA_INTMSK1) | 0x0002), FPGA_INTMSK1);
+       /* enable all interrupt at FPGA */
+       ctrl_outw(0, FPGA_INTMSK2);
+
+       /* set FPGA INTSEL register */
+       /* FPGA + 0x06 */
+       ctrl_outw( ((IRQPIN_SM501 << IRQPOS_SM501) |
+               (IRQPIN_SMC91CX << IRQPOS_SMC91CX)), FPGA_INTSEL1);
+
+       /* FPGA + 0x08 */
+       ctrl_outw(((IRQPIN_EXTINT4 << IRQPOS_EXTINT4) |
+               (IRQPIN_EXTINT3 << IRQPOS_EXTINT3) |
+               (IRQPIN_EXTINT2 << IRQPOS_EXTINT2) |
+               (IRQPIN_EXTINT1 << IRQPOS_EXTINT1)), FPGA_INTSEL2);
+
+       /* FPGA + 0x0A */
+       ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
+
+       for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) {
+               disable_irq_nosync(intc2_irq_table[i].irq);
+               set_irq_chip_and_handler_name( intc2_irq_table[i].irq, &se7780_irq_chip,
+                       handle_level_irq, "level");
+               set_irq_chip_data( intc2_irq_table[i].irq, &intc2_irq_table[i] );
+               disable_se7780_irq(intc2_irq_table[i].irq);
+       }
+}
diff --git a/arch/sh/boards/se/7780/setup.c b/arch/sh/boards/se/7780/setup.c
new file mode 100644 (file)
index 0000000..df7d08a
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * linux/arch/sh/boards/se/7780/setup.c
+ *
+ * Copyright (C) 2006,2007  Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7780 Support.
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/se7780.h>
+#include <asm/io.h>
+
+/* Heartbeat */
+static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PA_LED,
+               .end    = PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = heartbeat_bit_pos,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+/* SMC91x */
+static struct resource smc91x_eth_resources[] = {
+       [0] = {
+               .name   = "smc91x-regs" ,
+               .start  = PA_LAN + 0x300,
+               .end    = PA_LAN + 0x300 + 0x10 ,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = SMC_IRQ,
+               .end    = SMC_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_eth_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /* don't use dma */
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(smc91x_eth_resources),
+       .resource       = smc91x_eth_resources,
+};
+
+static struct platform_device *se7780_devices[] __initdata = {
+       &heartbeat_device,
+       &smc91x_eth_device,
+};
+
+static int __init se7780_devices_setup(void)
+{
+       return platform_add_devices(se7780_devices,
+               ARRAY_SIZE(se7780_devices));
+}
+device_initcall(se7780_devices_setup);
+
+#define GPIO_PHCR        0xFFEA000E
+#define GPIO_PMSELR      0xFFEA0080
+#define GPIO_PECR        0xFFEA0008
+
+static void __init se7780_setup(char **cmdline_p)
+{
+       /* "SH-Linux" on LED Display */
+       ctrl_outw( 'S' , PA_LED_DISP + (DISP_SEL0_ADDR << 1) );
+       ctrl_outw( 'H' , PA_LED_DISP + (DISP_SEL1_ADDR << 1) );
+       ctrl_outw( '-' , PA_LED_DISP + (DISP_SEL2_ADDR << 1) );
+       ctrl_outw( 'L' , PA_LED_DISP + (DISP_SEL3_ADDR << 1) );
+       ctrl_outw( 'i' , PA_LED_DISP + (DISP_SEL4_ADDR << 1) );
+       ctrl_outw( 'n' , PA_LED_DISP + (DISP_SEL5_ADDR << 1) );
+       ctrl_outw( 'u' , PA_LED_DISP + (DISP_SEL6_ADDR << 1) );
+       ctrl_outw( 'x' , PA_LED_DISP + (DISP_SEL7_ADDR << 1) );
+
+       printk(KERN_INFO "Hitachi UL Solutions Engine 7780SE03 support.\n");
+
+       /*
+        * PCI REQ/GNT setting
+        *   REQ0/GNT0 -> USB
+        *   REQ1/GNT1 -> PC Card
+        *   REQ2/GNT2 -> Serial ATA
+        *   REQ3/GNT3 -> PCI slot
+        */
+       ctrl_outw(0x0213, FPGA_REQSEL);
+
+       /* GPIO setting */
+       ctrl_outw(0x0000, GPIO_PECR);
+       ctrl_outw(ctrl_inw(GPIO_PHCR)&0xfff3, GPIO_PHCR);
+       ctrl_outw(0x0c00, GPIO_PMSELR);
+
+       /* iVDR Power ON */
+       ctrl_outw(0x0001, FPGA_IVDRPW);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_se7780 __initmv = {
+       .mv_name                = "Solution Engine 7780" ,
+       .mv_setup               = se7780_setup ,
+       .mv_nr_irqs             = 111 ,
+       .mv_init_irq            = init_se7780_IRQ,
+};
+ALIAS_MV(se7780)
diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig
new file mode 100644 (file)
index 0000000..be86414
--- /dev/null
@@ -0,0 +1,1271 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc4
+# Sat Mar 24 22:04:27 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+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 is not set
+CONFIG_SYSFS_DEPRECATED=y
+# 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 is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+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=y
+# 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=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_HIGHLANDER is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+CONFIG_SH_LBOX_RE2=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB 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=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=40000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200 root=/dev/sda1"
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+CONFIG_PCMCIA_DEBUG=y
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+# CONFIG_YENTA_RICOH is not set
+# CONFIG_YENTA_TI is not set
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# 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=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES 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 is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# 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 is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# 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=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# 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_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PCMCIA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_QDI is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_WINBOND_VLB is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# 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_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=y
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C 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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# 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=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# 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=y
+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 is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS 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_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 is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# 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 is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index 2b75b48..48c6a21 100644 (file)
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec  6 11:59:38 2006
+# Linux kernel version: 2.6.21-rc7
+# Tue May  1 12:28:39 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -13,6 +14,8 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -31,6 +34,7 @@ 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=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
@@ -41,7 +45,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -99,23 +103,23 @@ CONFIG_DEFAULT_IOSCHED="noop"
 # System type
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7722_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7780_SOLUTION_ENGINE is not set
 # CONFIG_SH_7300_SOLUTION_ENGINE is not set
 # CONFIG_SH_7343_SOLUTION_ENGINE is not set
 # CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
 # CONFIG_SH_SATURN is not set
 # CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
 # CONFIG_SH_MPC1211 is not set
 # CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_7710VOIPGW is not set
 # CONFIG_SH_RTS7751R2D is not set
-CONFIG_SH_R7780RP=y
+CONFIG_SH_HIGHLANDER=y
 # CONFIG_SH_EDOSK7705 is not set
 # CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_LANDISK is not set
@@ -123,7 +127,11 @@ CONFIG_SH_R7780RP=y
 # CONFIG_SH_SHMIN is not set
 # CONFIG_SH_7206_SOLUTION_ENGINE is not set
 # CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_LBOX_RE2 is not set
 # CONFIG_SH_UNKNOWN is not set
+CONFIG_SH_R7780RP=y
+# CONFIG_SH_R7780MP is not set
+# CONFIG_SH_R7785RP is not set
 
 #
 # Processor selection
@@ -152,6 +160,7 @@ CONFIG_CPU_SH4A=y
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 
 #
 # SH-4 Processor Support
@@ -183,6 +192,7 @@ CONFIG_CPU_SUBTYPE_SH7780=y
 #
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
@@ -193,6 +203,8 @@ CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 # CONFIG_32BIT is not set
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -210,6 +222,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 
 #
 # Cache configuration
@@ -226,20 +239,15 @@ CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 CONFIG_SH_STORE_QUEUES=y
+CONFIG_SPECULATIVE_EXECUTION=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_INTC2_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 
 #
-# Timer support
+# Timer and clock configuration
 #
 CONFIG_SH_TMU=y
-
-#
-# R7780RP options
-#
-CONFIG_SH_R7780MP=y
 CONFIG_SH_TIMER_IRQ=28
 CONFIG_NO_IDLE_HZ=y
 CONFIG_SH_PCLK_FREQ=32000000
@@ -262,6 +270,7 @@ CONFIG_SH_PCLK_FREQ=32000000
 #
 # Additional SuperH Device Drivers
 #
+# CONFIG_HEARTBEAT is not set
 CONFIG_PUSH_SWITCH=y
 
 #
@@ -269,9 +278,11 @@ CONFIG_PUSH_SWITCH=y
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
@@ -294,7 +305,6 @@ CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -334,6 +344,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # 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
@@ -425,6 +436,7 @@ 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
 
 #
@@ -445,6 +457,7 @@ CONFIG_FW_LOADER=m
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -461,7 +474,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -481,6 +493,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -500,6 +513,7 @@ CONFIG_CHR_DEV_SG=m
 # 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
@@ -544,11 +558,13 @@ CONFIG_CHR_DEV_SG=m
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -564,6 +580,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
@@ -579,6 +596,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -685,6 +703,7 @@ CONFIG_8139TOO_8129=y
 CONFIG_VIA_RHINE=m
 CONFIG_VIA_RHINE_MMIO=y
 # CONFIG_VIA_RHINE_NAPI is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -707,11 +726,13 @@ CONFIG_R8169=y
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -889,9 +910,15 @@ CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
 #
 # Multimedia devices
 #
@@ -905,9 +932,8 @@ CONFIG_HWMON=y
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
 
 #
 # Sound
@@ -923,15 +949,20 @@ CONFIG_SOUND=m
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
-# CONFIG_OSS_OBSOLETE_DRIVER is not set
+# CONFIG_OBSOLETE_OSS is not set
 # CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
 #
 # USB support
 #
@@ -1016,6 +1047,14 @@ CONFIG_RTC_DRV_SH=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
 #
 # File systems
 #
@@ -1174,6 +1213,11 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Profiling support
 #
@@ -1184,19 +1228,22 @@ CONFIG_OPROFILE=m
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_PRINTK_TIME=y
+# CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# 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_PREEMPT is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1204,19 +1251,19 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_FRAME_POINTER is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_KGDB is not set
+# CONFIG_SH_KGDB is not set
 
 #
 # Security options
@@ -1233,6 +1280,7 @@ CONFIG_CRYPTO_BLKCIPHER=y
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1241,9 +1289,13 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1257,6 +1309,7 @@ CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1266,7 +1319,10 @@ CONFIG_CRYPTO_DES=y
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
new file mode 100644 (file)
index 0000000..0f5ec64
--- /dev/null
@@ -0,0 +1,1334 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc3
+# Mon Mar 12 14:26:33 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=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=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+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 is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=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_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_R7780MP is not set
+CONFIG_SH_R7785RP=y
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+CONFIG_CPU_SUBTYPE_SH7785=y
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_32BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+CONFIG_HUGETLB_PAGE_SIZE_1MB=y
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB 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=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_DSP is not set
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_NO_IDLE_HZ=y
+CONFIG_SH_PCLK_FREQ=50000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+CONFIG_PUSH_SWITCH=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# 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=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# 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 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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 is not set
+# 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 is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# 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 is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# 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=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+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_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY 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=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW 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_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C 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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frambuffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# 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=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=y
+# 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=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# 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_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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_LOCKDEP=y
+# CONFIG_DEBUG_LOCKDEP is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index 06ebd6e..87ae5c1 100644 (file)
@@ -1,15 +1,21 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 12:03:04 2006
+# Linux kernel version: 2.6.21-rc5
+# Thu Apr 26 09:16:31 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -33,7 +39,9 @@ CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -91,27 +99,30 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_SOLUTION_ENGINE=y
 CONFIG_SH_SOLUTION_ENGINE=y
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7780_SOLUTION_ENGINE is not set
 # CONFIG_SH_7300_SOLUTION_ENGINE is not set
 # CONFIG_SH_7343_SOLUTION_ENGINE is not set
 # CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7722_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
 # CONFIG_SH_SATURN is not set
 # CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
 # CONFIG_SH_MPC1211 is not set
 # CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_7710VOIPGW is not set
 # CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_HIGHLANDER is not set
 # CONFIG_SH_EDOSK7705 is not set
 # CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_LANDISK is not set
 # CONFIG_SH_TITAN is not set
 # CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_LBOX_RE2 is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -123,6 +134,12 @@ CONFIG_CPU_SH3=y
 # SH-2 Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 
 #
 # SH-3 Processor Support
@@ -134,6 +151,7 @@ CONFIG_CPU_SUBTYPE_SH7705=y
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 
 #
 # SH-4 Processor Support
@@ -158,12 +176,14 @@ CONFIG_CPU_SUBTYPE_SH7705=y
 #
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
 
 #
 # SH4AL-DSP Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
@@ -173,6 +193,11 @@ CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -182,6 +207,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 
 #
 # Cache configuration
@@ -190,23 +216,31 @@ CONFIG_SH7705_CACHE_32KB=y
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
 # CONFIG_SH_OCRAM is not set
-# CONFIG_CF_ENABLER is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+# CONFIG_CF_AREA4 is not set
+CONFIG_CF_BASE_ADDR=0xb8000000
 
 #
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 # CONFIG_SH_FPU_EMU is not set
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_ADC is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_PINT_IRQ=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 
 #
-# Timer support
+# Timer and clock configuration
 #
 CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=33333333
 
 #
@@ -223,13 +257,19 @@ CONFIG_SH_PCLK_FREQ=33333333
 # Companion Chips
 #
 # CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
 CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
 
 #
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
@@ -287,6 +327,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # 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
@@ -307,11 +348,13 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # 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 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -388,6 +431,7 @@ CONFIG_MTD_PARTITIONS=y
 # 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
@@ -461,6 +505,7 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -472,10 +517,13 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
+#
+# Misc devices
+#
+
 #
 # ATA/ATAPI/MFM/RLL support
 #
@@ -649,17 +697,12 @@ CONFIG_HW_RANDOM=y
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -675,6 +718,7 @@ CONFIG_HW_RANDOM=y
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -683,18 +727,19 @@ CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
+# Multifunction device drivers
 #
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -704,7 +749,7 @@ CONFIG_VIDEO_V4L2=y
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 
 #
@@ -712,6 +757,12 @@ CONFIG_FIRMWARE_EDID=y
 #
 # CONFIG_SOUND is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
 #
 # USB support
 #
@@ -772,6 +823,14 @@ CONFIG_FIRMWARE_EDID=y
 # DMA Devices
 #
 
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
 #
 # File systems
 #
@@ -779,10 +838,12 @@ CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -828,7 +889,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -877,6 +937,10 @@ CONFIG_MSDOS_PARTITION=y
 #
 # CONFIG_NLS is not set
 
+#
+# Distributed Lock Manager
+#
+
 #
 # Profiling support
 #
@@ -885,15 +949,18 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
-# CONFIG_KGDB is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_SH_KGDB is not set
 
 #
 # Security options
@@ -908,6 +975,7 @@ CONFIG_LOG_BUF_SHIFT=14
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -915,3 +983,5 @@ CONFIG_CRC32=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/sh/configs/se7712_defconfig b/arch/sh/configs/se7712_defconfig
new file mode 100644 (file)
index 0000000..a5e37db
--- /dev/null
@@ -0,0 +1,1088 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc4
+# Wed Mar 28 10:19:02 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+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 is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+# CONFIG_BUG is not set
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# 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_SOLUTION_ENGINE=y
+CONFIG_SH_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_HIGHLANDER is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_LBOX_RE2 is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+CONFIG_CPU_SUBTYPE_SH7712=y
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB 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=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_DIAG is not set
+# 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 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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 is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# 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=y
+CONFIG_NET_SCH_FIFO=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_HFSC=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_RED=y
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TEQL=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_GRED=y
+CONFIG_NET_SCH_DSMARK=y
+CONFIG_NET_SCH_NETEM=y
+CONFIG_NET_SCH_INGRESS=y
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=y
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+# CONFIG_NET_CLS_POLICE is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_FIB_RULES=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# 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=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_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 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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# 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=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# 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=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# 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 is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET 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 is not set
+# CONFIG_SLIP is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT 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_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+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 is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_GEN_RTC 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 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 is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# 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 is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# 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 is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS 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 is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# 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 is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# 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 is not set
+# 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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING 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_INFO=y
+# 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_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
new file mode 100644 (file)
index 0000000..ca4c663
--- /dev/null
@@ -0,0 +1,980 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc7
+# Fri Apr 27 16:30:30 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=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=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS 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_SOLUTION_ENGINE=y
+# CONFIG_SH_SOLUTION_ENGINE is not set
+CONFIG_SH_7722_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7780_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_HIGHLANDER is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_LBOX_RE2 is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SH4AL_DSP=y
+CONFIG_CPU_SHX2=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+CONFIG_CPU_SUBTYPE_SH7722=y
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+# CONFIG_32BIT is not set
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB 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=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_NO_IDLE_HZ=y
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# 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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# 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 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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 is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# 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 is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER 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 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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# 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=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# 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=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# 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 is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+CONFIG_SMC91X=y
+
+#
+# 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 is not set
+# CONFIG_SLIP is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY 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=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW 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_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC 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 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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB 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=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# 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 is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+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_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 is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# 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 is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig
new file mode 100644 (file)
index 0000000..538661e
--- /dev/null
@@ -0,0 +1,1309 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc3
+# Thu Mar 15 14:06:20 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# 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=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+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_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_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+CONFIG_SOLUTION_ENGINE=y
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+CONFIG_SH_7780_SOLUTION_ENGINE=y
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_HIGHLANDER is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_32BIT=y
+CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00810000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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 is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK 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 is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD 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 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=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+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 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP 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=y
+# 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 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 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
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# 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_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_SMC91X=y
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C 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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# 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=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frambuffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_OBSOLETE_OSS is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# 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=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# 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_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK 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
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN 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_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 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_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS 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_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 is not set
+# 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 is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+# CONFIG_SYSFS is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
index c54c758..420c6b2 100644 (file)
@@ -1,5 +1,15 @@
+source "arch/sh/drivers/dma/Kconfig"
+source "arch/sh/cchips/Kconfig"
+
 menu "Additional SuperH Device Drivers"
 
+config HEARTBEAT
+       bool "Heartbeat LED"
+       help
+         Use the power-on LED on your machine as a load meter.  The exact
+         behavior is platform-dependent, but normally the flash frequency is
+         a hyperbolic function of the 5-minute load average.
+
 config PUSH_SWITCH
        tristate "Push switch support"
        help
index bc59cb6..23dd608 100644 (file)
@@ -40,16 +40,9 @@ static void heartbeat_timer(unsigned long data)
        static unsigned bit = 0, up = 1;
 
        ctrl_outw(1 << hd->bit_pos[bit], (unsigned long)hd->base);
-       if (up)
-               if (bit == (ARRAY_SIZE(hd->bit_pos) - 1)) {
-                       bit--;
-                       up = 0;
-               } else
-                       bit++;
-       else if (bit == 0)
-               up = 1;
-       else
-               bit--;
+       bit += up;
+       if ((bit == 0) || (bit == ARRAY_SIZE(hd->bit_pos)-1))
+               up = -up;
 
        mod_timer(&hd->timer, jiffies + (110 - ((300 << FSHIFT) /
                        ((avenrun[0] / 5) + (3 << FSHIFT)))));
index cc8d0d0..0e9b532 100644 (file)
@@ -8,12 +8,15 @@ obj-$(CONFIG_PCI_AUTO)                        += pci-auto.o
 obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)     += pci-st40.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += pci-sh7751.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += pci-sh7780.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7785)       += pci-sh7780.o ops-sh4.o
 
 obj-$(CONFIG_SH_DREAMCAST)             += ops-dreamcast.o fixups-dreamcast.o \
                                           dma-dreamcast.o
 obj-$(CONFIG_SH_SECUREEDGE5410)                += ops-snapgear.o
 obj-$(CONFIG_SH_RTS7751R2D)            += ops-rts7751r2d.o fixups-rts7751r2d.o
 obj-$(CONFIG_SH_SH03)                  += ops-sh03.o fixups-sh03.o
-obj-$(CONFIG_SH_R7780RP)               += ops-r7780rp.o fixups-r7780rp.o
+obj-$(CONFIG_SH_HIGHLANDER)            += ops-r7780rp.o fixups-r7780rp.o
 obj-$(CONFIG_SH_TITAN)                 += ops-titan.o
 obj-$(CONFIG_SH_LANDISK)               += ops-landisk.o
+obj-$(CONFIG_SH_LBOX_RE2)              += ops-lboxre2.o fixups-lboxre2.o
+obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)  += ops-se7780.o fixups-se7780.o
diff --git a/arch/sh/drivers/pci/fixups-lboxre2.c b/arch/sh/drivers/pci/fixups-lboxre2.c
new file mode 100644 (file)
index 0000000..40b19bd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/drivers/pci/fixups-lboxre2.c
+ *
+ * L-BOX RE2 PCI fixups
+ *
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ * 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 "pci-sh4.h"
+
+#define PCIMCR_MRSET_OFF       0xBFFFFFFF
+#define PCIMCR_RFSH_OFF                0xFFFFFFFB
+
+int pci_fixup_pcic(void)
+{
+       unsigned long bcr1, mcr;
+
+       bcr1 = inl(SH7751_BCR1);
+       bcr1 |= 0x40080000;     /* Enable Bit 19 BREQEN, set PCIC to slave */
+       pci_write_reg(bcr1, SH4_PCIBCR1);
+
+       /* Enable all interrupts, so we known what to fix */
+       pci_write_reg(0x0000c3ff, SH4_PCIINTM);
+       pci_write_reg(0x0000380f, SH4_PCIAINTM);
+       pci_write_reg(0xfb900047, SH7751_PCICONF1);
+       pci_write_reg(0xab000001, SH7751_PCICONF4);
+
+       mcr = inl(SH7751_MCR);
+       mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+       pci_write_reg(mcr, SH4_PCIMCR);
+
+       pci_write_reg(0x0c000000, SH7751_PCICONF5);
+       pci_write_reg(0xd0000000, SH7751_PCICONF6);
+       pci_write_reg(0x0c000000, SH4_PCILAR0);
+       pci_write_reg(0x00000000, SH4_PCILAR1);
+
+       return 0;
+}
diff --git a/arch/sh/drivers/pci/fixups-se7780.c b/arch/sh/drivers/pci/fixups-se7780.c
new file mode 100644 (file)
index 0000000..880cea1
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * arch/sh/drivers/pci/fixups-se7780.c
+ *
+ * HITACHI UL Solution Engine 7780  PCI fixups
+ *
+ * Copyright (C) 2003  Lineo uSolutions, Inc.
+ * Copyright (C) 2004 - 2006  Paul Mundt
+ * Copyright (C) 2006  Nobuhiro Iwamatsu
+ *
+ * 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/pci.h>
+#include "pci-sh4.h"
+#include <asm/io.h>
+
+int pci_fixup_pcic(void)
+{
+       ctrl_outl(0x00000001, SH7780_PCI_VCR2);
+
+       /* Enable all interrupts, so we know what to fix */
+       pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
+       pci_write_reg(0x0000380F, SH7780_PCIAINTM);
+
+       /* Set up standard PCI config registers */
+       ctrl_outw(0xFB00, PCI_REG(SH7780_PCISTATUS));
+       ctrl_outw(0x0047, PCI_REG(SH7780_PCICMD));
+       ctrl_outb(  0x00, PCI_REG(SH7780_PCIPIF));
+       ctrl_outb(  0x00, PCI_REG(SH7780_PCISUB));
+       ctrl_outb(  0x06, PCI_REG(SH7780_PCIBCC));
+       ctrl_outw(0x1912, PCI_REG(SH7780_PCISVID));
+       ctrl_outw(0x0001, PCI_REG(SH7780_PCISID));
+
+       pci_write_reg(0x08000000, SH7780_PCIMBAR0);     /* PCI */
+       pci_write_reg(0x08000000, SH7780_PCILAR0);     /* SHwy */
+       pci_write_reg(0x07F00001, SH7780_PCILSR);      /* size 128M w/ MBAR */
+
+       pci_write_reg(0x00000000, SH7780_PCIMBAR1);
+       pci_write_reg(0x00000000, SH7780_PCILAR1);
+       pci_write_reg(0x00000000, SH7780_PCILSR1);
+
+       pci_write_reg(0xAB000801, SH7780_PCIIBAR);
+
+       /*
+        * Set the MBR so PCI address is one-to-one with window,
+        * meaning all calls go straight through... use ifdef to
+        * catch erroneous assumption.
+        */
+       pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
+       pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0);    /* 16M */
+
+       /* Set IOBR for window containing area specified in pci.h */
+       pci_write_reg(PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1), SH7780_PCIIOBR);
+       pci_write_reg((SH7780_PCI_IO_SIZE-1) & (7 << 18), SH7780_PCIIOBMR);
+
+       pci_write_reg(0xA5000C01, SH7780_PCICR);
+
+       return 0;
+}
index d060308..bff09ec 100644 (file)
@@ -17,8 +17,8 @@
 
 static struct resource sh7751_io_resource = {
        .name = "SH7751 IO",
-       .start = 0x4000,
-       .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+       .start = SH7751_PCI_IO_BASE,
+       .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
        .flags = IORESOURCE_IO
 };
 
diff --git a/arch/sh/drivers/pci/ops-lboxre2.c b/arch/sh/drivers/pci/ops-lboxre2.c
new file mode 100644 (file)
index 0000000..a13cb76
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/sh/drivers/pci/ops-lboxre2.c
+ *
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ * PCI initialization for the NTT COMWARE L-BOX RE2
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <asm/lboxre2.h>
+#include "pci-sh4.h"
+
+static char lboxre2_irq_tab[] __initdata = {
+       IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       return lboxre2_irq_tab[slot];
+}
+
+static struct resource sh7751_io_resource = {
+       .name   = "SH7751_IO",
+       .start  = SH7751_PCI_IO_BASE ,
+       .end    = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+       .name   = "SH7751_mem",
+       .start  = SH7751_PCI_MEMORY_BASE,
+       .end    = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+       .window0        = {
+               .base   = SH7751_CS3_BASE_ADDR,
+               .size   = 0x04000000,
+       },
+       .window1        = {
+               .base   = 0x00000000,   /* Unused */
+               .size   = 0x00000000,   /* Unused */
+       },
+       .flags  = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7751_pcic_init(&sh7751_pci_map);
+}
index eeea157..f221608 100644 (file)
 #include <asm/io.h>
 #include "pci-sh4.h"
 
+static char r7780rp_irq_tab[] __initdata = {
+       0, 1, 2, 3,
+};
+
+static char r7780mp_irq_tab[] __initdata = {
+       65, 66, 67, 68,
+};
+
 int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
-        switch (slot) {
-       case 0: return IRQ_PCISLOT1;            /* PCI Interrupt #1 */
-       case 1: return IRQ_PCISLOT2;            /* PCI Interrupt #2 */
-       case 2: return IRQ_PCISLOT3;            /* PCI Interrupt #3 */
-       case 3: return IRQ_PCISLOT4;            /* PCI Interrupt E4 */
-       default:
-               printk(KERN_ERR "PCI: Bad IRQ mapping "
-                      "request for slot %d, func %d\n", slot, pin-1);
-               return -1;
-       }
+       if (mach_is_r7780rp())
+               return r7780rp_irq_tab[slot];
+       if (mach_is_r7780mp() || mach_is_r7785rp())
+               return r7780mp_irq_tab[slot];
+
+       printk(KERN_ERR "PCI: Bad IRQ mapping "
+              "request for slot %d, func %d\n", slot, pin-1);
+
+       return -1;
 }
 
 static struct resource sh7780_io_resource = {
diff --git a/arch/sh/drivers/pci/ops-se7780.c b/arch/sh/drivers/pci/ops-se7780.c
new file mode 100644 (file)
index 0000000..212674d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * linux/arch/sh/drivers/pci/ops-se7780.c
+ *
+ * Copyright (C) 2006  Nobuhiro Iwamatsu
+ *
+ * PCI initialization for the Hitachi UL Solution Engine 7780SE03
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm/se7780.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+/*
+ * IDSEL = AD16  PCI slot
+ * IDSEL = AD17  PCI slot
+ * IDSEL = AD18  Serial ATA Controller (Silicon Image SiL3512A)
+ * IDSEL = AD19  USB Host Controller (NEC uPD7210100A)
+ */
+
+/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
+static char se7780_irq_tab[4][16] __initdata = {
+       /* INTA */
+       { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+       /* INTB */
+       { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+       /* INTC */
+       { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+       /* INTD */
+       { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       return se7780_irq_tab[pin-1][slot];
+}
+
+static struct resource se7780_io_resource = {
+       .name   = "SH7780_IO",
+       .start  = 0x2000,
+       .end    = 0x2000 + SH7780_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource se7780_mem_resource = {
+       .name   = "SH7780_mem",
+       .start  = SH7780_PCI_MEMORY_BASE,
+       .end    = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+extern struct pci_ops se7780_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &se7780_io_resource, &se7780_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map se7780_pci_map = {
+       .window0        = {
+               .base   = SH7780_CS2_BASE_ADDR,
+               .size   = 0x04000000,
+       },
+       .flags  = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       printk("SH7780 PCI: Finished initialization of the PCI controller\n");
+
+       /*
+        * FPGA PCISEL register initialize
+        *
+        *  CPU  || SLOT1 | SLOT2 | S-ATA | USB
+        *  -------------------------------------
+        *  INTA || INTA  | INTD  |  --   | INTB
+        *  -------------------------------------
+        *  INTB || INTB  | INTA  |  --   | INTC
+        *  -------------------------------------
+        *  INTC || INTC  | INTB  | INTA  |  --
+        *  -------------------------------------
+        *  INTD || INTD  | INTC  |  --   | INTA
+        *  -------------------------------------
+        */
+       ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
+       ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
+
+       return sh7780_pcic_init(&se7780_pci_map);
+}
index 2d43710..54232f1 100644 (file)
@@ -162,3 +162,9 @@ char * __init pcibios_setup(char *str)
 
        return str;
 }
+
+int __attribute__((weak)) pci_fixup_pcic(void)
+{
+       /* Nothing to do. */
+       return 0;
+}
index 5a61d60..1901c33 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PCI_SH4_H
 #define __PCI_SH4_H
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
 #include "pci-sh7780.h"
 #else
 #include "pci-sh7751.h"
index 9ddff76..1aca7fe 100644 (file)
@@ -12,7 +12,6 @@
  *  License.  See linux/COPYING for more information.
  *
  */
-
 #undef DEBUG
 
 #include <linux/init.h>
@@ -28,7 +27,7 @@
  * Initialization. Try all known PCI access methods. Note that we support
  * using both PCI BIOS and direct access: in such cases, we use I/O ports
  * to access config space.
- * 
+ *
  * Note that the platform specific initialization (BSC registers, and memory
  * space mapping) will be called via the platform defined function
  * pcibios_init_platform().
@@ -115,7 +114,7 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
         * Wait Cycle Control + Parity Enable + Bus Master +
         * Mem space enable
         */
-       word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | 
+       word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
               SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
        pci_write_reg(word, SH7751_PCICONF1);
 
@@ -123,10 +122,10 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
        word = PCI_BASE_CLASS_BRIDGE << 24;
        pci_write_reg(word, SH7751_PCICONF2);
 
-       /* Set IO and Mem windows to local address 
-        * Make PCI and local address the same for easy 1 to 1 mapping 
+       /* Set IO and Mem windows to local address
+        * Make PCI and local address the same for easy 1 to 1 mapping
         * Window0 = map->window0.size @ non-cached area base = SDRAM
-        * Window1 = map->window1.size @ cached area base = SDRAM 
+        * Window1 = map->window1.size @ cached area base = SDRAM
         */
        word = map->window0.size - 1;
        pci_write_reg(word, SH4_PCILSR0);
@@ -175,7 +174,7 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
        case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(5); break;
        case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(6); break;
        }
-       
+
        if (!word)
                return 0;
 
@@ -194,9 +193,7 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
         * DMA interrupts...
         */
 
-#ifdef CONFIG_SH_RTS7751R2D
        pci_fixup_pcic();
-#endif
 
        /* SH7751 init done, set central function init complete */
        /* use round robin mode to stop a device starving/overruning */
index 602b644..5508e45 100644 (file)
@@ -48,7 +48,7 @@
 static int __init sh7780_pci_init(void)
 {
        unsigned int id;
-       int ret;
+       int ret, match = 0;
 
        pr_debug("PCI: Starting intialization.\n");
 
@@ -56,19 +56,43 @@ static int __init sh7780_pci_init(void)
 
        /* check for SH7780/SH7780R hardware */
        id = pci_read_reg(SH7780_PCIVID);
-       if ((id != ((SH7780_DEVICE_ID << 16) | SH7780_VENDOR_ID)) &&
-           (id != ((SH7781_DEVICE_ID << 16) | SH7780_VENDOR_ID))) {
+       if ((id & 0xffff) == SH7780_VENDOR_ID) {
+               switch ((id >> 16) & 0xffff) {
+               case SH7780_DEVICE_ID:
+               case SH7781_DEVICE_ID:
+               case SH7785_DEVICE_ID:
+                       match = 1;
+                       break;
+               }
+       }
+
+       if (unlikely(!match)) {
                printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
                return -ENODEV;
        }
 
        /* Setup the INTC */
-       ctrl_outl(0x00200000, INTC_ICR0);       /* INTC SH-4 Mode */
-       ctrl_outl(0x00078000, INTC_INT2MSKCR);  /* enable PCIINTA - PCIINTD */
-       ctrl_outl(0x40000000, INTC_INTMSK1);    /* disable IRL4-7 Interrupt */
-       ctrl_outl(0x0000fffe, INTC_INTMSK2);    /* disable IRL4-7 Interrupt */
-       ctrl_outl(0x80000000, INTC_INTMSKCLR1); /* enable IRL0-3 Interrupt */
-       ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); /* enable IRL0-3 Interrupt */
+       if (mach_is_7780se()) {
+               /* ICR0: IRL=use separately */
+               ctrl_outl(0x00C00020, INTC_ICR0);
+               /* ICR1: detect low level(for 2ndcut) */
+               ctrl_outl(0xAAAA0000, INTC_ICR1);
+               /* INTPRI: priority=3(all) */
+               ctrl_outl(0x33333333, INTC_INTPRI);
+       } else {
+               /* INTC SH-4 Mode */
+               ctrl_outl(0x00200000, INTC_ICR0);
+               /* enable PCIINTA - PCIINTD */
+               ctrl_outl(0x00078000, INTC_INT2MSKCR);
+               /* disable IRL4-7 Interrupt */
+               ctrl_outl(0x40000000, INTC_INTMSK1);
+               /* disable IRL4-7 Interrupt */
+               ctrl_outl(0x0000fffe, INTC_INTMSK2);
+               /* enable IRL0-3 Interrupt */
+               ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+               /* enable IRL0-3 Interrupt */
+               ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+       }
 
        if ((ret = sh4_pci_check_direct()) != 0)
                return ret;
@@ -138,9 +162,8 @@ int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
         * DMA interrupts...
         */
 
-#ifdef CONFIG_SH_R7780RP
+       /* Apply any last-minute PCIC fixups */
        pci_fixup_pcic();
-#endif
 
        /* SH7780 init done, set central function init complete */
        /* use round robin mode to stop a device starving/overruning */
index f02d218..00d12d0 100644 (file)
@@ -14,8 +14,9 @@
 
 /* Platform Specific Values */
 #define SH7780_VENDOR_ID       0x1912
-#define SH7780_DEVICE_ID       0x0002
 #define SH7781_DEVICE_ID       0x0001
+#define SH7780_DEVICE_ID       0x0002
+#define SH7785_DEVICE_ID       0x0007
 
 /* SH7780 Control Registers */
 #define        SH7780_PCI_VCR0         0xFE000000
 #define SH7780_PCIPMCSR_BSE    0x046
 #define SH7780_PCICDD          0x047
 
+#define SH7780_PCICR           0x100           /* PCI Control Register */
+#define SH7780_PCILSR          0x104           /* PCI Local Space Register0 */
+#define SH7780_PCILSR1         0x108           /* PCI Local Space Register1 */
+#define SH7780_PCILAR0         0x10C           /* PCI Local Address Register1 */
+#define SH7780_PCILAR1         0x110           /* PCI Local Address Register1 */
+#define SH7780_PCIIR           0x114           /* PCI Interrupt Register */
+#define SH7780_PCIIMR          0x118           /* PCI Interrupt Mask Register */
+#define SH7780_PCIAIR          0x11C           /* Error Address Register */
+#define SH7780_PCICIR          0x120           /* Error Command/Data Register */
+#define SH7780_PCIAINT         0x130           /* Arbiter Interrupt Register */
+#define SH7780_PCIAINTM                0x134           /* Arbiter Int. Mask Register */
+#define SH7780_PCIBMIR         0x138           /* Error Bus Master Register */
+#define SH7780_PCIPAR          0x1C0           /* PIO Address Register */
+#define SH7780_PCIPINT         0x1CC           /* Power Mgmnt Int. Register */
+#define SH7780_PCIPINTM                0x1D0           /* Power Mgmnt Mask Register */
+
 #define SH7780_PCIMBR0         0x1E0
 #define SH7780_PCIMBMR0                0x1E4
 #define SH7780_PCIMBR2         0x1F0
index ff30d7f..9104b62 100644 (file)
@@ -20,5 +20,6 @@ obj-$(CONFIG_SH_CPU_FREQ)     += cpufreq.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
index 3e5fa1e..0758d48 100644 (file)
@@ -29,7 +29,7 @@
  * 0xB8001000 : Common Memory
  * 0xBA000000 : I/O
  */
-#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4)
 /* SH4 can't access PCMCIA interface through P2 area.
  * we must remap it with appropreate attribute bit of the page set.
  * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
@@ -71,7 +71,7 @@ static int __init cf_init_default(void)
 /* You must have enabled the card, and set the level interrupt
  * before reaching this point. Possibly in boot ROM or boot loader.
  */
-#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4)
        allocate_cf_area();
 #endif
 #if defined(CONFIG_SH_UNKNOWN)
@@ -84,15 +84,25 @@ static int __init cf_init_default(void)
 
 #if defined(CONFIG_SH_SOLUTION_ENGINE)
 #include <asm/se.h>
+#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+#include <asm/se7722.h>
+#endif
 
 /*
- * SolutionEngine
+ * SolutionEngine Seriese
  *
+ * about MS770xSE
  * 0xB8400000 : Common Memory
  * 0xB8500000 : Attribute
  * 0xB8600000 : I/O
+ *
+ * about MS7722SE
+ * 0xB0400000 : Common Memory
+ * 0xB0500000 : Attribute
+ * 0xB0600000 : I/O
  */
 
+#if defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE) 
 static int __init cf_init_se(void)
 {
        if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
@@ -109,7 +119,7 @@ static int __init cf_init_se(void)
         *  flag == COMMON/ATTRIBUTE/IO
         */
        /* common window open */
-       ctrl_outw(0x8a84, MRSHPC_MW0CR1);/* window 0xb8400000 */
+       ctrl_outw(0x8a84, MRSHPC_MW0CR1);
        if((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
                /* common mode & bus width 16bit SWAP = 1*/
                ctrl_outw(0x0b00, MRSHPC_MW0CR2);
@@ -118,7 +128,7 @@ static int __init cf_init_se(void)
                ctrl_outw(0x0300, MRSHPC_MW0CR2); 
 
        /* attribute window open */
-       ctrl_outw(0x8a85, MRSHPC_MW1CR1);/* window 0xb8500000 */
+       ctrl_outw(0x8a85, MRSHPC_MW1CR1);
        if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
                /* attribute mode & bus width 16bit SWAP = 1*/
                ctrl_outw(0x0a00, MRSHPC_MW1CR2);
@@ -127,7 +137,7 @@ static int __init cf_init_se(void)
                ctrl_outw(0x0200, MRSHPC_MW1CR2);
 
        /* I/O window open */
-       ctrl_outw(0x8a86, MRSHPC_IOWCR1);/* I/O window 0xb8600000 */
+       ctrl_outw(0x8a86, MRSHPC_IOWCR1);
        ctrl_outw(0x0008, MRSHPC_CDCR);  /* I/O card mode */
        if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
                ctrl_outw(0x0a00, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1*/
@@ -143,10 +153,10 @@ static int __init cf_init_se(void)
 
 int __init cf_init(void)
 {
-#if defined(CONFIG_SH_SOLUTION_ENGINE)
-       if (MACH_SE)
+       if( mach_is_se() || mach_is_7722se() ){
                return cf_init_se();
-#endif
+       }
+       
        return cf_init_default();
 }
 
index abb586b..014f318 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/cpu/clock.c - SuperH clock framework
  *
- *  Copyright (C) 2005, 2006  Paul Mundt
+ *  Copyright (C) 2005, 2006, 2007  Paul Mundt
  *
  * This clock framework is derived from the OMAP version by:
  *
@@ -23,6 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
+#include <linux/proc_fs.h>
 #include <asm/clock.h>
 #include <asm/timer.h>
 
@@ -98,15 +99,17 @@ int __clk_enable(struct clk *clk)
                if (clk->ops && clk->ops->init)
                        clk->ops->init(clk);
 
+       kref_get(&clk->kref);
+
        if (clk->flags & CLK_ALWAYS_ENABLED)
                return 0;
 
        if (likely(clk->ops && clk->ops->enable))
                clk->ops->enable(clk);
 
-       kref_get(&clk->kref);
        return 0;
 }
+EXPORT_SYMBOL_GPL(__clk_enable);
 
 int clk_enable(struct clk *clk)
 {
@@ -119,6 +122,7 @@ int clk_enable(struct clk *clk)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(clk_enable);
 
 static void clk_kref_release(struct kref *kref)
 {
@@ -127,11 +131,17 @@ static void clk_kref_release(struct kref *kref)
 
 void __clk_disable(struct clk *clk)
 {
+       int count = kref_put(&clk->kref, clk_kref_release);
+
        if (clk->flags & CLK_ALWAYS_ENABLED)
                return;
 
-       kref_put(&clk->kref, clk_kref_release);
+       if (!count) {   /* count reaches zero, disable the clock */
+               if (likely(clk->ops && clk->ops->disable))
+                       clk->ops->disable(clk);
+       }
 }
+EXPORT_SYMBOL_GPL(__clk_disable);
 
 void clk_disable(struct clk *clk)
 {
@@ -141,6 +151,7 @@ void clk_disable(struct clk *clk)
        __clk_disable(clk);
        spin_unlock_irqrestore(&clock_lock, flags);
 }
+EXPORT_SYMBOL_GPL(clk_disable);
 
 int clk_register(struct clk *clk)
 {
@@ -151,8 +162,18 @@ int clk_register(struct clk *clk)
 
        mutex_unlock(&clock_list_sem);
 
+       if (clk->flags & CLK_ALWAYS_ENABLED) {
+               pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
+               if (clk->ops && clk->ops->init)
+                       clk->ops->init(clk);
+               if (clk->ops && clk->ops->enable)
+                       clk->ops->enable(clk);
+               pr_debug( "Enabled.");
+       }
+
        return 0;
 }
+EXPORT_SYMBOL_GPL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
@@ -160,13 +181,21 @@ void clk_unregister(struct clk *clk)
        list_del(&clk->node);
        mutex_unlock(&clock_list_sem);
 }
+EXPORT_SYMBOL_GPL(clk_unregister);
 
-inline unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_get_rate(struct clk *clk)
 {
        return clk->rate;
 }
+EXPORT_SYMBOL_GPL(clk_get_rate);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       return clk_set_rate_ex(clk, rate, 0);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
 {
        int ret = -EOPNOTSUPP;
 
@@ -174,7 +203,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
                unsigned long flags;
 
                spin_lock_irqsave(&clock_lock, flags);
-               ret = clk->ops->set_rate(clk, rate);
+               ret = clk->ops->set_rate(clk, rate, algo_id);
                spin_unlock_irqrestore(&clock_lock, flags);
        }
 
@@ -183,6 +212,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(clk_set_rate_ex);
 
 void clk_recalc_rate(struct clk *clk)
 {
@@ -197,6 +227,7 @@ void clk_recalc_rate(struct clk *clk)
        if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
                propagate_rate(clk);
 }
+EXPORT_SYMBOL_GPL(clk_recalc_rate);
 
 /*
  * Returns a clock. Note that we first try to use device id on the bus
@@ -233,18 +264,43 @@ found:
 
        return clk;
 }
+EXPORT_SYMBOL_GPL(clk_get);
 
 void clk_put(struct clk *clk)
 {
        if (clk && !IS_ERR(clk))
                module_put(clk->owner);
 }
+EXPORT_SYMBOL_GPL(clk_put);
 
 void __init __attribute__ ((weak))
 arch_init_clk_ops(struct clk_ops **ops, int type)
 {
 }
 
+static int show_clocks(char *buf, char **start, off_t off,
+                      int len, int *eof, void *data)
+{
+       struct clk *clk;
+       char *p = buf;
+
+       list_for_each_entry_reverse(clk, &clock_list, node) {
+               unsigned long rate = clk_get_rate(clk);
+
+               /*
+                * Don't bother listing dummy clocks with no ancestry
+                * that only support enable and disable ops.
+                */
+               if (unlikely(!rate && !clk->parent))
+                       continue;
+
+               p += sprintf(p, "%-12s\t: %ld.%02ldMHz\n", clk->name,
+                            rate / 1000000, (rate % 1000000) / 10000);
+       }
+
+       return p - buf;
+}
+
 int __init clk_init(void)
 {
        int i, ret = 0;
@@ -256,7 +312,6 @@ int __init clk_init(void)
 
                arch_init_clk_ops(&clk->ops, i);
                ret |= clk_register(clk);
-               clk_enable(clk);
        }
 
        /* Kick the child clocks.. */
@@ -266,35 +321,14 @@ int __init clk_init(void)
        return ret;
 }
 
-int show_clocks(struct seq_file *m)
+static int __init clk_proc_init(void)
 {
-       struct clk *clk;
-
-       list_for_each_entry_reverse(clk, &clock_list, node) {
-               unsigned long rate = clk_get_rate(clk);
-
-               /*
-                * Don't bother listing dummy clocks with no ancestry
-                * that only support enable and disable ops.
-                */
-               if (unlikely(!rate && !clk->parent))
-                       continue;
-
-               seq_printf(m, "%-12s\t: %ld.%02ldMHz\n", clk->name,
-                          rate / 1000000, (rate % 1000000) / 10000);
-       }
+       struct proc_dir_entry *p;
+       p = create_proc_read_entry("clocks", S_IRUSR, NULL,
+                                  show_clocks, NULL);
+       if (unlikely(!p))
+               return -EINVAL;
 
        return 0;
 }
-
-EXPORT_SYMBOL_GPL(clk_register);
-EXPORT_SYMBOL_GPL(clk_unregister);
-EXPORT_SYMBOL_GPL(clk_get);
-EXPORT_SYMBOL_GPL(clk_put);
-EXPORT_SYMBOL_GPL(clk_enable);
-EXPORT_SYMBOL_GPL(clk_disable);
-EXPORT_SYMBOL_GPL(__clk_enable);
-EXPORT_SYMBOL_GPL(__clk_disable);
-EXPORT_SYMBOL_GPL(clk_get_rate);
-EXPORT_SYMBOL_GPL(clk_set_rate);
-EXPORT_SYMBOL_GPL(clk_recalc_rate);
+subsys_initcall(clk_proc_init);
index 726acfc..6451ad6 100644 (file)
@@ -41,6 +41,23 @@ __setup("no" __stringify(x), x##_setup);
 onchip_setup(fpu);
 onchip_setup(dsp);
 
+#ifdef CONFIG_SPECULATIVE_EXECUTION
+#define CPUOPM         0xff2f0000
+#define CPUOPM_RABD    (1 << 5)
+
+static void __init speculative_execution_init(void)
+{
+       /* Clear RABD */
+       ctrl_outl(ctrl_inl(CPUOPM) & ~CPUOPM_RABD, CPUOPM);
+
+       /* Flush the update */
+       (void)ctrl_inl(CPUOPM);
+       ctrl_barrier();
+}
+#else
+#define speculative_execution_init()   do { } while (0)
+#endif
+
 /*
  * Generic first-level cache init
  */
@@ -261,4 +278,6 @@ asmlinkage void __init sh_cpu_init(void)
         */
        ubc_wakeup();
 #endif
+
+       speculative_execution_init();
 }
index 0049d21..1c23308 100644 (file)
@@ -4,6 +4,6 @@
 obj-y  += imask.o
 
 obj-$(CONFIG_CPU_HAS_IPR_IRQ)          += ipr.o
-obj-$(CONFIG_CPU_HAS_PINT_IRQ)         += pint.o
+obj-$(CONFIG_CPU_HAS_PINT_IRQ)         += pint.o 
 obj-$(CONFIG_CPU_HAS_MASKREG_IRQ)      += maskreg.o
 obj-$(CONFIG_CPU_HAS_INTC2_IRQ)                += intc2.o
index 74defe7..d8e22f4 100644 (file)
@@ -18,7 +18,8 @@
 #define INTC2_BASE     0xfe080000
 #define INTC2_INTMSK   (INTC2_BASE + 0x40)
 #define INTC2_INTMSKCLR        (INTC2_BASE + 0x60)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define INTC2_BASE     0xffd40000
 #define INTC2_INTMSK   (INTC2_BASE + 0x38)
 #define INTC2_INTMSKCLR        (INTC2_BASE + 0x3c)
index f600077..6760268 100644 (file)
 #include <asm/io.h>
 #include <asm/machvec.h>
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define INTC_INTER      0xA4000014UL
+#define INTC_IPRD       0xA4000018UL
+#define INTC_ICR2       0xA4000012UL
+
+/* PFC */
+#define PORT_PACR       0xA4000100UL
+#define PORT_PBCR       0xA4000102UL
+#define PORT_PCCR       0xA4000104UL
+#define PORT_PDCR       0xA4000106UL
+#define PORT_PECR       0xA4000108UL
+#define PORT_PFCR       0xA400010AUL
+#define PORT_PGCR       0xA400010CUL
+#define PORT_PHCR       0xA400010EUL
+#define PORT_PJCR       0xA4000110UL
+#define PORT_PKCR       0xA4000112UL
+#define PORT_PLCR       0xA4000114UL
+#define PORT_PMCR       0xA4000118UL
+#define PORT_PNCR       0xA400011AUL
+#define PORT_PECR2      0xA4050148UL
+#define PORT_PFCR2      0xA405014AUL
+#define PORT_PNCR2      0xA405015AUL
+
+/* I/O port */
+#define PORT_PADR       0xA4000120UL
+#define PORT_PBDR       0xA4000122UL
+#define PORT_PCDR       0xA4000124UL
+#define PORT_PDDR       0xA4000126UL
+#define PORT_PEDR       0xA4000128UL
+#define PORT_PFDR       0xA400012AUL
+#define PORT_PGDR       0xA400012CUL
+#define PORT_PHDR       0xA400012EUL
+#define PORT_PJDR       0xA4000130UL
+#define PORT_PKDR       0xA4000132UL
+#define PORT_PLDR       0xA4000134UL
+#define PORT_PMDR       0xA4000138UL
+#define PORT_PNDR       0xA400013AUL
+
+#define PINT0_IRQ       40
+#define PINT8_IRQ       41
+#define PINT_IRQ_BASE   86
+
+#define PINT0_IPR_ADDR          INTC_IPRD
+#define PINT0_IPR_POS           3
+#define PINT0_PRIORITY      2
+
+#define PINT8_IPR_ADDR          INTC_IPRD
+#define PINT8_IPR_POS           2
+#define PINT8_PRIORITY      2
+
+#endif /* CONFIG_CPU_SUBTYPE_SH7705 */
+
 static unsigned char pint_map[256];
 static unsigned long portcr_mask;
 
@@ -126,7 +178,7 @@ int ipr_irq_demux(int irq)
        unsigned long creg, dreg, d, sav;
 
        if (irq == PINT0_IRQ) {
-#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+#if defined(CONFIG_CPU_SUBTYPE_SH7705) || defined(CONFIG_CPU_SUBTYPE_SH7707)
                creg = PORT_PACR;
                dreg = PORT_PADR;
 #else
@@ -144,7 +196,7 @@ int ipr_irq_demux(int irq)
 
                return PINT_IRQ_BASE + pint_map[d];
        } else if (irq == PINT8_IRQ) {
-#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+#if defined(CONFIG_CPU_SUBTYPE_SH7705) || defined(CONFIG_CPU_SUBTYPE_SH7707)
                creg = PORT_PBCR;
                dreg = PORT_PBDR;
 #else
index 83905e4..09faa05 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7708)      += setup-sh7708.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh7709.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7300)       += setup-sh7300.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7712)       += setup-sh7710.o
 
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH3)                        := clock-sh3.o
index 821b0ab..647623b 100644 (file)
@@ -78,6 +78,9 @@ int __init detect_cpu_and_cache_system(void)
 #if defined(CONFIG_CPU_SUBTYPE_SH7710)
                current_cpu_data.type = CPU_SH7710;
 #endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7712)
+               current_cpu_data.type = CPU_SH7712;
+#endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
                current_cpu_data.type = CPU_SH7705;
 
index a8e41c5..1983fb7 100644 (file)
@@ -2,6 +2,7 @@
  * SH7705 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * 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
 
 static struct plat_sci_port sci_platform_data[] = {
        {
-               .mapbase        = 0xa4400000,
+               .mapbase        = 0xa4410000,
                .flags          = UPF_BOOT_AUTOCONF,
                .type           = PORT_SCIF,
-               .irqs           = { 52, 53, 55, 54 },
+               .irqs           = { 56, 57, 59 },
        }, {
-               .mapbase        = 0xa4410000,
+               .mapbase        = 0xa4400000,
                .flags          = UPF_BOOT_AUTOCONF,
                .type           = PORT_SCIF,
-               .irqs           = { 56, 57, 59, 58 },
+               .irqs           = { 52, 53, 55 },
        }, {
                .flags = 0,
        }
@@ -46,3 +47,48 @@ static int __init sh7705_devices_setup(void)
                                    ARRAY_SIZE(sh7705_devices));
 }
 __initcall(sh7705_devices_setup);
+
+static struct ipr_data sh7705_ipr_map[] = {
+       /* IRQ, IPR-idx, shift, priority */
+       { 16, 0, 12, 2 }, /* TMU0 TUNI*/
+       { 17, 0,  8, 2 }, /* TMU1 TUNI */
+       { 18, 0,  4, 2 }, /* TMU2 TUNI */
+       { 27, 1, 12, 2 }, /* WDT ITI */
+       { 20, 0,  0, 2 }, /* RTC ATI (alarm) */
+       { 21, 0,  0, 2 }, /* RTC PRI (period) */
+       { 22, 0,  0, 2 }, /* RTC CUI (carry) */
+       { 48, 4, 12, 7 }, /* DMAC DMTE0 */
+       { 49, 4, 12, 7 }, /* DMAC DMTE1 */
+       { 50, 4, 12, 7 }, /* DMAC DMTE2 */
+       { 51, 4, 12, 7 }, /* DMAC DMTE3 */
+       { 52, 4,  8, 3 }, /* SCIF0 ERI */
+       { 53, 4,  8, 3 }, /* SCIF0 RXI */
+       { 55, 4,  8, 3 }, /* SCIF0 TXI */
+       { 56, 4,  4, 3 }, /* SCIF1 ERI */
+       { 57, 4,  4, 3 }, /* SCIF1 RXI */
+       { 59, 4,  4, 3 }, /* SCIF1 TXI */
+};
+
+static unsigned long ipr_offsets[] = {
+       0xFFFFFEE2      /* 0: IPRA */
+,      0xFFFFFEE4      /* 1: IPRB */
+,      0xA4000016      /* 2: IPRC */
+,      0xA4000018      /* 3: IPRD */
+,      0xA400001A      /* 4: IPRE */
+,      0xA4080000      /* 5: IPRF */
+,      0xA4080002      /* 6: IPRG */
+,      0xA4080004      /* 7: IPRH */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (idx >= ARRAY_SIZE(ipr_offsets))
+               return 0;
+       return ipr_offsets[idx];
+}
+
+void __init init_IRQ_ipr()
+{
+       make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map));
+}
index dc9b211..c7d7c35 100644 (file)
@@ -48,24 +48,33 @@ static struct platform_device *sh7709_devices[] __initdata = {
 static int __init sh7709_devices_setup(void)
 {
        return platform_add_devices(sh7709_devices,
-                                   ARRAY_SIZE(sh7709_devices));
+               ARRAY_SIZE(sh7709_devices));
 }
 __initcall(sh7709_devices_setup);
 
-#define IPRx(A,N) .addr=A, .shift=0*N*-1
+#define IPRx(A,N)      .addr=A, .shift=N
 #define IPRA(N)        IPRx(0xfffffee2UL,N)
 #define IPRB(N)        IPRx(0xfffffee4UL,N)
+#define IPRC(N)        IPRx(0xa4000016UL,N)
+#define IPRD(N)        IPRx(0xa4000018UL,N)
 #define IPRE(N)        IPRx(0xa400001aUL,N)
 
 static struct ipr_data sh7709_ipr_map[] = {
-       [16]            = { IPRA(15-12), 2 }, /* TMU TUNI0 */
-       [17]            = { IPRA(11-8),  4 }, /* TMU TUNI1 */
-       [22]            = { IPRA(3-0),   2 }, /* RTC CUI */
-       [23 ... 26]     = { IPRB(7-4),   3 }, /* SCI */
-       [27]            = { IPRB(15-12), 2 }, /* WDT ITI */
-       [48 ... 51]     = { IPRE(15-12), 7 }, /* DMA */
-       [52 ... 55]     = { IPRE(11-8),  3 }, /* IRDA */
-       [56 ... 59]     = { IPRE(7-4),   3 }, /* SCIF */
+       [16]            = { IPRA(12), 2 }, /* TMU TUNI0 */
+       [17]            = { IPRA(8),  4 }, /* TMU TUNI1 */
+       [18 ... 19]     = { IPRA(4),  1 }, /* TMU TUNI1 */
+       [20 ... 22]     = { IPRA(0),  2 }, /* RTC CUI */
+       [23 ... 26]     = { IPRB(4),  3 }, /* SCI */
+       [27]            = { IPRB(12), 2 }, /* WDT ITI */
+       [32]            = { IPRC(0),  1 }, /* IRQ 0 */
+       [33]            = { IPRC(4),  1 }, /* IRQ 1 */
+       [34]            = { IPRC(8),  1 }, /* IRQ 2 APM */
+       [35]            = { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */
+       [36]            = { IPRD(0),  1 }, /* IRQ 4 */
+       [37]            = { IPRD(4),  1 }, /* IRQ 5 */
+       [48 ... 51]     = { IPRE(12), 7 }, /* DMA */
+       [52 ... 55]     = { IPRE(8),  3 }, /* IRDA */
+       [56 ... 59]     = { IPRE(4),  3 }, /* SCIF */
 };
 
 void __init init_IRQ_ipr()
index 895f99e..51760a7 100644 (file)
@@ -2,6 +2,7 @@
  * SH7710 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * 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
@@ -19,6 +20,12 @@ static struct plat_sci_port sci_platform_data[] = {
                .type           = PORT_SCIF,
                .irqs           = { 52, 53, 55, 54 },
        }, {
+               .mapbase        = 0xa4420000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 56, 57, 59, 58 },
+       }, {
+
                .flags = 0,
        }
 };
@@ -41,3 +48,56 @@ static int __init sh7710_devices_setup(void)
                                    ARRAY_SIZE(sh7710_devices));
 }
 __initcall(sh7710_devices_setup);
+
+static struct ipr_data sh7710_ipr_map[] = {
+       /* IRQ, IPR-idx, shift, priority */
+       { 16, 0, 12, 2 }, /* TMU0 TUNI*/
+       { 17, 0,  8, 2 }, /* TMU1 TUNI */
+       { 18, 0,  4, 2 }, /* TMU2 TUNI */
+       { 27, 1, 12, 2 }, /* WDT ITI */
+       { 20, 0,  0, 2 }, /* RTC ATI (alarm) */
+       { 21, 0,  0, 2 }, /* RTC PRI (period) */
+       { 22, 0,  0, 2 }, /* RTC CUI (carry) */
+       { 48, 4, 12, 7 }, /* DMAC DMTE0 */
+       { 49, 4, 12, 7 }, /* DMAC DMTE1 */
+       { 50, 4, 12, 7 }, /* DMAC DMTE2 */
+       { 51, 4, 12, 7 }, /* DMAC DMTE3 */
+       { 52, 4,  8, 3 }, /* SCIF0 ERI */
+       { 53, 4,  8, 3 }, /* SCIF0 RXI */
+       { 54, 4,  8, 3 }, /* SCIF0 BRI */
+       { 55, 4,  8, 3 }, /* SCIF0 TXI */
+       { 56, 4,  4, 3 }, /* SCIF1 ERI */
+       { 57, 4,  4, 3 }, /* SCIF1 RXI */
+       { 58, 4,  4, 3 }, /* SCIF1 BRI */
+       { 59, 4,  4, 3 }, /* SCIF1 TXI */
+       { 76, 5,  8, 7 }, /* DMAC DMTE4 */
+       { 77, 5,  8, 7 }, /* DMAC DMTE5 */
+       { 80, 6, 12, 5 }, /* EDMAC EINT0 */
+       { 81, 6,  8, 5 }, /* EDMAC EINT1 */
+       { 82, 6,  4, 5 }, /* EDMAC EINT2 */
+};
+
+static unsigned long ipr_offsets[] = {
+       0xA414FEE2      /* 0: IPRA */
+,      0xA414FEE4      /* 1: IPRB */
+,      0xA4140016      /* 2: IPRC */
+,      0xA4140018      /* 3: IPRD */
+,      0xA414001A      /* 4: IPRE */
+,      0xA4080000      /* 5: IPRF */
+,      0xA4080002      /* 6: IPRG */
+,      0xA4080004      /* 7: IPRH */
+,      0xA4080006      /* 8: IPRI */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (idx >= ARRAY_SIZE(ipr_offsets))
+               return 0;
+       return ipr_offsets[idx];
+}
+
+void __init init_IRQ_ipr()
+{
+       make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map));
+}
index fa2019a..fcb2c41 100644 (file)
@@ -82,7 +82,8 @@ static void shoc_clk_init(struct clk *clk)
        for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
                int divisor = frqcr3_divisors[i];
 
-               if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
+               if (clk->ops->set_rate(clk, clk->parent->rate /
+                                               divisor, 0) == 0)
                        break;
        }
 
index 58950de..8cd0490 100644 (file)
@@ -124,6 +124,14 @@ int __init detect_cpu_and_cache_system(void)
                current_cpu_data.dcache.ways = 4;
                current_cpu_data.flags |= CPU_HAS_LLSC;
                break;
+       case 0x3004:
+       case 0x3007:
+               current_cpu_data.type = CPU_SH7785;
+               current_cpu_data.icache.ways = 4;
+               current_cpu_data.dcache.ways = 4;
+               current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+                                         CPU_HAS_LLSC;
+               break;
        case 0x3008:
                if (prr == 0xa0) {
                        current_cpu_data.type = CPU_SH7722;
index a8f493f..ab7422f 100644 (file)
@@ -5,6 +5,7 @@
 # CPU subtype setup
 obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7785)       += setup-sh7785.o
 obj-$(CONFIG_CPU_SUBTYPE_SH73180)      += setup-sh73180.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o
@@ -13,7 +14,8 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7722)      += setup-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH73180)    := clock-sh73180.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7770)     := clock-sh7770.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7780)     := clock-sh7780.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7785)     := clock-sh7785.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7343)     := clock-sh7343.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7722)     := clock-sh7343.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722)     := clock-sh7722.o
 
 obj-y  += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
new file mode 100644 (file)
index 0000000..2909003
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+ *
+ * SH7722 support for the clock framework
+ *
+ * Copyright (c) 2006-2007 Nomad Global Solutions Inc
+ * Based on code for sh7343 by Paul Mundt
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+#define SH7722_PLL_FREQ (32000000/8)
+#define N  (-1)
+#define NM (-2)
+#define ROUND_NEAREST 0
+#define ROUND_DOWN -1
+#define ROUND_UP   +1
+
+static int adjust_algos[][3] = {
+       {},     /* NO_CHANGE */
+       { NM, N, 1 },   /* N:1, N:1 */
+       { 3, 2, 2 },    /* 3:2:2 */
+       { 5, 2, 2 },    /* 5:2:2 */
+       { N, 1, 1 },    /* N:1:1 */
+
+       { N, 1 },       /* N:1 */
+
+       { N, 1 },       /* N:1 */
+       { 3, 2 },
+       { 4, 3 },
+       { 5, 4 },
+
+       { N, 1 }
+};
+
+static unsigned long adjust_pair_of_clocks(unsigned long r1, unsigned long r2,
+                       int m1, int m2, int round_flag)
+{
+       unsigned long rem, div;
+       int the_one = 0;
+
+       pr_debug( "Actual values: r1 = %ld\n", r1);
+       pr_debug( "...............r2 = %ld\n", r2);
+
+       if (m1 == m2) {
+               r2 = r1;
+               pr_debug( "setting equal rates: r2 now %ld\n", r2);
+       } else if ((m2 == N  && m1 == 1) ||
+                  (m2 == NM && m1 == N)) { /* N:1 or NM:N */
+               pr_debug( "Setting rates as 1:N (N:N*M)\n");
+               rem = r2 % r1;
+               pr_debug( "...remainder = %ld\n", rem);
+               if (rem) {
+                       div = r2 / r1;
+                       pr_debug( "...div = %ld\n", div);
+                       switch (round_flag) {
+                       case ROUND_NEAREST:
+                               the_one = rem >= r1/2 ? 1 : 0; break;
+                       case ROUND_UP:
+                               the_one = 1; break;
+                       case ROUND_DOWN:
+                               the_one = 0; break;
+                       }
+
+                       r2 = r1 * (div + the_one);
+                       pr_debug( "...setting r2 to %ld\n", r2);
+               }
+       } else if ((m2 == 1  && m1 == N) ||
+                  (m2 == N && m1 == NM)) { /* 1:N or N:NM */
+               pr_debug( "Setting rates as N:1 (N*M:N)\n");
+               rem = r1 % r2;
+               pr_debug( "...remainder = %ld\n", rem);
+               if (rem) {
+                       div = r1 / r2;
+                       pr_debug( "...div = %ld\n", div);
+                       switch (round_flag) {
+                       case ROUND_NEAREST:
+                               the_one = rem > r2/2 ? 1 : 0; break;
+                       case ROUND_UP:
+                               the_one = 0; break;
+                       case ROUND_DOWN:
+                               the_one = 1; break;
+                       }
+
+                       r2 = r1 / (div + the_one);
+                       pr_debug( "...setting r2 to %ld\n", r2);
+               }
+       } else { /* value:value */
+               pr_debug( "Setting rates as %d:%d\n", m1, m2);
+               div = r1 / m1;
+               r2 = div * m2;
+               pr_debug( "...div = %ld\n", div);
+               pr_debug( "...setting r2 to %ld\n", r2);
+       }
+
+       return r2;
+}
+
+static void adjust_clocks(int originate, int *l, unsigned long v[],
+                         int n_in_line)
+{
+       int x;
+
+       pr_debug( "Go down from %d...\n", originate);
+       /* go up recalculation clocks */
+       for (x = originate; x>0; x -- )
+               v[x-1] = adjust_pair_of_clocks(v[x], v[x-1],
+                                       l[x], l[x-1],
+                                       ROUND_UP);
+
+       pr_debug( "Go up from %d...\n", originate);
+       /* go down recalculation clocks */
+       for (x = originate; x<n_in_line - 1; x ++ )
+               v[x+1] = adjust_pair_of_clocks(v[x], v[x+1],
+                                       l[x], l[x+1],
+                                       ROUND_UP);
+}
+
+
+/*
+ * SH7722 uses a common set of multipliers and divisors, so this
+ * is quite simple..
+ */
+
+/*
+ * Instead of having two separate multipliers/divisors set, like this:
+ *
+ * static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+ * static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+ *
+ * I created the divisors2 array, which is used to calculate rate like
+ *   rate = parent * 2 / divisors2[ divisor ];
+*/
+static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };
+
+static void master_clk_init(struct clk *clk)
+{
+       clk_set_rate(clk, clk_get_rate(clk));
+}
+
+static void master_clk_recalc(struct clk *clk)
+{
+       unsigned long frqcr = ctrl_inl(FRQCR);
+
+       clk->rate = CONFIG_SH_PCLK_FREQ * (1 + (frqcr >> 24 & 0xF));
+}
+
+static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
+{
+       int div = rate / SH7722_PLL_FREQ;
+       int master_divs[] = { 2, 3, 4, 6, 8, 16 };
+       int index;
+       unsigned long frqcr;
+
+       if (rate < SH7722_PLL_FREQ * 2)
+               return -EINVAL;
+
+       for (index = 1; index < ARRAY_SIZE(master_divs); index++)
+               if (div >= master_divs[index - 1] && div < master_divs[index])
+                       break;
+
+       if (index >= ARRAY_SIZE(master_divs))
+               index = ARRAY_SIZE(master_divs);
+       div = master_divs[index - 1];
+
+       frqcr = ctrl_inl(FRQCR);
+       frqcr &= ~(0xF << 24);
+       frqcr |= ( (div-1) << 24);
+       ctrl_outl(frqcr, FRQCR);
+
+       return 0;
+}
+
+static struct clk_ops sh7722_master_clk_ops = {
+       .init = master_clk_init,
+       .recalc = master_clk_recalc,
+       .set_rate = master_clk_setrate,
+};
+
+struct frqcr_context {
+       unsigned mask;
+       unsigned shift;
+};
+
+struct frqcr_context sh7722_get_clk_context(const char *name)
+{
+       struct frqcr_context ctx = { 0, };
+
+       if (!strcmp(name, "peripheral_clk")) {
+               ctx.shift = 0;
+               ctx.mask = 0xF;
+       } else if (!strcmp(name, "sdram_clk")) {
+               ctx.shift = 4;
+               ctx.mask = 0xF;
+       } else if (!strcmp(name, "bus_clk")) {
+               ctx.shift = 8;
+               ctx.mask = 0xF;
+       } else if (!strcmp(name, "sh_clk")) {
+               ctx.shift = 12;
+               ctx.mask = 0xF;
+       } else if (!strcmp(name, "umem_clk")) {
+               ctx.shift = 16;
+               ctx.mask = 0xF;
+       } else if (!strcmp(name, "cpu_clk")) {
+               ctx.shift = 20;
+               ctx.mask = 7;
+       }
+       return ctx;
+}
+
+/**
+ * sh7722_find_divisors - find divisor for setting rate
+ *
+ * All sh7722 clocks use the same set of multipliers/divisors. This function
+ * chooses correct divisor to set the rate of clock with parent clock that
+ * generates frequency of 'parent_rate'
+ *
+ * @parent_rate: rate of parent clock
+ * @rate: requested rate to be set
+ */
+static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate)
+{
+       unsigned div2 = parent_rate * 2 / rate;
+       int index;
+
+       if (rate > parent_rate)
+               return -EINVAL;
+
+       for (index = 1; index < ARRAY_SIZE(divisors2); index++) {
+               if (div2 > divisors2[index] && div2 <= divisors2[index])
+                       break;
+       }
+       if (index >= ARRAY_SIZE(divisors2))
+               index = ARRAY_SIZE(divisors2) - 1;
+       return divisors2[index];
+}
+
+static void sh7722_frqcr_recalc(struct clk *clk)
+{
+       struct frqcr_context ctx = sh7722_get_clk_context(clk->name);
+       unsigned long frqcr = ctrl_inl(FRQCR);
+       int index;
+
+       index = (frqcr >> ctx.shift) & ctx.mask;
+       clk->rate = clk->parent->rate * 2 / divisors2[index];
+}
+
+static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate,
+                                int algo_id)
+{
+       struct frqcr_context ctx = sh7722_get_clk_context(clk->name);
+       unsigned long parent_rate = clk->parent->rate;
+       int div;
+       unsigned long frqcr;
+       int err = 0;
+
+       /* pretty invalid */
+       if (parent_rate < rate)
+               return -EINVAL;
+
+       /* look for multiplier/divisor pair */
+       div = sh7722_find_divisors(parent_rate, rate);
+       if (div<0)
+               return div;
+
+       /* calculate new value of clock rate */
+       clk->rate = parent_rate * 2 / div;
+       frqcr = ctrl_inl(FRQCR);
+
+       /* FIXME: adjust as algo_id specifies */
+       if (algo_id != NO_CHANGE) {
+               int originator;
+               char *algo_group_1[] = { "cpu_clk", "umem_clk", "sh_clk" };
+               char *algo_group_2[] = { "sh_clk", "bus_clk" };
+               char *algo_group_3[] = { "sh_clk", "sdram_clk" };
+               char *algo_group_4[] = { "bus_clk", "peripheral_clk" };
+               char *algo_group_5[] = { "cpu_clk", "peripheral_clk" };
+               char **algo_current = NULL;
+               /* 3 is the maximum number of clocks in relation */
+               struct clk *ck[3];
+               unsigned long values[3]; /* the same comment as above */
+               int part_length = -1;
+               int i;
+
+               /*
+                * all the steps below only required if adjustion was
+                * requested
+                */
+               if (algo_id == IUS_N1_N1 ||
+                   algo_id == IUS_322 ||
+                   algo_id == IUS_522 ||
+                   algo_id == IUS_N11) {
+                       algo_current = algo_group_1;
+                       part_length = 3;
+               }
+               if (algo_id == SB_N1) {
+                       algo_current = algo_group_2;
+                       part_length = 2;
+               }
+               if (algo_id == SB3_N1 ||
+                   algo_id == SB3_32 ||
+                   algo_id == SB3_43 ||
+                   algo_id == SB3_54) {
+                       algo_current = algo_group_3;
+                       part_length = 2;
+               }
+               if (algo_id == BP_N1) {
+                       algo_current = algo_group_4;
+                       part_length = 2;
+               }
+               if (algo_id == IP_N1) {
+                       algo_current = algo_group_5;
+                       part_length = 2;
+               }
+               if (!algo_current)
+                       goto incorrect_algo_id;
+
+               originator = -1;
+               for (i = 0; i < part_length; i ++ ) {
+                       if (originator >= 0 && !strcmp(clk->name,
+                                                      algo_current[i]))
+                               originator = i;
+                       ck[i] = clk_get(NULL, algo_current[i]);
+                       values[i] = clk_get_rate(ck[i]);
+               }
+
+               if (originator >= 0)
+                       adjust_clocks(originator, adjust_algos[algo_id],
+                                     values, part_length);
+
+               for (i = 0; i < part_length; i ++ ) {
+                       struct frqcr_context part_ctx;
+                       int part_div;
+
+                       if (likely(!err)) {
+                               part_div = sh7722_find_divisors(parent_rate,
+                                                               rate);
+                               if (part_div > 0) {
+                                       part_ctx = sh7722_get_clk_context(
+                                                               ck[i]->name);
+                                       frqcr &= ~(part_ctx.mask <<
+                                                  part_ctx.shift);
+                                       frqcr |= part_div << part_ctx.shift;
+                               } else
+                                       err = part_div;
+                       }
+
+                       ck[i]->ops->recalc(ck[i]);
+                       clk_put(ck[i]);
+               }
+       }
+
+       /* was there any error during recalculation ? If so, bail out.. */
+       if (unlikely(err!=0))
+               goto out_err;
+
+       /* clear FRQCR bits */
+       frqcr &= ~(ctx.mask << ctx.shift);
+       frqcr |= div << ctx.shift;
+
+       /* ...and perform actual change */
+       ctrl_outl(frqcr, FRQCR);
+       return 0;
+
+incorrect_algo_id:
+       return -EINVAL;
+out_err:
+       return err;
+}
+
+static struct clk_ops sh7722_frqcr_clk_ops = {
+       .recalc = sh7722_frqcr_recalc,
+       .set_rate = sh7722_frqcr_set_rate,
+};
+
+/*
+ * clock ops methods for SIU A/B and IrDA clock
+ *
+ */
+static int sh7722_siu_which(struct clk *clk)
+{
+       if (!strcmp(clk->name, "siu_a_clk"))
+               return 0;
+       if (!strcmp(clk->name, "siu_b_clk"))
+               return 1;
+       if (!strcmp(clk->name, "irda_clk"))
+               return 2;
+       return -EINVAL;
+}
+
+static unsigned long sh7722_siu_regs[] = {
+       [0] = SCLKACR,
+       [1] = SCLKBCR,
+       [2] = IrDACLKCR,
+};
+
+static int sh7722_siu_start_stop(struct clk *clk, int enable)
+{
+       int siu = sh7722_siu_which(clk);
+       unsigned long r;
+
+       if (siu < 0)
+               return siu;
+       BUG_ON(siu > 2);
+       r = ctrl_inl(sh7722_siu_regs[siu]);
+       if (enable)
+               ctrl_outl(r & ~(1 << 8), sh7722_siu_regs[siu]);
+       else
+               ctrl_outl(r | (1 << 8), sh7722_siu_regs[siu]);
+       return 0;
+}
+
+static void sh7722_siu_enable(struct clk *clk)
+{
+       sh7722_siu_start_stop(clk, 1);
+}
+
+static void sh7722_siu_disable(struct clk *clk)
+{
+       sh7722_siu_start_stop(clk, 0);
+}
+
+static void sh7722_video_enable(struct clk *clk)
+{
+       unsigned long r;
+
+       r = ctrl_inl(VCLKCR);
+       ctrl_outl( r & ~(1<<8), VCLKCR);
+}
+
+static void sh7722_video_disable(struct clk *clk)
+{
+       unsigned long r;
+
+       r = ctrl_inl(VCLKCR);
+       ctrl_outl( r | (1<<8), VCLKCR);
+}
+
+static int sh7722_video_set_rate(struct clk *clk, unsigned long rate,
+                                int algo_id)
+{
+       unsigned long r;
+
+       r = ctrl_inl(VCLKCR);
+       r &= ~0x3F;
+       r |= ((clk->parent->rate / rate - 1) & 0x3F);
+       ctrl_outl(r, VCLKCR);
+       return 0;
+}
+
+static void sh7722_video_recalc(struct clk *clk)
+{
+       unsigned long r;
+
+       r = ctrl_inl(VCLKCR);
+       clk->rate = clk->parent->rate / ((r & 0x3F) + 1);
+}
+
+static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+{
+       int siu = sh7722_siu_which(clk);
+       unsigned long r;
+       int div;
+
+       if (siu < 0)
+               return siu;
+       BUG_ON(siu > 2);
+       r = ctrl_inl(sh7722_siu_regs[siu]);
+       div = sh7722_find_divisors(clk->parent->rate, rate);
+       if (div < 0)
+               return div;
+       r = (r & ~0xF) | div;
+       ctrl_outl(r, sh7722_siu_regs[siu]);
+       return 0;
+}
+
+static void sh7722_siu_recalc(struct clk *clk)
+{
+       int siu = sh7722_siu_which(clk);
+       unsigned long r;
+
+       if (siu < 0)
+               return /* siu */ ;
+       BUG_ON(siu > 1);
+       r = ctrl_inl(sh7722_siu_regs[siu]);
+       clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
+}
+
+static struct clk_ops sh7722_siu_clk_ops = {
+       .recalc = sh7722_siu_recalc,
+       .set_rate = sh7722_siu_set_rate,
+       .enable = sh7722_siu_enable,
+       .disable = sh7722_siu_disable,
+};
+
+static struct clk_ops sh7722_video_clk_ops = {
+       .recalc = sh7722_video_recalc,
+       .set_rate = sh7722_video_set_rate,
+       .enable = sh7722_video_enable,
+       .disable = sh7722_video_disable,
+};
+/*
+ * and at last, clock definitions themselves
+ */
+static struct clk sh7722_umem_clock = {
+       .name = "umem_clk",
+       .ops = &sh7722_frqcr_clk_ops,
+};
+
+static struct clk sh7722_sh_clock = {
+       .name = "sh_clk",
+       .ops = &sh7722_frqcr_clk_ops,
+};
+
+static struct clk sh7722_peripheral_clock = {
+       .name = "peripheral_clk",
+       .ops = &sh7722_frqcr_clk_ops,
+};
+
+static struct clk sh7722_sdram_clock = {
+       .name = "sdram_clk",
+       .ops = &sh7722_frqcr_clk_ops,
+};
+
+/*
+ * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops
+ * methods of clk_ops determine which register they should access by
+ * examining clk->name field
+ */
+static struct clk sh7722_siu_a_clock = {
+       .name = "siu_a_clk",
+       .ops = &sh7722_siu_clk_ops,
+};
+
+static struct clk sh7722_siu_b_clock = {
+       .name = "siu_b_clk",
+       .ops = &sh7722_siu_clk_ops,
+};
+
+static struct clk sh7722_irda_clock = {
+       .name = "irda_clk",
+       .ops = &sh7722_siu_clk_ops,
+};
+
+static struct clk sh7722_video_clock = {
+       .name = "video_clk",
+       .ops = &sh7722_video_clk_ops,
+};
+
+static struct clk *sh7722_clocks[] = {
+       &sh7722_umem_clock,
+       &sh7722_sh_clock,
+       &sh7722_peripheral_clock,
+       &sh7722_sdram_clock,
+       &sh7722_siu_a_clock,
+       &sh7722_siu_b_clock,
+       &sh7722_irda_clock,
+       &sh7722_video_clock,
+};
+
+/*
+ * init in order: master, module, bus, cpu
+ */
+struct clk_ops *onchip_ops[] = {
+       &sh7722_master_clk_ops,
+       &sh7722_frqcr_clk_ops,
+       &sh7722_frqcr_clk_ops,
+       &sh7722_frqcr_clk_ops,
+};
+
+void __init
+arch_init_clk_ops(struct clk_ops **ops, int type)
+{
+       BUG_ON(type < 0 || type > ARRAY_SIZE(onchip_ops));
+       *ops = onchip_ops[type];
+}
+
+int __init sh7722_clock_init(void)
+{
+       struct clk *master;
+       int i;
+
+       master = clk_get(NULL, "master_clk");
+       for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) {
+               pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name);
+               sh7722_clocks[i]->parent = master;
+               clk_register(sh7722_clocks[i]);
+       }
+       clk_put(master);
+       return 0;
+}
+arch_initcall(sh7722_clock_init);
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
new file mode 100644 (file)
index 0000000..805535a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+ *
+ * SH7785 support for the clock framework
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 2, 4, 6 };
+static int ufc_divisors[] = { 1, 1, 4, 6 };
+static int sfc_divisors[] = { 1, 1, 4, 6 };
+static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18,
+                            24, 32, 36, 48, 1, 1, 1, 1 };
+static int mfc_divisors[] = { 1, 1, 4, 6 };
+static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18,
+                             24, 32, 36, 48, 1, 1, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+       clk->rate *= 36;
+}
+
+static struct clk_ops sh7785_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQMR1) & 0x000f);
+       clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7785_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
+       clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops sh7785_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
+       clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7785_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7785_clk_ops[] = {
+       &sh7785_master_clk_ops,
+       &sh7785_module_clk_ops,
+       &sh7785_bus_clk_ops,
+       &sh7785_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7785_clk_ops))
+               *ops = sh7785_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+       int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
+       clk->rate = clk->parent->rate / sfc_divisors[idx];
+}
+
+static struct clk_ops sh7785_shyway_clk_ops = {
+       .recalc         = shyway_clk_recalc,
+};
+
+static struct clk sh7785_shyway_clk = {
+       .name           = "shyway_clk",
+       .flags          = CLK_ALWAYS_ENABLED,
+       .ops            = &sh7785_shyway_clk_ops,
+};
+
+static void ddr_clk_recalc(struct clk *clk)
+{
+       int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
+       clk->rate = clk->parent->rate / mfc_divisors[idx];
+}
+
+static struct clk_ops sh7785_ddr_clk_ops = {
+       .recalc         = ddr_clk_recalc,
+};
+
+static struct clk sh7785_ddr_clk = {
+       .name           = "ddr_clk",
+       .flags          = CLK_ALWAYS_ENABLED,
+       .ops            = &sh7785_ddr_clk_ops,
+};
+
+static void ram_clk_recalc(struct clk *clk)
+{
+       int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003);
+       clk->rate = clk->parent->rate / ufc_divisors[idx];
+}
+
+static struct clk_ops sh7785_ram_clk_ops = {
+       .recalc         = ram_clk_recalc,
+};
+
+static struct clk sh7785_ram_clk = {
+       .name           = "ram_clk",
+       .flags          = CLK_ALWAYS_ENABLED,
+       .ops            = &sh7785_ram_clk_ops,
+};
+
+/*
+ * Additional SH7785-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *sh7785_onchip_clocks[] = {
+       &sh7785_shyway_clk,
+       &sh7785_ddr_clk,
+       &sh7785_ram_clk,
+};
+
+static int __init sh7785_clk_init(void)
+{
+       struct clk *clk = clk_get(NULL, "master_clk");
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) {
+               struct clk *clkp = sh7785_onchip_clocks[i];
+
+               clkp->parent = clk;
+               clk_register(clkp);
+               clk_enable(clkp);
+       }
+
+       /*
+        * Now that we have the rest of the clocks registered, we need to
+        * force the parent clock to propagate so that these clocks will
+        * automatically figure out their rate. We cheat by handing the
+        * parent clock its current rate and forcing child propagation.
+        */
+       clk_set_rate(clk, clk_get_rate(clk));
+
+       clk_put(clk);
+
+       return 0;
+}
+arch_initcall(sh7785_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
new file mode 100644 (file)
index 0000000..07b0de8
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * SH7785 Setup
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffea0000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .mapbase        = 0xffeb0000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 44, 45, 47, 46 },
+       },
+
+       /*
+        * The rest of these all have multiplexed IRQs
+        */
+       {
+               .mapbase        = 0xffec0000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 60, 60, 60, 60 },
+       }, {
+               .mapbase        = 0xffed0000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 61, 61, 61, 61 },
+       }, {
+               .mapbase        = 0xffee0000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 62, 62, 62, 62 },
+       }, {
+               .mapbase        = 0xffef0000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 63, 63, 63, 63 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7785_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7785_devices_setup(void)
+{
+       return platform_add_devices(sh7785_devices,
+                                   ARRAY_SIZE(sh7785_devices));
+}
+__initcall(sh7785_devices_setup);
+
+static struct intc2_data intc2_irq_table[] = {
+       { 28, 0, 24, 0, 0, 2 },         /* TMU0 */
+
+       { 40, 8, 24, 0, 2, 3 },         /* SCIF0 ERI */
+       { 41, 8, 24, 0, 2, 3 },         /* SCIF0 RXI */
+       { 42, 8, 24, 0, 2, 3 },         /* SCIF0 BRI */
+       { 43, 8, 24, 0, 2, 3 },         /* SCIF0 TXI */
+
+       { 44, 8, 16, 0, 3, 3 },         /* SCIF1 ERI */
+       { 45, 8, 16, 0, 3, 3 },         /* SCIF1 RXI */
+       { 46, 8, 16, 0, 3, 3 },         /* SCIF1 BRI */
+       { 47, 8, 16, 0, 3, 3 },         /* SCIF1 TXI */
+
+       { 64, 0x14,  8, 0, 14, 2 },     /* PCIC0 */
+       { 65, 0x14,  0, 0, 15, 2 },     /* PCIC1 */
+       { 66, 0x18, 24, 0, 16, 2 },     /* PCIC2 */
+       { 67, 0x18, 16, 0, 17, 2 },     /* PCIC3 */
+       { 68, 0x18,  8, 0, 18, 2 },     /* PCIC4 */
+
+       { 60,  8,  8, 0, 4, 3 },        /* SCIF2 ERI, RXI, BRI, TXI */
+       { 60,  8,  0, 0, 5, 3 },        /* SCIF3 ERI, RXI, BRI, TXI */
+       { 60, 12, 24, 0, 6, 3 },        /* SCIF4 ERI, RXI, BRI, TXI */
+       { 60, 12, 16, 0, 7, 3 },        /* SCIF5 ERI, RXI, BRI, TXI */
+};
+
+void __init init_IRQ_intc2(void)
+{
+       make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+}
diff --git a/arch/sh/kernel/crash_dump.c b/arch/sh/kernel/crash_dump.c
new file mode 100644 (file)
index 0000000..4a2ecbe
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *     crash_dump.c - Memory preserving reboot related code.
+ *
+ *     Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *     Copyright (C) IBM Corporation, 2004. All rights reserved
+ */
+
+#include <linux/errno.h>
+#include <linux/crash_dump.h>
+#include <linux/io.h>
+#include <asm/uaccess.h>
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ *     space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ *     otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+                               size_t csize, unsigned long offset, int userbuf)
+{
+       void  *vaddr;
+
+       if (!csize)
+               return 0;
+
+       vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+
+       if (userbuf) {
+               if (copy_to_user(buf, (vaddr + offset), csize)) {
+                       iounmap(vaddr);
+                       return -EFAULT;
+               }
+       } else
+       memcpy(buf, (vaddr + offset), csize);
+
+       iounmap(vaddr);
+       return csize;
+}
index 9bdd8a0..27b923c 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <asm/processor.h>
+#include <asm/machvec.h>
 #include <asm/uaccess.h>
 #include <asm/thread_info.h>
 #include <asm/cpu/mmu_context.h>
@@ -44,7 +45,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_putc(p, '\n');
        }
 
-       if (i < NR_IRQS) {
+       if (i < sh_mv.mv_nr_irqs) {
                spin_lock_irqsave(&irq_desc[i].lock, flags);
                action = irq_desc[i].action;
                if (!action)
@@ -61,7 +62,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_putc(p, '\n');
 unlock:
                spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS)
+       } else if (i == sh_mv.mv_nr_irqs)
                seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
 
        return 0;
index d8927d8..a532336 100644 (file)
@@ -6,11 +6,11 @@
  * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
  * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
  * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
- * 
+ *
  * This version by Henry Bell <henry.bell@st.com>
  * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
- * 
- * Contains low-level support for remote debug using GDB. 
+ *
+ * Contains low-level support for remote debug using GDB.
  *
  * To enable debugger support, two things need to happen. A call to
  * set_debug_traps() is necessary in order to allow any breakpoints
@@ -48,7 +48,7 @@
  *    k             kill (Detach GDB)
  *
  *    d             Toggle debug flag
- *    D             Detach GDB 
+ *    D             Detach GDB
  *
  *    Hct           Set thread t for operations,           OK or ENN
  *                  c = 'c' (step, cont), c = 'g' (other
@@ -58,7 +58,7 @@
  *    qfThreadInfo  Get list of current threads (first)    m<id>
  *    qsThreadInfo   "    "  "     "      "   (subsequent)
  *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
- * 
+ *
  *    TXX           Find if thread XX is alive             OK or ENN
  *    ?             What was the last sigval ?             SNN   (signal NN)
  *    O             Output to GDB console
@@ -74,7 +74,7 @@
  *       '$' or '#'.  If <data> starts with two characters followed by
  *       ':', then the existing stubs interpret this as a sequence number.
  *
- *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
+ *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
  *       checksum of <data>, the most significant nibble is sent first.
  *       the hex digits 0-9,a-f are used.
  *
@@ -86,8 +86,8 @@
  * Responses can be run-length encoded to save space.  A '*' means that
  * the next character is an ASCII encoding giving a repeat count which
  * stands for that many repititions of the character preceding the '*'.
- * The encoding is n+29, yielding a printable character where n >=3 
- * (which is where RLE starts to win).  Don't use an n > 126. 
+ * The encoding is n+29, yielding a printable character where n >=3
+ * (which is where RLE starts to win).  Don't use an n > 126.
  *
  * So "0* " means the same as "0000".
  */
 #include <linux/delay.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
-
-#ifdef CONFIG_SH_KGDB_CONSOLE
 #include <linux/console.h>
-#endif
-
+#include <linux/sysrq.h>
 #include <asm/system.h>
+#include <asm/cacheflush.h>
 #include <asm/current.h>
 #include <asm/signal.h>
 #include <asm/pgtable.h>
@@ -153,7 +151,6 @@ char kgdb_in_gdb_mode;
 char in_nmi;                   /* Set during NMI to prevent reentry */
 int kgdb_nofault;              /* Boolean to ignore bus errs (i.e. in GDB) */
 int kgdb_enabled = 1;          /* Default to enabled, cmdline can disable */
-int kgdb_halt;
 
 /* Exposed for user access */
 struct task_struct *kgdb_current;
@@ -246,14 +243,6 @@ static char out_buffer[OUTBUFMAX];
 
 static void kgdb_to_gdb(const char *s);
 
-#ifdef CONFIG_KGDB_THREAD
-static struct task_struct *trapped_thread;
-static struct task_struct *current_thread;
-typedef unsigned char threadref[8];
-#define BUF_THREAD_ID_SIZE 16
-#endif
-
-
 /* Convert ch to hex */
 static int hex(const char ch)
 {
@@ -328,7 +317,7 @@ static int hex_to_int(char **ptr, int *int_value)
 }
 
 /*  Copy the binary array pointed to by buf into mem.  Fix $, #,
-    and 0x7d escaped with 0x7d.  Return a pointer to the character 
+    and 0x7d escaped with 0x7d.  Return a pointer to the character
     after the last byte written. */
 static char *ebin_to_mem(const char *buf, char *mem, int count)
 {
@@ -349,66 +338,6 @@ static char *pack_hex_byte(char *pkt, int byte)
        return pkt;
 }
 
-#ifdef CONFIG_KGDB_THREAD
-
-/* Pack a thread ID */
-static char *pack_threadid(char *pkt, threadref * id)
-{
-       char *limit;
-       unsigned char *altid;
-
-       altid = (unsigned char *) id;
-
-       limit = pkt + BUF_THREAD_ID_SIZE;
-       while (pkt < limit)
-               pkt = pack_hex_byte(pkt, *altid++);
-       return pkt;
-}
-
-/* Convert an integer into our threadref */
-static void int_to_threadref(threadref * id, const int value)
-{
-       unsigned char *scan = (unsigned char *) id;
-       int i = 4;
-
-       while (i--)
-               *scan++ = 0;
-
-       *scan++ = (value >> 24) & 0xff;
-       *scan++ = (value >> 16) & 0xff;
-       *scan++ = (value >> 8) & 0xff;
-       *scan++ = (value & 0xff);
-}
-
-/* Return a task structure ptr for a particular pid */
-static struct task_struct *get_thread(int pid)
-{
-       struct task_struct *thread;
-
-       /* Use PID_MAX w/gdb for pid 0 */
-       if (pid == PID_MAX) pid = 0;
-
-       /* First check via PID */
-       thread = find_task_by_pid(pid);
-
-       if (thread)
-               return thread;
-
-       /* Start at the start */
-       thread = init_tasks[0];
-
-       /* Walk along the linked list of tasks */
-       do {
-               if (thread->pid == pid)
-                       return thread;
-               thread = thread->next_task;
-       } while (thread != init_tasks[0]);
-
-       return NULL;
-}
-
-#endif /* CONFIG_KGDB_THREAD */
-
 /* Scan for the start char '$', read the packet and check the checksum */
 static void get_packet(char *buffer, int buflen)
 {
@@ -452,7 +381,7 @@ static void get_packet(char *buffer, int buflen)
                                /* Ack successful transfer */
                                put_debug_char('+');
 
-                               /* If a sequence char is present, reply 
+                               /* If a sequence char is present, reply
                                   the sequence ID */
                                if (buffer[2] == ':') {
                                        put_debug_char(buffer[0]);
@@ -611,74 +540,6 @@ static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
        regs->vbr = gdb_regs[VBR];
 }
 
-#ifdef CONFIG_KGDB_THREAD
-/* Make a local copy of registers from the specified thread */
-asmlinkage void ret_from_fork(void);
-static void thread_regs_to_gdb_regs(const struct task_struct *thread,
-                                   int *gdb_regs)
-{
-       int regno;
-       int *tregs;
-
-       /* Initialize to zero */
-       for (regno = 0; regno < MAXREG; regno++)
-               gdb_regs[regno] = 0;
-
-       /* Just making sure... */
-       if (thread == NULL)
-               return;
-
-       /* A new fork has pt_regs on the stack from a fork() call */
-       if (thread->thread.pc == (unsigned long)ret_from_fork) {
-
-               int vbr_val;
-               struct pt_regs *kregs;
-               kregs = (struct pt_regs*)thread->thread.sp;
-
-               gdb_regs[R0] = kregs->regs[R0];
-               gdb_regs[R1] = kregs->regs[R1];
-               gdb_regs[R2] = kregs->regs[R2];
-               gdb_regs[R3] = kregs->regs[R3];
-               gdb_regs[R4] = kregs->regs[R4];
-               gdb_regs[R5] = kregs->regs[R5];
-               gdb_regs[R6] = kregs->regs[R6];
-               gdb_regs[R7] = kregs->regs[R7];
-               gdb_regs[R8] = kregs->regs[R8];
-               gdb_regs[R9] = kregs->regs[R9];
-               gdb_regs[R10] = kregs->regs[R10];
-               gdb_regs[R11] = kregs->regs[R11];
-               gdb_regs[R12] = kregs->regs[R12];
-               gdb_regs[R13] = kregs->regs[R13];
-               gdb_regs[R14] = kregs->regs[R14];
-               gdb_regs[R15] = kregs->regs[R15];
-               gdb_regs[PC] = kregs->pc;
-               gdb_regs[PR] = kregs->pr;
-               gdb_regs[GBR] = kregs->gbr;
-               gdb_regs[MACH] = kregs->mach;
-               gdb_regs[MACL] = kregs->macl;
-               gdb_regs[SR] = kregs->sr;
-
-               asm("stc vbr, %0":"=r"(vbr_val));
-               gdb_regs[VBR] = vbr_val;
-               return;
-       }
-
-       /* Otherwise, we have only some registers from switch_to() */
-       tregs = (int *)thread->thread.sp;
-       gdb_regs[R15] = (int)tregs;
-       gdb_regs[R14] = *tregs++;
-       gdb_regs[R13] = *tregs++;
-       gdb_regs[R12] = *tregs++;
-       gdb_regs[R11] = *tregs++;
-       gdb_regs[R10] = *tregs++;
-       gdb_regs[R9] = *tregs++;
-       gdb_regs[R8] = *tregs++;
-       gdb_regs[PR] = *tregs++;
-       gdb_regs[GBR] = *tregs++;
-       gdb_regs[PC] = thread->thread.pc;
-}
-#endif /* CONFIG_KGDB_THREAD */
-
 /* Calculate the new address for after a step */
 static short *get_step_address(void)
 {
@@ -759,7 +620,7 @@ static short *get_step_address(void)
        return (short *) addr;
 }
 
-/* Set up a single-step.  Replace the instruction immediately after the 
+/* Set up a single-step.  Replace the instruction immediately after the
    current instruction (i.e. next in the expected flow of control) with a
    trap instruction, so that returning will cause only a single instruction
    to be executed. Note that this model is slightly broken for instructions
@@ -797,37 +658,11 @@ static void undo_single_step(void)
 /* Send a signal message */
 static void send_signal_msg(const int signum)
 {
-#ifndef CONFIG_KGDB_THREAD
        out_buffer[0] = 'S';
        out_buffer[1] = highhex(signum);
        out_buffer[2] = lowhex(signum);
        out_buffer[3] = 0;
        put_packet(out_buffer);
-#else /* CONFIG_KGDB_THREAD */
-       int threadid;
-       threadref thref;
-       char *out = out_buffer;
-       const char *tstring = "thread";
-
-       *out++ = 'T';
-       *out++ = highhex(signum);
-       *out++ = lowhex(signum);
-
-       while (*tstring) {
-               *out++ = *tstring++;
-       }
-       *out++ = ':';
-
-       threadid = trapped_thread->pid;
-       if (threadid == 0) threadid = PID_MAX;
-       int_to_threadref(&thref, threadid);
-       pack_threadid(out, &thref);
-       out += BUF_THREAD_ID_SIZE;
-       *out++ = ';';
-
-       *out = 0;
-       put_packet(out_buffer);
-#endif /* CONFIG_KGDB_THREAD */
 }
 
 /* Reply that all was well */
@@ -962,15 +797,7 @@ static void step_with_sig_msg(void)
 /* Send register contents */
 static void send_regs_msg(void)
 {
-#ifdef CONFIG_KGDB_THREAD
-       if (!current_thread)
-               kgdb_regs_to_gdb_regs(&trap_registers, registers);
-       else
-               thread_regs_to_gdb_regs(current_thread, registers);
-#else
        kgdb_regs_to_gdb_regs(&trap_registers, registers);
-#endif
-
        mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
        put_packet(out_buffer);
 }
@@ -978,201 +805,13 @@ static void send_regs_msg(void)
 /* Set register contents - currently can't set other thread's registers */
 static void set_regs_msg(void)
 {
-#ifdef CONFIG_KGDB_THREAD
-       if (!current_thread) {
-#endif
-               kgdb_regs_to_gdb_regs(&trap_registers, registers);
-               hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
-               gdb_regs_to_kgdb_regs(registers, &trap_registers);
-               send_ok_msg();
-#ifdef CONFIG_KGDB_THREAD
-       } else
-               send_err_msg();
-#endif
-}
-
-
-#ifdef CONFIG_KGDB_THREAD
-
-/* Set the status for a thread */
-void set_thread_msg(void)
-{
-       int threadid;
-       struct task_struct *thread = NULL;
-       char *ptr;
-
-       switch (in_buffer[1]) {
-
-               /* To select which thread for gG etc messages, i.e. supported */
-       case 'g':
-
-               ptr = &in_buffer[2];
-               hex_to_int(&ptr, &threadid);
-               thread = get_thread(threadid);
-
-               /* If we haven't found it */
-               if (!thread) {
-                       send_err_msg();
-                       break;
-               }
-
-               /* Set current_thread (or not) */
-               if (thread == trapped_thread)
-                       current_thread = NULL;
-               else
-                       current_thread = thread;
-               send_ok_msg();
-               break;
-
-       /* To select which thread for cCsS messages, i.e. unsupported */
-       case 'c':
-               send_ok_msg();
-               break;
-
-       default:
-               send_empty_msg();
-               break;
-       }
-}
-
-/* Is a thread alive? */
-static void thread_status_msg(void)
-{
-       char *ptr;
-       int threadid;
-       struct task_struct *thread = NULL;
-
-       ptr = &in_buffer[1];
-       hex_to_int(&ptr, &threadid);
-       thread = get_thread(threadid);
-       if (thread)
-               send_ok_msg();
-       else
-               send_err_msg();
-}
-/* Send the current thread ID */
-static void thread_id_msg(void)
-{
-       int threadid;
-       threadref thref;
-
-       out_buffer[0] = 'Q';
-       out_buffer[1] = 'C';
-
-       if (current_thread)
-               threadid = current_thread->pid;
-       else if (trapped_thread)
-               threadid = trapped_thread->pid;
-       else /* Impossible, but just in case! */
-       {
-               send_err_msg();
-               return;
-       }
-
-       /* Translate pid 0 to PID_MAX for gdb */
-       if (threadid == 0) threadid = PID_MAX;
-
-       int_to_threadref(&thref, threadid);
-       pack_threadid(out_buffer + 2, &thref);
-       out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
-       put_packet(out_buffer);
-}
-
-/* Send thread info */
-static void thread_info_msg(void)
-{
-       struct task_struct *thread = NULL;
-       int threadid;
-       char *pos;
-       threadref thref;
-
-       /* Start with 'm' */
-       out_buffer[0] = 'm';
-       pos = &out_buffer[1];
-
-       /* For all possible thread IDs - this will overrun if > 44 threads! */
-       /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
-       for (threadid = 1; threadid <= PID_MAX; threadid++) {
-
-               read_lock(&tasklist_lock);
-               thread = get_thread(threadid);
-               read_unlock(&tasklist_lock);
-
-               /* If it's a valid thread */
-               if (thread) {
-                       int_to_threadref(&thref, threadid);
-                       pack_threadid(pos, &thref);
-                       pos += BUF_THREAD_ID_SIZE;
-                       *pos++ = ',';
-               }
-       }
-       *--pos = 0;             /* Lose final comma */
-       put_packet(out_buffer);
-
-}
-
-/* Return printable info for gdb's 'info threads' command */
-static void thread_extra_info_msg(void)
-{
-       int threadid;
-       struct task_struct *thread = NULL;
-       char buffer[20], *ptr;
-       int i;
-
-       /* Extract thread ID */
-       ptr = &in_buffer[17];
-       hex_to_int(&ptr, &threadid);
-       thread = get_thread(threadid);
-
-       /* If we don't recognise it, say so */
-       if (thread == NULL)
-               strcpy(buffer, "(unknown)");
-       else
-               strcpy(buffer, thread->comm);
-
-       /* Construct packet */
-       for (i = 0, ptr = out_buffer; buffer[i]; i++)
-               ptr = pack_hex_byte(ptr, buffer[i]);
-
-       if (thread->thread.pc == (unsigned long)ret_from_fork) {
-               strcpy(buffer, "<new fork>");
-               for (i = 0; buffer[i]; i++)
-                       ptr = pack_hex_byte(ptr, buffer[i]);
-       }
-
-       *ptr = '\0';
-       put_packet(out_buffer);
-}
-
-/* Handle all qFooBarBaz messages - have to use an if statement as
-   opposed to a switch because q messages can have > 1 char id. */
-static void query_msg(void)
-{
-       const char *q_start = &in_buffer[1];
-
-       /* qC = return current thread ID */
-       if (strncmp(q_start, "C", 1) == 0)
-               thread_id_msg();
-
-       /* qfThreadInfo = query all threads (first) */
-       else if (strncmp(q_start, "fThreadInfo", 11) == 0)
-               thread_info_msg();
-
-       /* qsThreadInfo = query all threads (subsequent). We know we have sent
-          them all after the qfThreadInfo message, so there are no to send */
-       else if (strncmp(q_start, "sThreadInfo", 11) == 0)
-               put_packet("l");        /* el = last */
-
-       /* qThreadExtraInfo = supply printable information per thread */
-       else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
-               thread_extra_info_msg();
-
-       /* Unsupported - empty message as per spec */
-       else
-               send_empty_msg();
+       kgdb_regs_to_gdb_regs(&trap_registers, registers);
+       hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
+       gdb_regs_to_kgdb_regs(registers, &trap_registers);
+       send_ok_msg();
 }
-#endif /* CONFIG_KGDB_THREAD */
 
+#ifdef CONFIG_SH_KGDB_CONSOLE
 /*
  * Bring up the ports..
  */
@@ -1185,6 +824,9 @@ static int kgdb_serial_setup(void)
 
        return 0;
 }
+#else
+#define kgdb_serial_setup()    0
+#endif
 
 /* The command loop, read and act on requests */
 static void kgdb_command_loop(const int excep_code, const int trapa_value)
@@ -1193,7 +835,7 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
 
        if (excep_code == NMI_VEC) {
 #ifndef CONFIG_KGDB_NMI
-               KGDB_PRINTK("Ignoring unexpected NMI?\n");
+               printk(KERN_NOTICE "KGDB: Ignoring unexpected NMI?\n");
                return;
 #else /* CONFIG_KGDB_NMI */
                if (!kgdb_enabled) {
@@ -1207,19 +849,10 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
        if (!kgdb_enabled)
                return;
 
-#ifdef CONFIG_KGDB_THREAD
-       /* Until GDB specifies a thread */
-       current_thread = NULL;
-       trapped_thread = current;
-#endif
-
        /* Enter GDB mode (e.g. after detach) */
        if (!kgdb_in_gdb_mode) {
                /* Do serial setup, notify user, issue preemptive ack */
-               kgdb_serial_setup();
-               KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
-                           (kgdb_porttype ? kgdb_porttype->name : ""),
-                           kgdb_portnum, kgdb_baud);
+               printk(KERN_NOTICE "KGDB: Waiting for GDB\n");
                kgdb_in_gdb_mode = 1;
                put_debug_char('+');
        }
@@ -1233,21 +866,18 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
           will later be replaced by its original one.  Do NOT do this for
           trap 0xff, since that indicates a compiled-in breakpoint which
           will not be replaced (and we would retake the trap forever) */
-       if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
+       if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2)))
                trap_registers.pc -= 2;
-       }
 
        /* Undo any stepping we may have done */
        undo_single_step();
 
        while (1) {
-
                out_buffer[0] = 0;
                get_packet(in_buffer, BUFMAX);
 
                /* Examine first char of buffer to see what we need to do */
                switch (in_buffer[0]) {
-
                case '?':       /* Send which signal we've received */
                        send_signal_msg(sigval);
                        break;
@@ -1291,21 +921,6 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
                        step_msg();
                        return;
 
-#ifdef CONFIG_KGDB_THREAD
-
-               case 'H':       /* Task related */
-                       set_thread_msg();
-                       break;
-
-               case 'T':       /* Query thread status */
-                       thread_status_msg();
-                       break;
-
-               case 'q':       /* Handle query - currently thread-related */
-                       query_msg();
-                       break;
-#endif
-
                case 'k':       /* 'Kill the program' with a kernel ? */
                        break;
 
@@ -1323,11 +938,8 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
 }
 
 /* There has been an exception, most likely a breakpoint. */
-asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
-                                     unsigned long r6, unsigned long r7,
-                                     struct pt_regs __regs)
+static void handle_exception(struct pt_regs *regs)
 {
-       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int excep_code, vbr_val;
        int count;
        int trapa_value = ctrl_inl(TRA);
@@ -1355,7 +967,7 @@ asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
        kgdb_trapa_val = trapa_value;
 
        /* Act on the exception */
-       kgdb_command_loop(excep_code >> 5, trapa_value);
+       kgdb_command_loop(excep_code, trapa_value);
 
        kgdb_current = NULL;
 
@@ -1373,14 +985,12 @@ asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
        asm("ldc %0, vbr": :"r"(vbr_val));
 }
 
-/* Trigger a breakpoint by function */
-void breakpoint(void)
+asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
+                                     unsigned long r6, unsigned long r7,
+                                     struct pt_regs __regs)
 {
-       if (!kgdb_enabled) {
-               kgdb_enabled = 1;
-               kgdb_init();
-       }
-       BREAKPOINT();
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       handle_exception(regs);
 }
 
 /* Initialise the KGDB data structures and serial configuration */
@@ -1395,24 +1005,16 @@ int kgdb_init(void)
        kgdb_in_gdb_mode = 0;
 
        if (kgdb_serial_setup() != 0) {
-               KGDB_PRINTK("serial setup error\n");
+               printk(KERN_NOTICE "KGDB: serial setup error\n");
                return -1;
        }
 
        /* Init ptr to exception handler */
-       kgdb_debug_hook = kgdb_handle_exception;
+       kgdb_debug_hook = handle_exception;
        kgdb_bus_err_hook = kgdb_handle_bus_error;
 
        /* Enter kgdb now if requested, or just report init done */
-       if (kgdb_halt) {
-               kgdb_in_gdb_mode = 1;
-               put_debug_char('+');
-               breakpoint();
-       }
-       else
-       {
-               KGDB_PRINTK("stub is initialized.\n");
-       }
+       printk(KERN_NOTICE "KGDB: stub is initialized.\n");
 
        return 0;
 }
@@ -1437,7 +1039,7 @@ static void kgdb_msg_write(const char *s, unsigned count)
 
                /* Calculate how many this time */
                wcount = (count > MAXOUT) ? MAXOUT : count;
-               
+
                /* Pack in hex chars */
                for (i = 0; i < wcount; i++)
                        bufptr = pack_hex_byte(bufptr, s[i]);
@@ -1467,3 +1069,25 @@ void kgdb_console_write(struct console *co, const char *s, unsigned count)
        kgdb_msg_write(s, count);
 }
 #endif
+
+#ifdef CONFIG_KGDB_SYSRQ
+static void sysrq_handle_gdb(int key, struct tty_struct *tty)
+{
+       printk("Entering GDB stub\n");
+       breakpoint();
+}
+
+static struct sysrq_key_op sysrq_gdb_op = {
+        .handler        = sysrq_handle_gdb,
+        .help_msg       = "Gdb",
+        .action_msg     = "GDB",
+};
+
+static int gdb_register_sysrq(void)
+{
+       printk("Registering GDB sysrq handler\n");
+       register_sysrq_key('g', &sysrq_gdb_op);
+       return 0;
+}
+module_init(gdb_register_sysrq);
+#endif
index 08587cd..790ed69 100644 (file)
@@ -59,13 +59,13 @@ static void kexec_info(struct kimage *image)
                printk("  segment[%d]: 0x%08x - 0x%08x (0x%08x)\n",
                       i,
                       (unsigned int)image->segment[i].mem,
-                      (unsigned int)image->segment[i].mem + image->segment[i].memsz,
+                      (unsigned int)image->segment[i].mem +
+                                    image->segment[i].memsz,
                       (unsigned int)image->segment[i].memsz);
-       }
+       }
        printk("  start     : 0x%08x\n\n", (unsigned int)image->start);
 }
 
-
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
@@ -101,6 +101,27 @@ NORET_TYPE void machine_kexec(struct kimage *image)
 
        /* now call it */
        rnk = (relocate_new_kernel_t) reboot_code_buffer;
-               (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
+       (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
 }
 
+/* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel.  By reserving this memory we guarantee
+ * that linux never sets it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+static int __init parse_crashkernel(char *arg)
+{
+       unsigned long size, base;
+       size = memparse(arg, &arg);
+       if (*arg == '@') {
+               base = memparse(arg+1, &arg);
+               /* FIXME: Do I want a sanity check
+                * to validate the memory range?
+                */
+               crashk_res.start = base;
+               crashk_res.end   = base + size - 1;
+       }
+       return 0;
+}
+early_param("crashkernel", parse_crashkernel);
index e760736..329b3f3 100644 (file)
@@ -7,7 +7,7 @@
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *                  Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
- *                  Copyright (C) 2002 - 2006  Paul Mundt
+ *                  Copyright (C) 2002 - 2007  Paul Mundt
  */
 #include <linux/module.h>
 #include <linux/mm.h>
@@ -15,6 +15,7 @@
 #include <linux/pm.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
+#include <asm/kdebug.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/ubc.h>
@@ -299,7 +300,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
        ctrl_outl(0, UBC_BAMRA);
 
        if (current_cpu_data.type == CPU_SH7729 ||
-           current_cpu_data.type == CPU_SH7710) {
+           current_cpu_data.type == CPU_SH7710 ||
+           current_cpu_data.type == CPU_SH7712) {
                ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
                ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
        } else {
@@ -495,6 +497,10 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
        /* Rewind */
        regs->pc -= 2;
 
+       if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
+                      SIGTRAP) == NOTIFY_STOP)
+               return;
+
        force_sig(SIGTRAP, current);
 }
 
@@ -510,6 +516,10 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
        /* Rewind */
        regs->pc -= 2;
 
+       if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
+                      SIGTRAP) == NOTIFY_STOP)
+               return;
+
 #ifdef CONFIG_BUG
        if (__kernel_text_address(instruction_pointer(regs))) {
                u16 insn = *(u16 *)instruction_pointer(regs);
index 98802ab..477d2a8 100644 (file)
@@ -4,7 +4,7 @@
  * This file handles the architecture-dependent parts of initialization
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2002 - 2006 Paul Mundt
+ *  Copyright (C) 2002 - 2007 Paul Mundt
  */
 #include <linux/screen_info.h>
 #include <linux/ioport.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/utsname.h>
+#include <linux/nodemask.h>
 #include <linux/cpu.h>
 #include <linux/pfn.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/kexec.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/clock.h>
+#include <asm/mmu_context.h>
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-static int kgdb_parse_options(char *options);
-#endif
 extern void * __rd_start, * __rd_end;
+
 /*
  * Machine setup..
  */
@@ -205,53 +206,33 @@ static int __init sh_mv_setup(char **cmdline_p)
        return 0;
 }
 
-void __init setup_arch(char **cmdline_p)
+/*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+static void __init register_bootmem_low_pages(void)
 {
-       unsigned long bootmap_size;
-       unsigned long start_pfn, max_pfn, max_low_pfn;
-
-#ifdef CONFIG_CMDLINE_BOOL
-        strcpy(COMMAND_LINE, CONFIG_CMDLINE);
-#endif
-
-       ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
-
-#ifdef CONFIG_BLK_DEV_RAM
-       rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-       rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
-       rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
-#endif
-
-       if (!MOUNT_ROOT_RDONLY)
-               root_mountflags &= ~MS_RDONLY;
-       init_mm.start_code = (unsigned long) _text;
-       init_mm.end_code = (unsigned long) _etext;
-       init_mm.end_data = (unsigned long) _edata;
-       init_mm.brk = (unsigned long) _end;
-
-       code_resource.start = (unsigned long)virt_to_phys(_text);
-       code_resource.end = (unsigned long)virt_to_phys(_etext)-1;
-       data_resource.start = (unsigned long)virt_to_phys(_etext);
-       data_resource.end = (unsigned long)virt_to_phys(_edata)-1;
-
-       sh_mv_setup(cmdline_p);
-
+       unsigned long curr_pfn, last_pfn, pages;
 
        /*
-        * Find the highest page frame number we have available
+        * We are rounding up the start address of usable memory:
         */
-       max_pfn = PFN_DOWN(__pa(memory_end));
+       curr_pfn = PFN_UP(__MEMORY_START);
 
        /*
-        * Determine low and high memory ranges:
+        * ... and at the end of the usable range downwards:
         */
-       max_low_pfn = max_pfn;
+       last_pfn = PFN_DOWN(__pa(memory_end));
 
-       /*
-        * Partially used pages are not usable - thus
-        * we are rounding upwards:
-        */
-       start_pfn = PFN_UP(__pa(_end));
+       if (last_pfn > max_low_pfn)
+               last_pfn = max_low_pfn;
+
+       pages = last_pfn - curr_pfn;
+       free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
+}
+
+void __init setup_bootmem_allocator(unsigned long start_pfn)
+{
+       unsigned long bootmap_size;
 
        /*
         * Find a proper area for the bootmem bitmap. After this
@@ -259,31 +240,11 @@ void __init setup_arch(char **cmdline_p)
         * is intact) must be done via bootmem_alloc().
         */
        bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
-                                        __MEMORY_START>>PAGE_SHIFT,
-                                        max_low_pfn);
-       /*
-        * Register fully available low RAM pages with the bootmem allocator.
-        */
-       {
-               unsigned long curr_pfn, last_pfn, pages;
-
-               /*
-                * We are rounding up the start address of usable memory:
-                */
-               curr_pfn = PFN_UP(__MEMORY_START);
-               /*
-                * ... and at the end of the usable range downwards:
-                */
-               last_pfn = PFN_DOWN(__pa(memory_end));
+                                        min_low_pfn, max_low_pfn);
 
-               if (last_pfn > max_low_pfn)
-                       last_pfn = max_low_pfn;
-
-               pages = last_pfn - curr_pfn;
-               free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
-                                 PFN_PHYS(pages));
-       }
+       register_bootmem_low_pages();
 
+       node_set_online(0);
 
        /*
         * Reserve the kernel text and
@@ -292,14 +253,14 @@ void __init setup_arch(char **cmdline_p)
         * case of us accidentally initializing the bootmem allocator with
         * an invalid RAM area.
         */
-       reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE,
+       reserve_bootmem(__MEMORY_START+PAGE_SIZE,
                (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
 
        /*
         * reserve physical page 0 - it's a special BIOS page on many boxes,
         * enabling clean reboots, SMP operation, laptop functions.
         */
-       reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
+       reserve_bootmem(__MEMORY_START, PAGE_SIZE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
@@ -313,8 +274,8 @@ void __init setup_arch(char **cmdline_p)
 
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-                       reserve_bootmem_node(NODE_DATA(0), INITRD_START +
-                                               __MEMORY_START, INITRD_SIZE);
+                       reserve_bootmem(INITRD_START + __MEMORY_START,
+                                       INITRD_SIZE);
                        initrd_start = INITRD_START + PAGE_OFFSET +
                                        __MEMORY_START;
                        initrd_end = initrd_start + INITRD_SIZE;
@@ -327,6 +288,76 @@ void __init setup_arch(char **cmdline_p)
                }
        }
 #endif
+#ifdef CONFIG_KEXEC
+       if (crashk_res.start != crashk_res.end)
+               reserve_bootmem(crashk_res.start,
+                       crashk_res.end - crashk_res.start + 1);
+#endif
+}
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+static void __init setup_memory(void)
+{
+       unsigned long start_pfn;
+
+       /*
+        * Partially used pages are not usable - thus
+        * we are rounding upwards:
+        */
+       start_pfn = PFN_UP(__pa(_end));
+       setup_bootmem_allocator(start_pfn);
+}
+#else
+extern void __init setup_memory(void);
+#endif
+
+void __init setup_arch(char **cmdline_p)
+{
+       enable_mmu();
+
+#ifdef CONFIG_CMDLINE_BOOL
+       strcpy(COMMAND_LINE, CONFIG_CMDLINE);
+#endif
+
+       ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+
+#ifdef CONFIG_BLK_DEV_RAM
+       rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+       rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+       rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+       if (!MOUNT_ROOT_RDONLY)
+               root_mountflags &= ~MS_RDONLY;
+       init_mm.start_code = (unsigned long) _text;
+       init_mm.end_code = (unsigned long) _etext;
+       init_mm.end_data = (unsigned long) _edata;
+       init_mm.brk = (unsigned long) _end;
+
+       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;
+
+       parse_early_param();
+
+       sh_mv_setup(cmdline_p);
+
+       /*
+        * Find the highest page frame number we have available
+        */
+       max_pfn = PFN_DOWN(__pa(memory_end));
+
+       /*
+        * Determine low and high memory ranges:
+        */
+       max_low_pfn = max_pfn;
+       min_low_pfn = __MEMORY_START >> PAGE_SHIFT;
+
+       nodes_clear(node_online_map);
+       setup_memory();
+       paging_init();
+       sparse_init();
 
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
@@ -335,8 +366,6 @@ void __init setup_arch(char **cmdline_p)
        /* Perform the machine specific initialisation */
        if (likely(sh_mv.mv_setup))
                sh_mv.mv_setup(cmdline_p);
-
-       paging_init();
 }
 
 struct sh_machine_vector* __init get_mv_byname(const char* name)
@@ -380,6 +409,7 @@ static const char *cpu_name[] = {
        [CPU_SH7705]    = "SH7705",     [CPU_SH7706]    = "SH7706",
        [CPU_SH7707]    = "SH7707",     [CPU_SH7708]    = "SH7708",
        [CPU_SH7709]    = "SH7709",     [CPU_SH7710]    = "SH7710",
+       [CPU_SH7712]    = "SH7712",
        [CPU_SH7729]    = "SH7729",     [CPU_SH7750]    = "SH7750",
        [CPU_SH7750S]   = "SH7750S",    [CPU_SH7750R]   = "SH7750R",
        [CPU_SH7751]    = "SH7751",     [CPU_SH7751R]   = "SH7751R",
@@ -477,7 +507,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                     c->loops_per_jiffy/(500000/HZ),
                     (c->loops_per_jiffy/(5000/HZ)) % 100);
 
-       return show_clocks(m);
+       return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
@@ -499,92 +529,3 @@ struct seq_operations cpuinfo_op = {
        .show   = show_cpuinfo,
 };
 #endif /* CONFIG_PROC_FS */
-
-#ifdef CONFIG_SH_KGDB
-/*
- * Parse command-line kgdb options.  By default KGDB is enabled,
- * entered on error (or other action) using default serial info.
- * The command-line option can include a serial port specification
- * and an action to override default or configured behavior.
- */
-struct kgdb_sermap kgdb_sci_sermap =
-{ "ttySC", 5, kgdb_sci_setup, NULL };
-
-struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
-struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
-
-void kgdb_register_sermap(struct kgdb_sermap *map)
-{
-       struct kgdb_sermap *last;
-
-       for (last = kgdb_serlist; last->next; last = last->next)
-               ;
-       last->next = map;
-       if (!map->namelen) {
-               map->namelen = strlen(map->name);
-       }
-}
-
-static int __init kgdb_parse_options(char *options)
-{
-       char c;
-       int baud;
-
-       /* Check for port spec (or use default) */
-
-       /* Determine port type and instance */
-       if (!memcmp(options, "tty", 3)) {
-               struct kgdb_sermap *map = kgdb_serlist;
-
-               while (map && memcmp(options, map->name, map->namelen))
-                       map = map->next;
-
-               if (!map) {
-                       KGDB_PRINTK("unknown port spec in %s\n", options);
-                       return -1;
-               }
-
-               kgdb_porttype = map;
-               kgdb_serial_setup = map->setup_fn;
-               kgdb_portnum = options[map->namelen] - '0';
-               options += map->namelen + 1;
-
-               options = (*options == ',') ? options+1 : options;
-
-               /* Read optional parameters (baud/parity/bits) */
-               baud = simple_strtoul(options, &options, 10);
-               if (baud != 0) {
-                       kgdb_baud = baud;
-
-                       c = toupper(*options);
-                       if (c == 'E' || c == 'O' || c == 'N') {
-                               kgdb_parity = c;
-                               options++;
-                       }
-
-                       c = *options;
-                       if (c == '7' || c == '8') {
-                               kgdb_bits = c;
-                               options++;
-                       }
-                       options = (*options == ',') ? options+1 : options;
-               }
-       }
-
-       /* Check for action specification */
-       if (!memcmp(options, "halt", 4)) {
-               kgdb_halt = 1;
-               options += 4;
-       } else if (!memcmp(options, "disabled", 8)) {
-               kgdb_enabled = 0;
-               options += 8;
-       }
-
-       if (*options) {
-                KGDB_PRINTK("ignored unknown options: %s\n", options);
-               return 0;
-       }
-       return 1;
-}
-__setup("kgdb=", kgdb_parse_options);
-#endif /* CONFIG_SH_KGDB */
index 6e0d10f..17f0b50 100644 (file)
@@ -65,7 +65,6 @@ EXPORT_SYMBOL(__div64_32);
 
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
-DECLARE_EXPORT(__udivdi3);
 DECLARE_EXPORT(__sdivsi3);
 DECLARE_EXPORT(__ashrdi3);
 DECLARE_EXPORT(__ashldi3);
index e060e71..ad1ede5 100644 (file)
@@ -148,7 +148,9 @@ static int tmu_timer_init(void)
 
        /* Start TMU0 */
        tmu_timer_stop();
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7785)
        ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 #endif
 
index e9f168f..7b40f0f 100644 (file)
@@ -5,7 +5,7 @@
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
- *                  Copyright (C) 2002 - 2006 Paul Mundt
+ *                  Copyright (C) 2002 - 2007 Paul Mundt
  *
  * 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
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/io.h>
+#include <linux/bug.h>
 #include <linux/debug_locks.h>
 #include <linux/limits.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/kdebug.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -74,7 +76,21 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
        }
 }
 
-DEFINE_SPINLOCK(die_lock);
+ATOMIC_NOTIFIER_HEAD(shdie_chain);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&shdie_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&shdie_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
+static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -130,40 +146,6 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
        return -EFAULT;
 }
 
-#ifdef CONFIG_BUG
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-static inline void do_bug_verbose(struct pt_regs *regs)
-{
-       struct bug_frame f;
-       long len;
-
-       if (__copy_from_user(&f, (const void __user *)regs->pc,
-                            sizeof(struct bug_frame)))
-               return;
-
-       len = __strnlen_user(f.file, PATH_MAX) - 1;
-       if (unlikely(len < 0 || len >= PATH_MAX))
-               f.file = "<bad filename>";
-       len = __strnlen_user(f.func, PATH_MAX) - 1;
-       if (unlikely(len < 0 || len >= PATH_MAX))
-               f.func = "<bad function>";
-
-       printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n",
-              f.func, f.file, f.line);
-}
-#else
-static inline void do_bug_verbose(struct pt_regs *regs)
-{
-}
-#endif /* CONFIG_DEBUG_BUGVERBOSE */
-
-void handle_BUG(struct pt_regs *regs)
-{
-       do_bug_verbose(regs);
-       die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
-}
-#endif /* CONFIG_BUG */
-
 /*
  * handle an instruction that does an unaligned memory access by emulating the
  * desired behaviour
@@ -888,6 +870,25 @@ void __init trap_init(void)
        per_cpu_trap_init();
 }
 
+#ifdef CONFIG_BUG
+void handle_BUG(struct pt_regs *regs)
+{
+       enum bug_trap_type tt;
+       tt = report_bug(regs->pc);
+       if (tt == BUG_TRAP_TYPE_WARN) {
+               regs->pc += 2;
+               return;
+       }
+
+       die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
+}
+
+int is_valid_bugaddr(unsigned long addr)
+{
+       return addr >= PAGE_OFFSET;
+}
+#endif
+
 void show_trace(struct task_struct *tsk, unsigned long *sp,
                struct pt_regs *regs)
 {
index 78a6c09..d83143c 100644 (file)
@@ -34,9 +34,11 @@ SECTIONS
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
+  _etext = .;                  /* End of text section */
+
   RODATA
 
-  _etext = .;                  /* End of text section */
+  BUG_TABLE
 
   .data : {                    /* Data */
        *(.data)
@@ -53,8 +55,12 @@ SECTIONS
 
   . = ALIGN(PAGE_SIZE);
   .data.page_aligned : { *(.data.page_aligned) }
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(PAGE_SIZE);
+  __nosave_end = .;
 
-  . = ALIGN(L1_CACHE_BYTES);
+  . = ALIGN(PAGE_SIZE);
   __per_cpu_start = .;
   .data.percpu : { *(.data.percpu) }
   __per_cpu_end = .;
@@ -110,43 +116,10 @@ SECTIONS
    * it's a module.
    */
   /DISCARD/ : {
-       *(.exit.text)
-       *(.exit.data)
        *(.exitcall.exit)
        }
 
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-  /* DWARF debug sections.
-     Symbols in the DWARF debugging section are relative to the beginning
-     of the section so we begin .debug at 0.  */
-  /* DWARF 1 */
-  .debug          0 : { *(.debug) }
-  .line           0 : { *(.line) }
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info) }
-  .debug_abbrev   0 : { *(.debug_abbrev) }
-  .debug_line     0 : { *(.debug_line) }
-  .debug_frame    0 : { *(.debug_frame) }
-  .debug_str      0 : { *(.debug_str) }
-  .debug_loc      0 : { *(.debug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames) }
-  /* These must appear regardless of  .  */
+  STABS_DEBUG
+
+  DWARF_DEBUG
 }
index 0b9cca5..e23dd1a 100644 (file)
@@ -3,11 +3,9 @@
 #
 
 lib-y  = delay.o memset.o memmove.o memchr.o \
-        checksum.o strlen.o div64.o udivdi3.o \
-        div64-generic.o
+        checksum.o strlen.o div64.o div64-generic.o
 
 memcpy-y                       := memcpy.o
 memcpy-$(CONFIG_CPU_SH4)       := memcpy-sh4.o
 
 lib-y  += $(memcpy-y)
-
diff --git a/arch/sh/lib/udivdi3.c b/arch/sh/lib/udivdi3.c
deleted file mode 100644 (file)
index 68f038b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Simple __udivdi3 function which doesn't use FPU.
- */
-
-#include <linux/types.h>
-
-extern u64 __xdiv64_32(u64 n, u32 d);
-extern void panic(const char * fmt, ...);
-
-u64 __udivdi3(u64 n, u64 d)
-{
-       if (d & ~0xffffffff)
-               panic("Need true 64-bit/64-bit division");
-       return __xdiv64_32(n, (u32)d);
-}
-
index 6b0d28a..12f3d39 100644 (file)
@@ -67,6 +67,7 @@ config CPU_SUBTYPE_SH7300
 config CPU_SUBTYPE_SH7705
        bool "Support SH7705 processor"
        select CPU_SH3
+       select CPU_HAS_IPR_IRQ
        select CPU_HAS_PINT_IRQ
 
 config CPU_SUBTYPE_SH7706
@@ -101,9 +102,17 @@ config CPU_SUBTYPE_SH7709
 config CPU_SUBTYPE_SH7710
        bool "Support SH7710 processor"
        select CPU_SH3
+       select CPU_HAS_IPR_IRQ
        help
          Select SH7710 if you have a SH3-DSP SH7710 CPU.
 
+config CPU_SUBTYPE_SH7712
+       bool "Support SH7712 processor"
+       select CPU_SH3
+       select CPU_HAS_IPR_IRQ
+       help
+         Select SH7712 if you have a SH3-DSP SH7712 CPU.
+
 comment "SH-4 Processor Support"
 
 config CPU_SUBTYPE_SH7750
@@ -283,6 +292,17 @@ config VSYSCALL
          For systems with an MMU that can afford to give up a page,
          (the default value) say Y.
 
+config NODES_SHIFT
+       int
+       default "1"
+       depends on NEED_MULTIPLE_NODES
+
+config ARCH_FLATMEM_ENABLE
+       def_bool y
+
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 choice
        prompt "Kernel page size"
        default PAGE_SIZE_4KB
index fa5d7f0..0ecc117 100644 (file)
@@ -2,7 +2,7 @@
  * Page fault handler for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2007  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/fault.c:
  *   Copyright (C) 1995  Linus Torvalds
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
+#include <asm/kdebug.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 #include <asm/kgdb.h>
 
-extern void die(const char *,struct pt_regs *,long);
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
+/* Hook to register for page fault notifications */
+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 inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
+                                   int trap, int sig)
+{
+       struct die_args args = {
+               .regs = regs,
+               .trapnr = trap,
+       };
+       return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
+                                   int trap, int sig)
+{
+       return NOTIFY_DONE;
+}
+#endif
 
 /*
  * This routine handles page faults.  It determines the address,
@@ -39,6 +69,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        siginfo_t info;
 
        trace_hardirqs_on();
+
+       if (notify_page_fault(DIE_PAGE_FAULT, regs,
+                             writeaccess, SIGSEGV) == NOTIFY_STOP)
+               return;
+
        local_irq_enable();
 
 #ifdef CONFIG_SH_KGDB
index ae957a9..4d03098 100644 (file)
@@ -1,37 +1,20 @@
-/* $Id: init.c,v 1.19 2004/02/21 04:42:16 kkojima Exp $
- *
- *  linux/arch/sh/mm/init.c
+/*
+ * linux/arch/sh/mm/init.c
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2002, 2004  Paul Mundt
+ *  Copyright (C) 2002 - 2007  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/init.c:
  *   Copyright (C) 1995  Linus Torvalds
  */
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
-#include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/highmem.h>
 #include <linux/bootmem.h>
-#include <linux/pagemap.h>
 #include <linux/proc_fs.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
+#include <linux/percpu.h>
+#include <linux/io.h>
 #include <asm/mmu_context.h>
-#include <asm/io.h>
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-#ifdef CONFIG_MMU
-/* It'd be good if these lines were in the standard header file. */
-#define START_PFN      (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
-#define MAX_LOW_PFN    (NODE_DATA(0)->bdata->node_low_pfn)
-#endif
-
 void (*copy_page)(void *from, void *to);
 void (*clear_page)(void *to);
 
 void show_mem(void)
 {
-       int i, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
+       int total = 0, reserved = 0, free = 0;
+       int shared = 0, cached = 0, slab = 0;
+       pg_data_t *pgdat;
 
        printk("Mem-info:\n");
        show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       i = max_mapnr;
-       while (i-- > 0) {
-               total++;
-               if (PageReserved(mem_map+i))
-                       reserved++;
-               else if (PageSwapCache(mem_map+i))
-                       cached++;
-               else if (page_count(mem_map+i))
-                       shared += page_count(mem_map+i) - 1;
+
+       for_each_online_pgdat(pgdat) {
+               struct page *page, *end;
+               unsigned long flags;
+
+               pgdat_resize_lock(pgdat, &flags);
+               page = pgdat->node_mem_map;
+               end = page + pgdat->node_spanned_pages;
+
+               do {
+                       total++;
+                       if (PageReserved(page))
+                               reserved++;
+                       else if (PageSwapCache(page))
+                               cached++;
+                       else if (PageSlab(page))
+                               slab++;
+                       else if (!page_count(page))
+                               free++;
+                       else
+                               shared += page_count(page) - 1;
+                       page++;
+               } while (page < end);
+
+               pgdat_resize_unlock(pgdat, &flags);
        }
-       printk("%d pages of RAM\n",total);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
-       printk("%d pages swap cached\n",cached);
+
+       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk("%d pages of RAM\n", total);
+       printk("%d free pages\n", free);
+       printk("%d reserved pages\n", reserved);
+       printk("%d slab pages\n", slab);
+       printk("%d pages shared\n", shared);
+       printk("%d pages swap cached\n", cached);
 }
 
 #ifdef CONFIG_MMU
@@ -147,52 +144,38 @@ extern char __init_begin, __init_end;
  */
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+       int nid;
 
-       /*
-        * Setup some defaults for the zone sizes.. these should be safe
-        * regardless of distcontiguous memory or MMU settings.
-        */
-       zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
-#ifdef CONFIG_HIGHMEM
-       zones_size[ZONE_HIGHMEM] = 0 >> PAGE_SHIFT;
-#endif
-
-#ifdef CONFIG_MMU
-       /*
-        * If we have an MMU, and want to be using it .. we need to adjust
-        * the zone sizes accordingly, in addition to turning it on.
-        */
-       {
-               /* We don't need to map the kernel through the TLB, as
-                * it is permanatly mapped using P1. So clear the
-                * entire pgd. */
-               memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
-
-               /* Turn on the MMU */
-               enable_mmu();
-               zones_size[ZONE_NORMAL] = MAX_LOW_PFN - START_PFN;
-       }
+       /* We don't need to map the kernel through the TLB, as
+        * it is permanatly mapped using P1. So clear the
+        * entire pgd. */
+       memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
 
        /* Set an initial value for the MMU.TTB so we don't have to
         * check for a null value. */
        set_TTB(swapper_pg_dir);
 
-#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
-       /*
-        * If we don't have CONFIG_MMU set and the processor in question
-        * still has an MMU, care needs to be taken to make sure it doesn't
-        * stay on.. Since the boot loader could have potentially already
-        * turned it on, and we clearly don't want it, we simply turn it off.
-        *
-        * We don't need to do anything special for the zone sizes, since the
-        * default values that were already configured up above should be
-        * satisfactory.
-        */
-       disable_mmu();
-#endif
-       NODE_DATA(0)->node_mem_map = NULL;
-       free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+       for_each_online_node(nid) {
+               pg_data_t *pgdat = NODE_DATA(nid);
+               unsigned long max_zone_pfns[MAX_NR_ZONES];
+               unsigned long low, start_pfn;
+
+               memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+
+               start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
+               low = pgdat->bdata->node_low_pfn;
+
+               max_zone_pfns[ZONE_NORMAL] = low;
+               add_active_range(nid, start_pfn, low);
+
+               printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
+                      nid, start_pfn, low);
+
+               free_area_init_nodes(max_zone_pfns);
+
+               printk("Node %u: mem_map starts at %p\n",
+                      pgdat->node_id, pgdat->node_mem_map);
+       }
 }
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -200,18 +183,33 @@ static struct kcore_list kcore_mem, kcore_vmalloc;
 void __init mem_init(void)
 {
        int codesize, reservedpages, datasize, initsize;
-       int tmp;
-       extern unsigned long memory_start;
+       int nid;
 
-#ifdef CONFIG_MMU
-       high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE);
-#else
-       extern unsigned long memory_end;
+       reservedpages = 0;
 
-       high_memory = (void *)(memory_end & PAGE_MASK);
-#endif
+       for_each_online_node(nid) {
+               pg_data_t *pgdat = NODE_DATA(nid);
+               unsigned long node_pages = 0;
+               void *node_high_memory;
+               int i;
+
+               num_physpages += pgdat->node_present_pages;
+
+               if (pgdat->node_spanned_pages)
+                       node_pages = free_all_bootmem_node(pgdat);
+
+               totalram_pages += node_pages;
 
-       max_mapnr = num_physpages = MAP_NR(high_memory) - MAP_NR(memory_start);
+               for (i = 0; i < node_pages; i++)
+                       if (PageReserved(pgdat->node_mem_map + i))
+                               reservedpages++;
+
+               node_high_memory = (void *)((pgdat->node_start_pfn +
+                                            pgdat->node_spanned_pages) <<
+                                               PAGE_SHIFT);
+               if (node_high_memory > high_memory)
+                       high_memory = node_high_memory;
+       }
 
        /* clear the zero-page */
        memset(empty_zero_page, 0, PAGE_SIZE);
@@ -229,16 +227,6 @@ void __init mem_init(void)
        clear_page = clear_page_nommu;
 #endif
 
-       /* this will put all low memory onto the freelists */
-       totalram_pages += free_all_bootmem_node(NODE_DATA(0));
-       reservedpages = 0;
-       for (tmp = 0; tmp < num_physpages; tmp++)
-               /*
-                * Only count reserved RAM pages
-                */
-               if (PageReserved(mem_map+tmp))
-                       reservedpages++;
-
        codesize =  (unsigned long) &_etext - (unsigned long) &_text;
        datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
@@ -250,7 +238,7 @@ void __init mem_init(void)
        printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
               "%dk reserved, %dk data, %dk init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-               max_mapnr << (PAGE_SHIFT-10),
+               totalram_pages << (PAGE_SHIFT-10),
                codesize >> 10,
                reservedpages << (PAGE_SHIFT-10),
                datasize >> 10,
@@ -289,4 +277,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
-
index 4fe0f94..554f801 100644 (file)
@@ -9,6 +9,7 @@ SE                      SH_SOLUTION_ENGINE
 7751SE                 SH_7751_SOLUTION_ENGINE         
 7300SE                 SH_7300_SOLUTION_ENGINE
 7343SE                 SH_7343_SOLUTION_ENGINE
+7780SE                 SH_7780_SOLUTION_ENGINE
 73180SE                        SH_73180_SOLUTION_ENGINE
 7751SYSTEMH            SH_7751_SYSTEMH
 HP6XX                  SH_HP6XX
@@ -26,6 +27,7 @@ SH03                  SH_SH03
 LANDISK                        SH_LANDISK
 R7780RP                        SH_R7780RP
 R7780MP                        SH_R7780MP
+R7785RP                        SH_R7785RP
 TITAN                  SH_TITAN
 SHMIN                  SH_SHMIN
 7710VOIPGW             SH_7710VOIPGW
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 e2d9c01..4e07bdb 100644 (file)
@@ -405,7 +405,7 @@ void __init smp4m_blackbox_current(unsigned *addr)
        
        addr[0] = 0x81580000 | rd;              /* rd %tbr, reg */
        addr[2] = 0x8130200a | rd | rs1;        /* srl reg, 0xa, reg */
-       addr[4] = 0x8008200c | rd | rs1;        /* and reg, 3, reg */
+       addr[4] = 0x8008200c | rd | rs1;        /* and reg, 0xc, reg */
 }
 
 void __init sun4m_init_smp(void)
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..ad8d6b2 100644 (file)
@@ -34,6 +34,10 @@ config MMU
        bool
        default y
 
+config QUICKLIST
+       bool
+       default y
+
 config STACKTRACE_SUPPORT
        bool
        default y
@@ -306,6 +310,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 120c9c3..37c2d36 100644 (file)
@@ -1,15 +1,16 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc4
-# Sat Mar 17 14:18:44 2007
+# Linux kernel version: 2.6.21
+# Sun May  6 22:46:54 2007
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_TIME_INTERPOLATION=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -108,6 +109,9 @@ CONFIG_GENERIC_HARDIRQS=y
 #
 # General machine setup
 #
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_SMP is not set
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=m
@@ -140,8 +144,7 @@ CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_SPARSEMEM_MANUAL=y
 CONFIG_SPARSEMEM=y
 CONFIG_HAVE_MEMORY_PRESENT=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
@@ -151,6 +154,7 @@ CONFIG_SUN_AUXIO=y
 CONFIG_SUN_IO=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+CONFIG_ARCH_SUPPORTS_MSI=y
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 CONFIG_SUN_OPENPROMFS=m
@@ -178,7 +182,6 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -219,6 +222,7 @@ CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -292,6 +296,14 @@ CONFIG_NET_TCPPROBE=m
 # 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_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 
 #
@@ -312,10 +324,6 @@ CONFIG_FW_LOADER=y
 # Connector - unified userspace <-> kernelspace linker
 #
 CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -383,7 +391,6 @@ CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_BLK_DEV_OPTI621 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=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 CONFIG_BLK_DEV_ALI15X3=y
@@ -413,7 +420,6 @@ CONFIG_BLK_DEV_ALI15X3=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
 
 #
@@ -443,6 +449,7 @@ CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -485,6 +492,7 @@ CONFIG_ISCSI_TCP=m
 # 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_SUNESP is not set
 # CONFIG_SCSI_SRP is not set
 
@@ -628,9 +636,10 @@ CONFIG_BNX2=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
@@ -695,6 +704,12 @@ CONFIG_KEYBOARD_LKKBD=m
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 CONFIG_MOUSE_SERIAL=y
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
@@ -702,6 +717,7 @@ CONFIG_MOUSE_SERIAL=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_SPARCSPKR=y
 # CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Hardware I/O ports
@@ -763,11 +779,8 @@ CONFIG_RTC=y
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 
 #
@@ -791,17 +804,17 @@ CONFIG_I2C_ALGOBIT=y
 # 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_SIMTEC 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_TINY_USB 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
@@ -912,7 +925,7 @@ CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 
 #
-# Frambuffer hardware drivers
+# Frambuffer hardware drivers
 #
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
@@ -937,6 +950,8 @@ CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_XVR500 is not set
+# CONFIG_FB_XVR2500 is not set
 # CONFIG_FB_PCI is not set
 # CONFIG_FB_VIRTUAL is not set
 
@@ -1093,6 +1108,14 @@ CONFIG_AC97_BUS=m
 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=y
+
 #
 # USB support
 #
@@ -1106,6 +1129,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_OTG is not set
 
@@ -1156,10 +1180,6 @@ CONFIG_USB_STORAGE=m
 #
 # USB Input Devices
 #
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_ACECAD is not set
@@ -1524,6 +1544,7 @@ CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_LRW=m
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
index eff0c01..6bf6fb6 100644 (file)
@@ -17,7 +17,7 @@ obj-y         := process.o setup.o cpu.o idprom.o \
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-$(CONFIG_PCI)       += ebus.o isa.o pci_common.o pci_iommu.o \
                            pci_psycho.o pci_sabre.o pci_schizo.o \
-                           pci_sun4v.o pci_sun4v_asm.o
+                           pci_sun4v.o pci_sun4v_asm.o pci_fire.o
 obj-$(CONFIG_SMP)       += smp.o trampoline.o
 obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
 obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
index c65b2f9..8230099 100644 (file)
@@ -98,7 +98,7 @@ void apply_central_ranges(struct linux_central *central,
                            central->num_central_ranges);
 }
 
-void * __init central_alloc_bootmem(unsigned long size)
+static void * __init central_alloc_bootmem(unsigned long size)
 {
        void *ret;
 
@@ -116,7 +116,7 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
        return ret | (unsigned long) r->phys_addr;
 }
 
-static void probe_other_fhcs(void)
+static void __init probe_other_fhcs(void)
 {
        struct device_node *dp;
        const struct linux_prom64_registers *fpregs;
@@ -298,7 +298,7 @@ static void init_all_fhc_hw(void)
 
 }
 
-void central_probe(void)
+void __init central_probe(void)
 {
        struct linux_prom_registers fpregs[6];
        const struct linux_prom_registers *pr;
index 6241e3d..3edc18e 100644 (file)
@@ -279,7 +279,7 @@ static void sun4u_irq_enable(unsigned int virt_irq)
        struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
        if (likely(data)) {
-               unsigned long cpuid, imap;
+               unsigned long cpuid, imap, val;
                unsigned int tid;
 
                cpuid = irq_choose_cpu(virt_irq);
@@ -287,7 +287,11 @@ static void sun4u_irq_enable(unsigned int virt_irq)
 
                tid = sun4u_compute_tid(imap, cpuid);
 
-               upa_writel(tid | IMAP_VALID, imap);
+               val = upa_readq(imap);
+               val &= ~(IMAP_TID_UPA | IMAP_TID_JBUS |
+                        IMAP_AID_SAFARI | IMAP_NID_SAFARI);
+               val |= tid | IMAP_VALID;
+               upa_writeq(val, imap);
        }
 }
 
@@ -297,10 +301,10 @@ static void sun4u_irq_disable(unsigned int virt_irq)
 
        if (likely(data)) {
                unsigned long imap = data->imap;
-               u32 tmp = upa_readl(imap);
+               u32 tmp = upa_readq(imap);
 
                tmp &= ~IMAP_VALID;
-               upa_writel(tmp, imap);
+               upa_writeq(tmp, imap);
        }
 }
 
@@ -309,7 +313,7 @@ static void sun4u_irq_end(unsigned int virt_irq)
        struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
        if (likely(data))
-               upa_writel(ICLR_IDLE, data->iclr);
+               upa_writeq(ICLR_IDLE, data->iclr);
 }
 
 static void sun4v_irq_enable(unsigned int virt_irq)
@@ -465,7 +469,7 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
 
        BUG_ON(tlb_type == hypervisor);
 
-       ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
+       ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
        bucket = &ivector_table[ino];
        if (!bucket->virt_irq) {
                bucket->virt_irq = virt_irq_alloc(__irq(bucket));
index 023af41..af2c7ff 100644 (file)
@@ -190,6 +190,7 @@ extern void schizo_init(struct device_node *, const char *);
 extern void schizo_plus_init(struct device_node *, const char *);
 extern void tomatillo_init(struct device_node *, const char *);
 extern void sun4v_pci_init(struct device_node *, const char *);
+extern void fire_pci_init(struct device_node *, const char *);
 
 static struct {
        char *model_name;
@@ -207,6 +208,7 @@ static struct {
        { "SUNW,tomatillo", tomatillo_init },
        { "pci108e,a801", tomatillo_init },
        { "SUNW,sun4v-pci", sun4v_pci_init },
+       { "pciex108e,80f0", fire_pci_init },
 };
 #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
                                  sizeof(pci_controller_table[0]))
@@ -436,6 +438,13 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
        printk("    class: 0x%x device name: %s\n",
               dev->class, pci_name(dev));
 
+       /* I have seen IDE devices which will not respond to
+        * the bmdma simplex check reads if bus mastering is
+        * disabled.
+        */
+       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
+               pci_set_master(dev);
+
        dev->current_state = 4;         /* unknown power state */
        dev->error_state = pci_channel_io_normal;
 
@@ -468,7 +477,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
        return dev;
 }
 
-static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
+static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
 {
        u32 idx, first, last;
 
@@ -497,9 +506,9 @@ static void __init pci_resource_adjust(struct resource *res,
 /* Cook up fake bus resources for SUNW,simba PCI bridges which lack
  * a proper 'ranges' property.
  */
-static void __init apb_fake_ranges(struct pci_dev *dev,
-                                  struct pci_bus *bus,
-                                  struct pci_pbm_info *pbm)
+static void __devinit apb_fake_ranges(struct pci_dev *dev,
+                                     struct pci_bus *bus,
+                                     struct pci_pbm_info *pbm)
 {
        struct resource *res;
        u32 first, last;
@@ -522,15 +531,15 @@ static void __init apb_fake_ranges(struct pci_dev *dev,
        pci_resource_adjust(res, &pbm->mem_space);
 }
 
-static void __init pci_of_scan_bus(struct pci_pbm_info *pbm,
-                                  struct device_node *node,
-                                  struct pci_bus *bus);
+static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
+                                     struct device_node *node,
+                                     struct pci_bus *bus);
 
 #define GET_64BIT(prop, i)     ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
 
-void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
-                                 struct device_node *node,
-                                 struct pci_dev *dev)
+static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
+                                        struct device_node *node,
+                                        struct pci_dev *dev)
 {
        struct pci_bus *bus;
        const u32 *busrange, *ranges;
@@ -629,9 +638,9 @@ simba_cont:
        pci_of_scan_bus(pbm, node, bus);
 }
 
-static void __init pci_of_scan_bus(struct pci_pbm_info *pbm,
-                                  struct device_node *node,
-                                  struct pci_bus *bus)
+static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
+                                     struct device_node *node,
+                                     struct pci_bus *bus)
 {
        struct device_node *child;
        const u32 *reg;
@@ -733,7 +742,7 @@ int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
        return PCIBIOS_SUCCESSFUL;
 }
 
-struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm)
+struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
 {
        struct pci_controller_info *p = pbm->parent;
        struct device_node *node = pbm->prom_node;
@@ -1092,10 +1101,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)
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c
new file mode 100644 (file)
index 0000000..0fe6266
--- /dev/null
@@ -0,0 +1,418 @@
+/* pci_fire.c: Sun4u platform PCI-E controller support.
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <asm/pbm.h>
+#include <asm/oplib.h>
+#include <asm/prom.h>
+
+#include "pci_impl.h"
+
+#define fire_read(__reg) \
+({     u64 __ret; \
+       __asm__ __volatile__("ldxa [%1] %2, %0" \
+                            : "=r" (__ret) \
+                            : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+                            : "memory"); \
+       __ret; \
+})
+#define fire_write(__reg, __val) \
+       __asm__ __volatile__("stxa %0, [%1] %2" \
+                            : /* no outputs */ \
+                            : "r" (__val), "r" (__reg), \
+                              "i" (ASI_PHYS_BYPASS_EC_E) \
+                            : "memory")
+
+/* Fire config space address format is nearly identical to
+ * that of SCHIZO and PSYCHO, except that in order to accomodate
+ * PCI-E extended config space the encoding can handle 12 bits
+ * of register address:
+ *
+ *  32     28 27 20 19    15 14      12 11  2  1 0
+ * -------------------------------------------------
+ * |0 0 0 0 0| bus | device | function | reg | 0 0 |
+ * -------------------------------------------------
+ */
+#define FIRE_CONFIG_BASE(PBM)  ((PBM)->config_space)
+#define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG)    \
+       (((unsigned long)(BUS)   << 20) |       \
+        ((unsigned long)(DEVFN) << 12)  |      \
+        ((unsigned long)(REG)))
+
+static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm,
+                                     unsigned char bus,
+                                     unsigned int devfn,
+                                     int where)
+{
+       if (!pbm)
+               return NULL;
+       return (void *)
+               (FIRE_CONFIG_BASE(pbm) |
+                FIRE_CONFIG_ENCODE(bus, devfn, where));
+}
+
+/* FIRE PCI configuration space accessors. */
+
+static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+                            int where, int size, u32 *value)
+{
+       struct pci_pbm_info *pbm = bus_dev->sysdata;
+       unsigned char bus = bus_dev->number;
+       u32 *addr;
+       u16 tmp16;
+       u8 tmp8;
+
+       if (bus_dev == pbm->pci_bus && devfn == 0x00)
+               return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
+                                                   size, value);
+       switch (size) {
+       case 1:
+               *value = 0xff;
+               break;
+       case 2:
+               *value = 0xffff;
+               break;
+       case 4:
+               *value = 0xffffffff;
+               break;
+       }
+
+       addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
+       if (!addr)
+               return PCIBIOS_SUCCESSFUL;
+
+       switch (size) {
+       case 1:
+               pci_config_read8((u8 *)addr, &tmp8);
+               *value = tmp8;
+               break;
+
+       case 2:
+               if (where & 0x01) {
+                       printk("pci_read_config_word: misaligned reg [%x]\n",
+                              where);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               pci_config_read16((u16 *)addr, &tmp16);
+               *value = tmp16;
+               break;
+
+       case 4:
+               if (where & 0x03) {
+                       printk("pci_read_config_dword: misaligned reg [%x]\n",
+                              where);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+
+               pci_config_read32(addr, value);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+                             int where, int size, u32 value)
+{
+       struct pci_pbm_info *pbm = bus_dev->sysdata;
+       unsigned char bus = bus_dev->number;
+       u32 *addr;
+
+       if (bus_dev == pbm->pci_bus && devfn == 0x00)
+               return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
+                                                    size, value);
+       addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
+       if (!addr)
+               return PCIBIOS_SUCCESSFUL;
+
+       switch (size) {
+       case 1:
+               pci_config_write8((u8 *)addr, value);
+               break;
+
+       case 2:
+               if (where & 0x01) {
+                       printk("pci_write_config_word: misaligned reg [%x]\n",
+                              where);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               pci_config_write16((u16 *)addr, value);
+               break;
+
+       case 4:
+               if (where & 0x03) {
+                       printk("pci_write_config_dword: misaligned reg [%x]\n",
+                              where);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+
+               pci_config_write32(addr, value);
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_fire_ops = {
+       .read   =       fire_read_pci_cfg,
+       .write  =       fire_write_pci_cfg,
+};
+
+static void pbm_scan_bus(struct pci_controller_info *p,
+                        struct pci_pbm_info *pbm)
+{
+       pbm->pci_bus = pci_scan_one_pbm(pbm);
+}
+
+static void pci_fire_scan_bus(struct pci_controller_info *p)
+{
+       struct device_node *dp;
+
+       if ((dp = p->pbm_A.prom_node) != NULL)
+               pbm_scan_bus(p, &p->pbm_A);
+
+       if ((dp = p->pbm_B.prom_node) != NULL)
+               pbm_scan_bus(p, &p->pbm_B);
+
+       /* XXX register error interrupt handlers XXX */
+}
+
+#define FIRE_IOMMU_CONTROL     0x40000UL
+#define FIRE_IOMMU_TSBBASE     0x40008UL
+#define FIRE_IOMMU_FLUSH       0x40100UL
+#define FIRE_IOMMU_FLUSHINV    0x40100UL
+
+static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
+{
+       struct iommu *iommu = pbm->iommu;
+       u32 vdma[2], dma_mask;
+       u64 control;
+       int tsbsize;
+
+       /* No virtual-dma property on these guys, use largest size.  */
+       vdma[0] = 0xc0000000; /* base */
+       vdma[1] = 0x40000000; /* size */
+       dma_mask = 0xffffffff;
+       tsbsize = 128;
+
+       /* Register addresses. */
+       iommu->iommu_control  = pbm->pbm_regs + FIRE_IOMMU_CONTROL;
+       iommu->iommu_tsbbase  = pbm->pbm_regs + FIRE_IOMMU_TSBBASE;
+       iommu->iommu_flush    = pbm->pbm_regs + FIRE_IOMMU_FLUSH;
+       iommu->iommu_flushinv = pbm->pbm_regs + FIRE_IOMMU_FLUSHINV;
+
+       /* We use the main control/status register of FIRE as the write
+        * completion register.
+        */
+       iommu->write_complete_reg = pbm->controller_regs + 0x410000UL;
+
+       /*
+        * Invalidate TLB Entries.
+        */
+       fire_write(iommu->iommu_flushinv, ~(u64)0);
+
+       pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+
+       fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL);
+
+       control = fire_read(iommu->iommu_control);
+       control |= (0x00000400 /* TSB cache snoop enable */     |
+                   0x00000300 /* Cache mode */                 |
+                   0x00000002 /* Bypass enable */              |
+                   0x00000001 /* Translation enable */);
+       fire_write(iommu->iommu_control, control);
+}
+
+/* Based at pbm->controller_regs */
+#define FIRE_PARITY_CONTROL    0x470010UL
+#define  FIRE_PARITY_ENAB      0x8000000000000000UL
+#define FIRE_FATAL_RESET_CTL   0x471028UL
+#define  FIRE_FATAL_RESET_SPARE        0x0000000004000000UL
+#define  FIRE_FATAL_RESET_MB   0x0000000002000000UL
+#define  FIRE_FATAL_RESET_CPE  0x0000000000008000UL
+#define  FIRE_FATAL_RESET_APE  0x0000000000004000UL
+#define  FIRE_FATAL_RESET_PIO  0x0000000000000040UL
+#define  FIRE_FATAL_RESET_JW   0x0000000000000004UL
+#define  FIRE_FATAL_RESET_JI   0x0000000000000002UL
+#define  FIRE_FATAL_RESET_JR   0x0000000000000001UL
+#define FIRE_CORE_INTR_ENABLE  0x471800UL
+
+/* Based at pbm->pbm_regs */
+#define FIRE_TLU_CTRL          0x80000UL
+#define  FIRE_TLU_CTRL_TIM     0x00000000da000000UL
+#define  FIRE_TLU_CTRL_QDET    0x0000000000000100UL
+#define  FIRE_TLU_CTRL_CFG     0x0000000000000001UL
+#define FIRE_TLU_DEV_CTRL      0x90008UL
+#define FIRE_TLU_LINK_CTRL     0x90020UL
+#define FIRE_TLU_LINK_CTRL_CLK 0x0000000000000040UL
+#define FIRE_LPU_RESET         0xe2008UL
+#define FIRE_LPU_LLCFG         0xe2200UL
+#define  FIRE_LPU_LLCFG_VC0    0x0000000000000100UL
+#define FIRE_LPU_FCTRL_UCTRL   0xe2240UL
+#define  FIRE_LPU_FCTRL_UCTRL_N        0x0000000000000002UL
+#define  FIRE_LPU_FCTRL_UCTRL_P        0x0000000000000001UL
+#define FIRE_LPU_TXL_FIFOP     0xe2430UL
+#define FIRE_LPU_LTSSM_CFG2    0xe2788UL
+#define FIRE_LPU_LTSSM_CFG3    0xe2790UL
+#define FIRE_LPU_LTSSM_CFG4    0xe2798UL
+#define FIRE_LPU_LTSSM_CFG5    0xe27a0UL
+#define FIRE_DMC_IENAB         0x31800UL
+#define FIRE_DMC_DBG_SEL_A     0x53000UL
+#define FIRE_DMC_DBG_SEL_B     0x53008UL
+#define FIRE_PEC_IENAB         0x51800UL
+
+static void pci_fire_hw_init(struct pci_pbm_info *pbm)
+{
+       u64 val;
+
+       fire_write(pbm->controller_regs + FIRE_PARITY_CONTROL,
+                  FIRE_PARITY_ENAB);
+
+       fire_write(pbm->controller_regs + FIRE_FATAL_RESET_CTL,
+                  (FIRE_FATAL_RESET_SPARE |
+                   FIRE_FATAL_RESET_MB |
+                   FIRE_FATAL_RESET_CPE |
+                   FIRE_FATAL_RESET_APE |
+                   FIRE_FATAL_RESET_PIO |
+                   FIRE_FATAL_RESET_JW |
+                   FIRE_FATAL_RESET_JI |
+                   FIRE_FATAL_RESET_JR));
+
+       fire_write(pbm->controller_regs + FIRE_CORE_INTR_ENABLE, ~(u64)0);
+
+       val = fire_read(pbm->pbm_regs + FIRE_TLU_CTRL);
+       val |= (FIRE_TLU_CTRL_TIM |
+               FIRE_TLU_CTRL_QDET |
+               FIRE_TLU_CTRL_CFG);
+       fire_write(pbm->pbm_regs + FIRE_TLU_CTRL, val);
+       fire_write(pbm->pbm_regs + FIRE_TLU_DEV_CTRL, 0);
+       fire_write(pbm->pbm_regs + FIRE_TLU_LINK_CTRL,
+                  FIRE_TLU_LINK_CTRL_CLK);
+
+       fire_write(pbm->pbm_regs + FIRE_LPU_RESET, 0);
+       fire_write(pbm->pbm_regs + FIRE_LPU_LLCFG,
+                  FIRE_LPU_LLCFG_VC0);
+       fire_write(pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL,
+                  (FIRE_LPU_FCTRL_UCTRL_N |
+                   FIRE_LPU_FCTRL_UCTRL_P));
+       fire_write(pbm->pbm_regs + FIRE_LPU_TXL_FIFOP,
+                  ((0xffff << 16) | (0x0000 << 0)));
+       fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2, 3000000);
+       fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3, 500000);
+       fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4,
+                  (2 << 16) | (140 << 8));
+       fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5, 0);
+
+       fire_write(pbm->pbm_regs + FIRE_DMC_IENAB, ~(u64)0);
+       fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_A, 0);
+       fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_B, 0);
+
+       fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0);
+}
+
+static void pci_fire_pbm_init(struct pci_controller_info *p,
+                               struct device_node *dp, u32 portid)
+{
+       const struct linux_prom64_registers *regs;
+       struct pci_pbm_info *pbm;
+       const u32 *ino_bitmap;
+       const unsigned int *busrange;
+
+       if ((portid & 1) == 0)
+               pbm = &p->pbm_A;
+       else
+               pbm = &p->pbm_B;
+
+       pbm->portid = portid;
+       pbm->parent = p;
+       pbm->prom_node = dp;
+       pbm->name = dp->full_name;
+
+       regs = of_get_property(dp, "reg", NULL);
+       pbm->pbm_regs = regs[0].phys_addr;
+       pbm->controller_regs = regs[1].phys_addr - 0x410000UL;
+
+       printk("%s: SUN4U PCIE Bus Module\n", pbm->name);
+
+       pci_determine_mem_io_space(pbm);
+
+       ino_bitmap = of_get_property(dp, "ino-bitmap", NULL);
+       pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
+                          ((u64)ino_bitmap[0] <<  0UL));
+
+       busrange = of_get_property(dp, "bus-range", NULL);
+       pbm->pci_first_busno = busrange[0];
+       pbm->pci_last_busno = busrange[1];
+
+       pci_fire_hw_init(pbm);
+       pci_fire_pbm_iommu_init(pbm);
+}
+
+static inline int portid_compare(u32 x, u32 y)
+{
+       if (x == (y ^ 1))
+               return 1;
+       return 0;
+}
+
+void fire_pci_init(struct device_node *dp, const char *model_name)
+{
+       struct pci_controller_info *p;
+       u32 portid = of_getintprop_default(dp, "portid", 0xff);
+       struct iommu *iommu;
+
+       for (p = pci_controller_root; p; p = p->next) {
+               struct pci_pbm_info *pbm;
+
+               if (p->pbm_A.prom_node && p->pbm_B.prom_node)
+                       continue;
+
+               pbm = (p->pbm_A.prom_node ?
+                      &p->pbm_A :
+                      &p->pbm_B);
+
+               if (portid_compare(pbm->portid, portid)) {
+                       pci_fire_pbm_init(p, dp, portid);
+                       return;
+               }
+       }
+
+       p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+       if (!p)
+               goto fatal_memory_error;
+
+       iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
+       if (!iommu)
+               goto fatal_memory_error;
+
+       p->pbm_A.iommu = iommu;
+
+       iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
+       if (!iommu)
+               goto fatal_memory_error;
+
+       p->pbm_B.iommu = iommu;
+
+       p->next = pci_controller_root;
+       pci_controller_root = p;
+
+       p->index = pci_num_controllers++;
+
+       p->scan_bus = pci_fire_scan_bus;
+       /* XXX MSI support XXX */
+       p->pci_ops = &pci_fire_ops;
+
+       /* Like PSYCHO and SCHIZO we have a 2GB aligned area
+        * for memory space.
+        */
+       pci_memspace_mask = 0x7fffffffUL;
+
+       pci_fire_pbm_init(p, dp, portid);
+       return;
+
+fatal_memory_error:
+       prom_printf("PCI_FIRE: Fatal memory allocation error.\n");
+       prom_halt();
+}
index 6671277..9e405cb 100644 (file)
 /* Must be invoked under the IOMMU lock. */
 static void __iommu_flushall(struct iommu *iommu)
 {
-       unsigned long tag;
-       int entry;
+       if (iommu->iommu_flushinv) {
+               pci_iommu_write(iommu->iommu_flushinv, ~(u64)0);
+       } else {
+               unsigned long tag;
+               int entry;
 
-       tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
-       for (entry = 0; entry < 16; entry++) {
-               pci_iommu_write(tag, 0);
-               tag += 8;
-       }
+               tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
+               for (entry = 0; entry < 16; entry++) {
+                       pci_iommu_write(tag, 0);
+                       tag += 8;
+               }
 
-       /* Ensure completion of previous PIO writes. */
-       (void) pci_iommu_read(iommu->write_complete_reg);
+               /* Ensure completion of previous PIO writes. */
+               (void) pci_iommu_read(iommu->write_complete_reg);
+       }
 }
 
 #define IOPTE_CONSISTENT(CTX) \
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 5e1fcd0..c54d4d8 100644 (file)
@@ -386,11 +386,9 @@ static unsigned int psycho_irq_build(struct device_node *dp,
 
        /* Now build the IRQ bucket. */
        imap = controller_regs + imap_off;
-       imap += 4;
 
        iclr_off = psycho_iclr_offset(ino);
        iclr = controller_regs + iclr_off;
-       iclr += 4;
 
        if ((ino & 0x20) == 0)
                inofixup = ino & 0x03;
@@ -398,7 +396,7 @@ static unsigned int psycho_irq_build(struct device_node *dp,
        return build_irq(inofixup, iclr, imap);
 }
 
-static void psycho_irq_trans_init(struct device_node *dp)
+static void __init psycho_irq_trans_init(struct device_node *dp)
 {
        const struct linux_prom64_registers *regs;
 
@@ -613,11 +611,9 @@ static unsigned int sabre_irq_build(struct device_node *dp,
 
        /* Now build the IRQ bucket. */
        imap = controller_regs + imap_off;
-       imap += 4;
 
        iclr_off = sabre_iclr_offset(ino);
        iclr = controller_regs + iclr_off;
-       iclr += 4;
 
        if ((ino & 0x20) == 0)
                inofixup = ino & 0x03;
@@ -640,7 +636,7 @@ static unsigned int sabre_irq_build(struct device_node *dp,
        return virt_irq;
 }
 
-static void sabre_irq_trans_init(struct device_node *dp)
+static void __init sabre_irq_trans_init(struct device_node *dp)
 {
        const struct linux_prom64_registers *regs;
        struct sabre_irq_data *irq_data;
@@ -679,13 +675,14 @@ static unsigned long schizo_iclr_offset(unsigned long ino)
 static unsigned long schizo_ino_to_iclr(unsigned long pbm_regs,
                                        unsigned int ino)
 {
-       return pbm_regs + schizo_iclr_offset(ino) + 4;
+
+       return pbm_regs + schizo_iclr_offset(ino);
 }
 
 static unsigned long schizo_ino_to_imap(unsigned long pbm_regs,
                                        unsigned int ino)
 {
-       return pbm_regs + schizo_imap_offset(ino) + 4;
+       return pbm_regs + schizo_imap_offset(ino);
 }
 
 #define schizo_read(__reg) \
@@ -796,7 +793,8 @@ static unsigned int schizo_irq_build(struct device_node *dp,
        return virt_irq;
 }
 
-static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo)
+static void __init __schizo_irq_trans_init(struct device_node *dp,
+                                          int is_tomatillo)
 {
        const struct linux_prom64_registers *regs;
        struct schizo_irq_data *irq_data;
@@ -818,12 +816,12 @@ static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo)
        irq_data->chip_version = of_getintprop_default(dp, "version#", 0);
 }
 
-static void schizo_irq_trans_init(struct device_node *dp)
+static void __init schizo_irq_trans_init(struct device_node *dp)
 {
        __schizo_irq_trans_init(dp, 0);
 }
 
-static void tomatillo_irq_trans_init(struct device_node *dp)
+static void __init tomatillo_irq_trans_init(struct device_node *dp)
 {
        __schizo_irq_trans_init(dp, 1);
 }
@@ -837,7 +835,7 @@ static unsigned int pci_sun4v_irq_build(struct device_node *dp,
        return sun4v_build_irq(devhandle, devino);
 }
 
-static void pci_sun4v_irq_trans_init(struct device_node *dp)
+static void __init pci_sun4v_irq_trans_init(struct device_node *dp)
 {
        const struct linux_prom64_registers *regs;
 
@@ -848,6 +846,85 @@ static void pci_sun4v_irq_trans_init(struct device_node *dp)
        dp->irq_trans->data = (void *) (unsigned long)
                ((regs->phys_addr >> 32UL) & 0x0fffffff);
 }
+
+struct fire_irq_data {
+       unsigned long pbm_regs;
+       u32 portid;
+};
+
+#define FIRE_IMAP_BASE 0x001000
+#define FIRE_ICLR_BASE 0x001400
+
+static unsigned long fire_imap_offset(unsigned long ino)
+{
+       return FIRE_IMAP_BASE + (ino * 8UL);
+}
+
+static unsigned long fire_iclr_offset(unsigned long ino)
+{
+       return FIRE_ICLR_BASE + (ino * 8UL);
+}
+
+static unsigned long fire_ino_to_iclr(unsigned long pbm_regs,
+                                           unsigned int ino)
+{
+       return pbm_regs + fire_iclr_offset(ino);
+}
+
+static unsigned long fire_ino_to_imap(unsigned long pbm_regs,
+                                           unsigned int ino)
+{
+       return pbm_regs + fire_imap_offset(ino);
+}
+
+static unsigned int fire_irq_build(struct device_node *dp,
+                                        unsigned int ino,
+                                        void *_data)
+{
+       struct fire_irq_data *irq_data = _data;
+       unsigned long pbm_regs = irq_data->pbm_regs;
+       unsigned long imap, iclr;
+       unsigned long int_ctrlr;
+
+       ino &= 0x3f;
+
+       /* Now build the IRQ bucket. */
+       imap = fire_ino_to_imap(pbm_regs, ino);
+       iclr = fire_ino_to_iclr(pbm_regs, ino);
+
+       /* Set the interrupt controller number.  */
+       int_ctrlr = 1 << 6;
+       upa_writeq(int_ctrlr, imap);
+
+       /* The interrupt map registers do not have an INO field
+        * like other chips do.  They return zero in the INO
+        * field, and the interrupt controller number is controlled
+        * in bits 6 thru 9.  So in order for build_irq() to get
+        * the INO right we pass it in as part of the fixup
+        * which will get added to the map register zero value
+        * read by build_irq().
+        */
+       ino |= (irq_data->portid << 6);
+       ino -= int_ctrlr;
+       return build_irq(ino, iclr, imap);
+}
+
+static void __init fire_irq_trans_init(struct device_node *dp)
+{
+       const struct linux_prom64_registers *regs;
+       struct fire_irq_data *irq_data;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = fire_irq_build;
+
+       irq_data = prom_early_alloc(sizeof(struct fire_irq_data));
+
+       regs = of_get_property(dp, "reg", NULL);
+       dp->irq_trans->data = irq_data;
+
+       irq_data->pbm_regs = regs[0].phys_addr;
+       irq_data->portid = of_getintprop_default(dp, "portid", 0);
+}
 #endif /* CONFIG_PCI */
 
 #ifdef CONFIG_SBUS
@@ -995,7 +1072,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp,
        return build_irq(sbus_level, iclr, imap);
 }
 
-static void sbus_irq_trans_init(struct device_node *dp)
+static void __init sbus_irq_trans_init(struct device_node *dp)
 {
        const struct linux_prom64_registers *regs;
 
@@ -1042,7 +1119,7 @@ static unsigned int central_build_irq(struct device_node *dp,
        return build_irq(0, iclr, imap);
 }
 
-static void central_irq_trans_init(struct device_node *dp)
+static void __init central_irq_trans_init(struct device_node *dp)
 {
        dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
        dp->irq_trans->irq_build = central_build_irq;
@@ -1056,7 +1133,7 @@ struct irq_trans {
 };
 
 #ifdef CONFIG_PCI
-static struct irq_trans pci_irq_trans_table[] = {
+static struct irq_trans __initdata pci_irq_trans_table[] = {
        { "SUNW,sabre", sabre_irq_trans_init },
        { "pci108e,a000", sabre_irq_trans_init },
        { "pci108e,a001", sabre_irq_trans_init },
@@ -1069,6 +1146,7 @@ static struct irq_trans pci_irq_trans_table[] = {
        { "SUNW,tomatillo", tomatillo_irq_trans_init },
        { "pci108e,a801", tomatillo_irq_trans_init },
        { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init },
+       { "pciex108e,80f0", fire_irq_trans_init },
 };
 #endif
 
@@ -1081,7 +1159,7 @@ static unsigned int sun4v_vdev_irq_build(struct device_node *dp,
        return sun4v_build_irq(devhandle, devino);
 }
 
-static void sun4v_vdev_irq_trans_init(struct device_node *dp)
+static void __init sun4v_vdev_irq_trans_init(struct device_node *dp)
 {
        const struct linux_prom64_registers *regs;
 
@@ -1093,7 +1171,7 @@ static void sun4v_vdev_irq_trans_init(struct device_node *dp)
                ((regs->phys_addr >> 32UL) & 0x0fffffff);
 }
 
-static void irq_trans_init(struct device_node *dp)
+static void __init irq_trans_init(struct device_node *dp)
 {
 #ifdef CONFIG_PCI
        const char *model;
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 00677b5..e224a94 100644 (file)
@@ -175,6 +175,12 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
        if (len > task_size)
                return -ENOMEM;
 
+       if (flags & MAP_FIXED) {
+               if (prepare_hugepage_range(addr, len, pgoff))
+                       return -EINVAL;
+               return addr;
+       }
+
        if (addr) {
                addr = ALIGN(addr, HPAGE_SIZE);
                vma = find_vma(mm, addr);
index cafadcb..d7004ea 100644 (file)
@@ -164,30 +164,6 @@ unsigned long sparc64_kern_sec_context __read_mostly;
 
 int bigkernel = 0;
 
-struct kmem_cache *pgtable_cache __read_mostly;
-
-static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
-{
-       clear_page(addr);
-}
-
-extern void tsb_cache_init(void);
-
-void pgtable_cache_init(void)
-{
-       pgtable_cache = kmem_cache_create("pgtable_cache",
-                                         PAGE_SIZE, PAGE_SIZE,
-                                         SLAB_HWCACHE_ALIGN |
-                                         SLAB_MUST_HWCACHE_ALIGN,
-                                         zero_ctor,
-                                         NULL);
-       if (!pgtable_cache) {
-               prom_printf("Could not create pgtable_cache\n");
-               prom_halt();
-       }
-       tsb_cache_init();
-}
-
 #ifdef CONFIG_DEBUG_DCFLUSH
 atomic_t dcpage_flushes = ATOMIC_INIT(0);
 #ifdef CONFIG_SMP
index 236d02f..8eb8a7c 100644 (file)
@@ -252,7 +252,7 @@ static const char *tsb_cache_names[8] = {
        "tsb_1MB",
 };
 
-void __init tsb_cache_init(void)
+void __init pgtable_cache_init(void)
 {
        unsigned long i;
 
@@ -262,8 +262,7 @@ void __init tsb_cache_init(void)
 
                tsb_caches[i] = kmem_cache_create(name,
                                                  size, size,
-                                                 SLAB_HWCACHE_ALIGN |
-                                                 SLAB_MUST_HWCACHE_ALIGN,
+                                                 0,
                                                  NULL, NULL);
                if (!tsb_caches[i]) {
                        prom_printf("Could not create %s cache\n", name);
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 9fdfad6..3aa3516 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/tty_flip.h>
 #include <asm/irq.h>
 #include "chan_kern.h"
-#include "user_util.h"
 #include "kern.h"
 #include "irq_user.h"
 #include "sigio.h"
index 0cad354..13f0bf8 100644 (file)
@@ -14,7 +14,6 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include "kern_util.h"
-#include "user_util.h"
 #include "chan_user.h"
 #include "user.h"
 #include "os.h"
@@ -158,7 +157,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
         */
        err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
        if(err < 0){
-               printk("fork of winch_thread failed - errno = %d\n", errno);
+               printk("fork of winch_thread failed - errno = %d\n", -err);
                goto out_close;
        }
 
@@ -204,14 +203,3 @@ void register_winch(int fd, struct tty_struct *tty)
                }
        }
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index c6a3084..1545384 100644 (file)
@@ -2,14 +2,13 @@
 #define __COW_SYS_H__
 
 #include "kern_util.h"
-#include "user_util.h"
 #include "os.h"
 #include "user.h"
 #include "um_malloc.h"
 
 static inline void *cow_malloc(int size)
 {
-       return(um_kmalloc(size));
+       return um_kmalloc(size);
 }
 
 static inline void cow_free(void *ptr)
@@ -21,29 +20,22 @@ static inline void cow_free(void *ptr)
 
 static inline char *cow_strdup(char *str)
 {
-       return(uml_strdup(str));
+       return uml_strdup(str);
 }
 
 static inline int cow_seek_file(int fd, __u64 offset)
 {
-       return(os_seek_file(fd, offset));
+       return os_seek_file(fd, offset);
 }
 
 static inline int cow_file_size(char *file, unsigned long long *size_out)
 {
-       return(os_file_size(file, size_out));
+       return os_file_size(file, size_out);
 }
 
 static inline int cow_write_file(int fd, void *buf, int size)
 {
-       return(os_write_file(fd, buf, size));
+       return os_write_file(fd, buf, size);
 }
 
 #endif
-
-/*
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 021b82c..b869e38 100644 (file)
@@ -14,7 +14,6 @@
 #include "net_user.h"
 #include "daemon.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 #include "um_malloc.h"
@@ -39,11 +38,11 @@ static struct sockaddr_un *new_addr(void *name, int len)
        sun = um_kmalloc(sizeof(struct sockaddr_un));
        if(sun == NULL){
                printk("new_addr: allocation of sockaddr_un failed\n");
-               return(NULL);
+               return NULL;
        }
        sun->sun_family = AF_UNIX;
        memcpy(sun->sun_path, name, len);
-       return(sun);
+       return sun;
 }
 
 static int connect_to_switch(struct daemon_data *pri)
@@ -112,7 +111,7 @@ static int connect_to_switch(struct daemon_data *pri)
        }
 
        pri->data_addr = sun;
-       return(fd);
+       return fd;
 
  out_free:
        kfree(sun);
@@ -120,10 +119,10 @@ static int connect_to_switch(struct daemon_data *pri)
        os_close_file(fd);
  out:
        os_close_file(pri->control);
-       return(err);
+       return err;
 }
 
-static void daemon_user_init(void *data, void *dev)
+static int daemon_user_init(void *data, void *dev)
 {
        struct daemon_data *pri = data;
        struct timeval tv;
@@ -146,13 +145,16 @@ static void daemon_user_init(void *data, void *dev)
        if(pri->fd < 0){
                kfree(pri->local_addr);
                pri->local_addr = NULL;
+               return pri->fd;
        }
+
+       return 0;
 }
 
 static int daemon_open(void *data)
 {
        struct daemon_data *pri = data;
-       return(pri->fd);
+       return pri->fd;
 }
 
 static void daemon_remove(void *data)
@@ -176,12 +178,12 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
 {
        struct sockaddr_un *data_addr = pri->data_addr;
 
-       return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)));
+       return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
 }
 
 static int daemon_set_mtu(int mtu, void *data)
 {
-       return(mtu);
+       return mtu;
 }
 
 const struct net_user_info daemon_user_info = {
@@ -194,14 +196,3 @@ const struct net_user_info daemon_user_info = {
        .delete_address = NULL,
        .max_packet     = MAX_PACKET - ETH_HEADER_OTHER
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 218aa0e..7f083ec 100644 (file)
@@ -9,7 +9,6 @@
 #include <termios.h>
 #include <errno.h>
 #include "user.h"
-#include "user_util.h"
 #include "chan_user.h"
 #include "os.h"
 #include "um_malloc.h"
index c495ecf..5eeecf8 100644 (file)
@@ -6,7 +6,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
-#include "user_util.h"
 #include "user.h"
 #include "mconsole.h"
 #include "os.h"
index f75d7b0..ced9910 100644 (file)
@@ -13,7 +13,6 @@
 #include "irq_user.h"
 #include "line.h"
 #include "kern.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
 #include "irq_kern.h"
index b827e82..d319db1 100644 (file)
@@ -20,7 +20,6 @@
 #include "net_user.h"
 #include "mcast.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 #include "um_malloc.h"
@@ -34,20 +33,21 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
        sin = um_kmalloc(sizeof(struct sockaddr_in));
        if(sin == NULL){
                printk("new_addr: allocation of sockaddr_in failed\n");
-               return(NULL);
+               return NULL;
        }
        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = in_aton(addr);
        sin->sin_port = htons(port);
-       return(sin);
+       return sin;
 }
 
-static void mcast_user_init(void *data, void *dev)
+static int mcast_user_init(void *data, void *dev)
 {
        struct mcast_data *pri = data;
 
        pri->mcast_addr = new_addr(pri->addr, pri->port);
        pri->dev = dev;
+       return 0;
 }
 
 static void mcast_remove(void *data)
@@ -107,8 +107,8 @@ static int mcast_open(void *data)
                err = -errno;
                printk("mcast_open : data bind failed, errno = %d\n", errno);
                goto out_close;
-       }               
-       
+       }
+
        /* subscribe to the multicast group */
        mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
        mreq.imr_interface.s_addr = 0;
@@ -153,12 +153,12 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
 {
        struct sockaddr_in *data_addr = pri->mcast_addr;
 
-       return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)));
+       return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
 }
 
 static int mcast_set_mtu(int mtu, void *data)
 {
-       return(mtu);
+       return mtu;
 }
 
 const struct net_user_info mcast_user_info = {
index 65ad293..542c9ef 100644 (file)
@@ -25,7 +25,6 @@
 #include "linux/console.h"
 #include "asm/irq.h"
 #include "asm/uaccess.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "mconsole.h"
index f02634f..62e5ad6 100644 (file)
@@ -17,7 +17,6 @@
 #include "sysdep/ptrace.h"
 #include "mconsole.h"
 #include "os.h"
-#include "user_util.h"
 
 static struct mconsole_command commands[] = {
        /* With uts namespaces, uts information becomes process-specific, so
index df3516e..e41a08f 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/miscdevice.h>
 #include <asm/uaccess.h>
 #include "mem_user.h"
-#include "user_util.h"
  
 /* These are set in mmapper_init, which is called at boot time */
 static unsigned long mmapper_size;
index 8593037..baac4ad 100644 (file)
@@ -21,7 +21,6 @@
 #include "linux/ethtool.h"
 #include "linux/platform_device.h"
 #include "asm/uaccess.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "net_kern.h"
 #include "net_user.h"
@@ -284,7 +283,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
 #endif
 }
 
-static void setup_etheraddr(char *str, unsigned char *addr)
+static void setup_etheraddr(char *str, unsigned char *addr, char *name)
 {
        char *end;
        int i;
@@ -303,15 +302,32 @@ static void setup_etheraddr(char *str, unsigned char *addr)
                }
                str = end + 1;
        }
-       if(addr[0] & 1){
+       if (is_multicast_ether_addr(addr)) {
                printk(KERN_ERR
-                      "Attempt to assign a broadcast ethernet address to a "
+                      "Attempt to assign a multicast ethernet address to a "
                       "device disallowed\n");
                goto random;
        }
+       if (!is_valid_ether_addr(addr)) {
+               printk(KERN_ERR
+                      "Attempt to assign an invalid ethernet address to a "
+                      "device disallowed\n");
+               goto random;
+       }
+       if (!is_local_ether_addr(addr)) {
+               printk(KERN_WARNING
+                      "Warning: attempt to assign a globally valid ethernet address to a "
+                      "device\n");
+               printk(KERN_WARNING "You should better enable the 2nd rightmost bit "
+                     "in the first byte of the MAC, i.e. "
+                     "%02x:%02x:%02x:%02x:%02x:%02x\n",
+                     addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], addr[5]);
+       }
        return;
 
 random:
+       printk(KERN_INFO
+              "Choosing a random ethernet address for device %s\n", name);
        random_ether_addr(addr);
 }
 
@@ -325,31 +341,53 @@ static struct platform_driver uml_net_driver = {
 };
 static int driver_registered;
 
-static int eth_configure(int n, void *init, char *mac,
-                        struct transport *transport)
+static void net_device_release(struct device *dev)
+{
+       struct uml_net *device = dev->driver_data;
+       struct net_device *netdev = device->dev;
+       struct uml_net_private *lp = netdev->priv;
+
+       if(lp->remove != NULL)
+               (*lp->remove)(&lp->user);
+       list_del(&device->list);
+       kfree(device);
+       free_netdev(netdev);
+}
+
+static void eth_configure(int n, void *init, char *mac,
+                         struct transport *transport)
 {
        struct uml_net *device;
        struct net_device *dev;
        struct uml_net_private *lp;
-       int save, err, size;
+       int err, size;
 
-       size = transport->private_size + sizeof(struct uml_net_private) +
-               sizeof(((struct uml_net_private *) 0)->user);
+       size = transport->private_size + sizeof(struct uml_net_private);
 
        device = kzalloc(sizeof(*device), GFP_KERNEL);
        if (device == NULL) {
-               printk(KERN_ERR "eth_configure failed to allocate uml_net\n");
-               return(1);
+               printk(KERN_ERR "eth_configure failed to allocate struct "
+                      "uml_net\n");
+               return;
+       }
+
+       dev = alloc_etherdev(size);
+       if (dev == NULL) {
+               printk(KERN_ERR "eth_configure: failed to allocate struct "
+                      "net_device for eth%d\n", n);
+               goto out_free_device;
        }
 
        INIT_LIST_HEAD(&device->list);
        device->index = n;
 
-       spin_lock(&devices_lock);
-       list_add(&device->list, &devices);
-       spin_unlock(&devices_lock);
+       /* If this name ends up conflicting with an existing registered
+        * netdevice, that is OK, register_netdev{,ice}() will notice this
+        * and fail.
+        */
+       snprintf(dev->name, sizeof(dev->name), "eth%d", n);
 
-       setup_etheraddr(mac, device->mac);
+       setup_etheraddr(mac, device->mac, dev->name);
 
        printk(KERN_INFO "Netdevice %d ", n);
        printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
@@ -357,11 +395,6 @@ static int eth_configure(int n, void *init, char *mac,
               device->mac[2], device->mac[3],
               device->mac[4], device->mac[5]);
        printk(": ");
-       dev = alloc_etherdev(size);
-       if (dev == NULL) {
-               printk(KERN_ERR "eth_configure: failed to allocate device\n");
-               return 1;
-       }
 
        lp = dev->priv;
        /* This points to the transport private data. It's still clear, but we
@@ -376,47 +409,20 @@ static int eth_configure(int n, void *init, char *mac,
        }
        device->pdev.id = n;
        device->pdev.name = DRIVER_NAME;
-       platform_device_register(&device->pdev);
+       device->pdev.dev.release = net_device_release;
+       device->pdev.dev.driver_data = device;
+       if(platform_device_register(&device->pdev))
+               goto out_free_netdev;
        SET_NETDEV_DEV(dev,&device->pdev.dev);
 
-       /* If this name ends up conflicting with an existing registered
-        * netdevice, that is OK, register_netdev{,ice}() will notice this
-        * and fail.
-        */
-       snprintf(dev->name, sizeof(dev->name), "eth%d", n);
        device->dev = dev;
 
+       /*
+        * These just fill in a data structure, so there's no failure
+        * to be worried about.
+        */
        (*transport->kern->init)(dev, init);
 
-       dev->mtu = transport->user->max_packet;
-       dev->open = uml_net_open;
-       dev->hard_start_xmit = uml_net_start_xmit;
-       dev->stop = uml_net_close;
-       dev->get_stats = uml_net_get_stats;
-       dev->set_multicast_list = uml_net_set_multicast_list;
-       dev->tx_timeout = uml_net_tx_timeout;
-       dev->set_mac_address = uml_net_set_mac;
-       dev->change_mtu = uml_net_change_mtu;
-       dev->ethtool_ops = &uml_net_ethtool_ops;
-       dev->watchdog_timeo = (HZ >> 1);
-       dev->irq = UM_ETH_IRQ;
-
-       rtnl_lock();
-       err = register_netdevice(dev);
-       rtnl_unlock();
-       if (err) {
-               device->dev = NULL;
-               /* XXX: should we call ->remove() here? */
-               free_netdev(dev);
-               return 1;
-       }
-
-       /* lp.user is the first four bytes of the transport data, which
-        * has already been initialized.  This structure assignment will
-        * overwrite that, so we make sure that .user gets overwritten with
-        * what it already has.
-        */
-       save = lp->user[0];
        *lp = ((struct uml_net_private)
                { .list                 = LIST_HEAD_INIT(lp->list),
                  .dev                  = dev,
@@ -430,20 +436,52 @@ static int eth_configure(int n, void *init, char *mac,
                  .write                = transport->kern->write,
                  .add_address          = transport->user->add_address,
                  .delete_address       = transport->user->delete_address,
-                 .set_mtu              = transport->user->set_mtu,
-                 .user                 = { save } });
+                 .set_mtu              = transport->user->set_mtu });
 
        init_timer(&lp->tl);
        spin_lock_init(&lp->lock);
        lp->tl.function = uml_net_user_timer_expire;
        memcpy(lp->mac, device->mac, sizeof(lp->mac));
 
-       if (transport->user->init)
-               (*transport->user->init)(&lp->user, dev);
+       if ((transport->user->init != NULL) &&
+           ((*transport->user->init)(&lp->user, dev) != 0))
+               goto out_unregister;
 
        set_ether_mac(dev, device->mac);
+       dev->mtu = transport->user->max_packet;
+       dev->open = uml_net_open;
+       dev->hard_start_xmit = uml_net_start_xmit;
+       dev->stop = uml_net_close;
+       dev->get_stats = uml_net_get_stats;
+       dev->set_multicast_list = uml_net_set_multicast_list;
+       dev->tx_timeout = uml_net_tx_timeout;
+       dev->set_mac_address = uml_net_set_mac;
+       dev->change_mtu = uml_net_change_mtu;
+       dev->ethtool_ops = &uml_net_ethtool_ops;
+       dev->watchdog_timeo = (HZ >> 1);
+       dev->irq = UM_ETH_IRQ;
 
-       return 0;
+       rtnl_lock();
+       err = register_netdevice(dev);
+       rtnl_unlock();
+       if (err)
+               goto out_undo_user_init;
+
+       spin_lock(&devices_lock);
+       list_add(&device->list, &devices);
+       spin_unlock(&devices_lock);
+
+       return;
+
+out_undo_user_init:
+       if (transport->user->remove != NULL)
+               (*transport->user->remove)(&lp->user);
+out_unregister:
+       platform_device_unregister(&device->pdev);
+out_free_netdev:
+       free_netdev(dev);
+out_free_device:
+       kfree(device);
 }
 
 static struct uml_net *find_device(int n)
@@ -666,13 +704,9 @@ static int net_remove(int n, char **error_out)
        lp = dev->priv;
        if(lp->fd > 0)
                return -EBUSY;
-       if(lp->remove != NULL) (*lp->remove)(&lp->user);
        unregister_netdev(dev);
        platform_device_unregister(&device->pdev);
 
-       list_del(&device->list);
-       kfree(device);
-       free_netdev(dev);
        return 0;
 }
 
index 0ffd7ac..3503cff 100644 (file)
 #include <sys/wait.h>
 #include <sys/time.h>
 #include "user.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "net_user.h"
 #include "os.h"
 #include "um_malloc.h"
+#include "kern_constants.h"
 
 int tap_open_common(void *dev, char *gate_addr)
 {
@@ -216,7 +216,7 @@ static void change(char *dev, char *what, unsigned char *addr,
        sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], 
                netmask[2], netmask[3]);
 
-       output_len = page_size();
+       output_len = UM_KERN_PAGE_SIZE;
        output = um_kmalloc(output_len);
        if(output == NULL)
                printk("change : failed to allocate output buffer\n");
index 11921a7..dc0a903 100644 (file)
@@ -18,7 +18,7 @@
 
 #define PCAP_FD(p) (*(int *)(p))
 
-static void pcap_user_init(void *data, void *dev)
+static int pcap_user_init(void *data, void *dev)
 {
        struct pcap_data *pri = data;
        pcap_t *p;
@@ -28,11 +28,12 @@ static void pcap_user_init(void *data, void *dev)
        if(p == NULL){
                printk("pcap_user_init : pcap_open_live failed - '%s'\n", 
                       errors);
-               return;
+               return -EINVAL;
        }
 
        pri->dev = dev;
        pri->pcap = p;
+       return 0;
 }
 
 static int pcap_open(void *data)
@@ -42,39 +43,39 @@ static int pcap_open(void *data)
        int err;
 
        if(pri->pcap == NULL)
-               return(-ENODEV);
+               return -ENODEV;
 
        if(pri->filter != NULL){
                err = dev_netmask(pri->dev, &netmask);
                if(err < 0){
                        printk("pcap_open : dev_netmask failed\n");
-                       return(-EIO);
+                       return -EIO;
                }
 
                pri->compiled = um_kmalloc(sizeof(struct bpf_program));
                if(pri->compiled == NULL){
                        printk("pcap_open : kmalloc failed\n");
-                       return(-ENOMEM);
+                       return -ENOMEM;
                }
-               
+
                err = pcap_compile(pri->pcap, 
                                   (struct bpf_program *) pri->compiled, 
                                   pri->filter, pri->optimize, netmask);
                if(err < 0){
                        printk("pcap_open : pcap_compile failed - '%s'\n", 
                               pcap_geterr(pri->pcap));
-                       return(-EIO);
+                       return -EIO;
                }
 
                err = pcap_setfilter(pri->pcap, pri->compiled);
                if(err < 0){
                        printk("pcap_open : pcap_setfilter failed - '%s'\n", 
                               pcap_geterr(pri->pcap));
-                       return(-EIO);
+                       return -EIO;
                }
        }
-       
-       return(PCAP_FD(pri->pcap));
+
+       return PCAP_FD(pri->pcap);
 }
 
 static void pcap_remove(void *data)
@@ -114,11 +115,11 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
        n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
        if(n < 0){
                printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap));
-               return(-EIO);
+               return -EIO;
        }
        else if(n == 0) 
-               return(0);
-       return(hdata.len);
+               return 0;
+       return hdata.len;
 }
 
 const struct net_user_info pcap_user_info = {
@@ -131,14 +132,3 @@ const struct net_user_info pcap_user_info = {
        .delete_address = NULL,
        .max_packet     = MAX_PACKET - ETH_HEADER_OTHER
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 8050802..3f6357d 100644 (file)
@@ -13,7 +13,6 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <netinet/in.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "chan_user.h"
index 829a5ec..df4976c 100644 (file)
@@ -4,13 +4,13 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <termios.h>
 #include "chan_user.h"
 #include "user.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
index 7eddacc..78f0e51 100644 (file)
@@ -8,7 +8,6 @@
 #include <sys/termios.h>
 #include <sys/wait.h>
 #include <sys/signal.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "net_user.h"
 #include "slip_common.h"
 #include "os.h"
 #include "um_malloc.h"
+#include "kern_constants.h"
 
-void slip_user_init(void *data, void *dev)
+static int slip_user_init(void *data, void *dev)
 {
        struct slip_data *pri = data;
 
        pri->dev = dev;
+       return 0;
 }
 
 static int set_up_tty(int fd)
@@ -89,7 +90,7 @@ static int slip_tramp(char **argv, int fd)
                goto out_close;
        pid = err;
 
-       output_len = page_size();
+       output_len = UM_KERN_PAGE_SIZE;
        output = um_kmalloc(output_len);
        if(output == NULL){
                printk("slip_tramp : failed to allocate output buffer\n");
index ce5e85d..39f889f 100644 (file)
@@ -7,7 +7,6 @@
 #include <errno.h>
 #include <sys/wait.h>
 #include <sys/signal.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "net_user.h"
 #include "slip_common.h"
 #include "os.h"
 
-void slirp_user_init(void *data, void *dev)
+static int slirp_user_init(void *data, void *dev)
 {
        struct slirp_data *pri = data;
 
        pri->dev = dev;
+       return 0;
 }
 
 struct slirp_pre_exec_data {
index 4b382a6..fd09ad9 100644 (file)
@@ -15,7 +15,6 @@
 #include "line.h"
 #include "ssl.h"
 #include "chan_kern.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "init.h"
@@ -192,12 +191,12 @@ static int ssl_init(void)
        ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
                                    ARRAY_SIZE(serial_lines));
 
-       lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
-
        new_title = add_xterm_umid(opts.xterm_title);
        if (new_title != NULL)
                opts.xterm_title = new_title;
 
+       lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
+
        ssl_init_done = 1;
        register_console(&ssl_cons);
        return 0;
index 76d1f1c..2bb4193 100644 (file)
@@ -22,7 +22,6 @@
 #include "stdio_console.h"
 #include "line.h"
 #include "chan_kern.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
@@ -167,12 +166,12 @@ int stdio_init(void)
                return -1;
        printk(KERN_INFO "Initialized stdio console driver\n");
 
-       lines_init(vts, ARRAY_SIZE(vts), &opts);
-
        new_title = add_xterm_umid(opts.xterm_title);
        if(new_title != NULL)
                opts.xterm_title = new_title;
 
+       lines_init(vts, ARRAY_SIZE(vts), &opts);
+
        con_init_done = 1;
        register_console(&stdiocons);
        return 0;
index d95d643..c07d0d5 100644 (file)
@@ -8,7 +8,6 @@
 #include <errno.h>
 #include <unistd.h>
 #include "chan_user.h"
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 #include "um_malloc.h"
index 8bd9204..70509dd 100644 (file)
@@ -39,7 +39,6 @@
 #include "asm/irq.h"
 #include "asm/types.h"
 #include "asm/tlbflush.h"
-#include "user_util.h"
 #include "mem_user.h"
 #include "kern_util.h"
 #include "kern.h"
@@ -90,7 +89,7 @@ static inline int ubd_test_bit(__u64 bit, unsigned char *data)
        bits = sizeof(data[0]) * 8;
        n = bit / bits;
        off = bit % bits;
-       return((data[n] & (1 << off)) != 0);
+       return (data[n] & (1 << off)) != 0;
 }
 
 static inline void ubd_set_bit(__u64 bit, unsigned char *data)
@@ -147,10 +146,13 @@ struct cow {
        unsigned long *bitmap;
        unsigned long bitmap_len;
        int bitmap_offset;
-        int data_offset;
+       int data_offset;
 };
 
+#define MAX_SG 64
+
 struct ubd {
+       struct list_head restart;
        /* name (and fd, below) of the file opened for writing, either the
         * backing or the cow file. */
        char *file;
@@ -165,15 +167,17 @@ struct ubd {
        struct platform_device pdev;
        struct request_queue *queue;
        spinlock_t lock;
-       int active;
+       struct scatterlist sg[MAX_SG];
+       struct request *request;
+       int start_sg, end_sg;
 };
 
 #define DEFAULT_COW { \
        .file =                 NULL, \
-        .fd =                  -1, \
-        .bitmap =              NULL, \
+       .fd =                   -1,     \
+       .bitmap =               NULL, \
        .bitmap_offset =        0, \
-        .data_offset =         0, \
+       .data_offset =          0, \
 }
 
 #define DEFAULT_UBD { \
@@ -183,11 +187,13 @@ struct ubd {
        .size =                 -1, \
        .boot_openflags =       OPEN_FLAGS, \
        .openflags =            OPEN_FLAGS, \
-        .no_cow =               0, \
+       .no_cow =               0, \
        .shared =               0, \
-        .cow =                 DEFAULT_COW, \
+       .cow =                  DEFAULT_COW, \
        .lock =                 SPIN_LOCK_UNLOCKED,     \
-       .active =               0, \
+       .request =              NULL, \
+       .start_sg =             0, \
+       .end_sg =               0, \
 }
 
 /* Protected by ubd_lock */
@@ -243,7 +249,7 @@ static void make_ide_entries(char *dev_name)
 static int fake_ide_setup(char *str)
 {
        fake_ide = 1;
-       return(1);
+       return 1;
 }
 
 __setup("fake_ide", fake_ide_setup);
@@ -261,7 +267,7 @@ static int parse_unit(char **ptr)
        if(isdigit(*str)) {
                n = simple_strtoul(str, &end, 0);
                if(end == str)
-                       return(-1);
+                       return -1;
                *ptr = end;
        }
        else if (('a' <= *str) && (*str <= 'z')) {
@@ -269,7 +275,7 @@ static int parse_unit(char **ptr)
                str++;
                *ptr = str;
        }
-       return(n);
+       return n;
 }
 
 /* If *index_out == -1 at exit, the passed option was a general one;
@@ -436,7 +442,7 @@ static int udb_setup(char *str)
 {
        printk("udb%s specified on command line is almost certainly a ubd -> "
               "udb TYPO\n", str);
-       return(1);
+       return 1;
 }
 
 __setup("udb", udb_setup);
@@ -467,66 +473,75 @@ static void do_ubd_request(request_queue_t * q);
 /* Only changed by ubd_init, which is an initcall. */
 int thread_fd = -1;
 
-/* call ubd_finish if you need to serialize */
-static void __ubd_finish(struct request *req, int error)
+static void ubd_end_request(struct request *req, int bytes, int uptodate)
 {
-       int nsect;
-
-       if(error){
-               end_request(req, 0);
-               return;
+       if (!end_that_request_first(req, uptodate, bytes >> 9)) {
+               struct ubd *dev = req->rq_disk->private_data;
+               unsigned long flags;
+
+               add_disk_randomness(req->rq_disk);
+               spin_lock_irqsave(&dev->lock, flags);
+               end_that_request_last(req, uptodate);
+               spin_unlock_irqrestore(&dev->lock, flags);
        }
-       nsect = req->current_nr_sectors;
-       req->sector += nsect;
-       req->buffer += nsect << 9;
-       req->errors = 0;
-       req->nr_sectors -= nsect;
-       req->current_nr_sectors = 0;
-       end_request(req, 1);
 }
 
 /* Callable only from interrupt context - otherwise you need to do
  * spin_lock_irq()/spin_lock_irqsave() */
-static inline void ubd_finish(struct request *req, int error)
+static inline void ubd_finish(struct request *req, int bytes)
 {
-       struct ubd *dev = req->rq_disk->private_data;
-
-       spin_lock(&dev->lock);
-       __ubd_finish(req, error);
-       spin_unlock(&dev->lock);
+       if(bytes < 0){
+               ubd_end_request(req, 0, 0);
+               return;
+       }
+       ubd_end_request(req, bytes, 1);
 }
 
+static LIST_HEAD(restart);
+
 /* XXX - move this inside ubd_intr. */
 /* Called without dev->lock held, and only in interrupt context. */
 static void ubd_handler(void)
 {
-       struct io_thread_req req;
+       struct io_thread_req *req;
        struct request *rq;
-       struct ubd *dev;
+       struct ubd *ubd;
+       struct list_head *list, *next_ele;
+       unsigned long flags;
        int n;
 
-       n = os_read_file(thread_fd, &req, sizeof(req));
-       if(n != sizeof(req)){
-               printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
-                      "err = %d\n", os_getpid(), -n);
-               return;
-       }
-
-       rq = req.req;
-       dev = rq->rq_disk->private_data;
-       dev->active = 0;
+       while(1){
+               n = os_read_file(thread_fd, &req,
+                                sizeof(struct io_thread_req *));
+               if(n != sizeof(req)){
+                       if(n == -EAGAIN)
+                               break;
+                       printk(KERN_ERR "spurious interrupt in ubd_handler, "
+                              "err = %d\n", -n);
+                       return;
+               }
 
-       ubd_finish(rq, req.error);
+               rq = req->req;
+               rq->nr_sectors -= req->length >> 9;
+               if(rq->nr_sectors == 0)
+                       ubd_finish(rq, rq->hard_nr_sectors << 9);
+               kfree(req);
+       }
        reactivate_fd(thread_fd, UBD_IRQ);
-       spin_lock(&dev->lock);
-       do_ubd_request(dev->queue);
-       spin_unlock(&dev->lock);
+
+       list_for_each_safe(list, next_ele, &restart){
+               ubd = container_of(list, struct ubd, restart);
+               list_del_init(&ubd->restart);
+               spin_lock_irqsave(&ubd->lock, flags);
+               do_ubd_request(ubd->queue);
+               spin_unlock_irqrestore(&ubd->lock, flags);
+       }
 }
 
 static irqreturn_t ubd_intr(int irq, void *dev)
 {
        ubd_handler();
-       return(IRQ_HANDLED);
+       return IRQ_HANDLED;
 }
 
 /* Only changed by ubd_init, which is an initcall. */
@@ -545,7 +560,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
        char *file;
 
        file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
-       return(os_file_size(file, size_out));
+       return os_file_size(file, size_out);
 }
 
 static void ubd_close_dev(struct ubd *ubd_dev)
@@ -617,10 +632,18 @@ static int ubd_open_dev(struct ubd *ubd_dev)
                if(err < 0) goto error;
                ubd_dev->cow.fd = err;
        }
-       return(0);
+       return 0;
  error:
        os_close_file(ubd_dev->fd);
-       return(err);
+       return err;
+}
+
+static void ubd_device_release(struct device *dev)
+{
+       struct ubd *ubd_dev = dev->driver_data;
+
+       blk_cleanup_queue(ubd_dev->queue);
+       *ubd_dev = ((struct ubd) DEFAULT_UBD);
 }
 
 static int ubd_disk_register(int major, u64 size, int unit,
@@ -630,7 +653,7 @@ static int ubd_disk_register(int major, u64 size, int unit,
 
        disk = alloc_disk(1 << UBD_SHIFT);
        if(disk == NULL)
-               return(-ENOMEM);
+               return -ENOMEM;
 
        disk->major = major;
        disk->first_minor = unit << UBD_SHIFT;
@@ -645,6 +668,8 @@ static int ubd_disk_register(int major, u64 size, int unit,
        if (major == MAJOR_NR) {
                ubd_devs[unit].pdev.id   = unit;
                ubd_devs[unit].pdev.name = DRIVER_NAME;
+               ubd_devs[unit].pdev.dev.release = ubd_device_release;
+               ubd_devs[unit].pdev.dev.driver_data = &ubd_devs[unit];
                platform_device_register(&ubd_devs[unit].pdev);
                disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
        }
@@ -675,6 +700,8 @@ static int ubd_add(int n, char **error_out)
 
        ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
 
+       INIT_LIST_HEAD(&ubd_dev->restart);
+
        err = -ENOMEM;
        ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
        if (ubd_dev->queue == NULL) {
@@ -683,6 +710,7 @@ static int ubd_add(int n, char **error_out)
        }
        ubd_dev->queue->queuedata = ubd_dev;
 
+       blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG);
        err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
        if(err){
                *error_out = "Failed to register device";
@@ -730,14 +758,14 @@ static int ubd_config(char *str, char **error_out)
                goto err_free;
        }
 
-       mutex_lock(&ubd_lock);
+       mutex_lock(&ubd_lock);
        ret = ubd_add(n, error_out);
        if (ret)
                ubd_devs[n].file = NULL;
-       mutex_unlock(&ubd_lock);
+       mutex_unlock(&ubd_lock);
 
 out:
-       return ret;
+       return ret;
 
 err_free:
        kfree(str);
@@ -752,7 +780,7 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
        n = parse_unit(&name);
        if((n >= MAX_DEV) || (n < 0)){
                *error_out = "ubd_get_config : device number out of range";
-               return(-1);
+               return -1;
        }
 
        ubd_dev = &ubd_devs[n];
@@ -773,29 +801,27 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
 
  out:
        mutex_unlock(&ubd_lock);
-       return(len);
+       return len;
 }
 
 static int ubd_id(char **str, int *start_out, int *end_out)
 {
-        int n;
+       int n;
 
        n = parse_unit(str);
-        *start_out = 0;
-        *end_out = MAX_DEV - 1;
-        return n;
+       *start_out = 0;
+       *end_out = MAX_DEV - 1;
+       return n;
 }
 
 static int ubd_remove(int n, char **error_out)
 {
+       struct gendisk *disk = ubd_gendisk[n];
        struct ubd *ubd_dev;
        int err = -ENODEV;
 
        mutex_lock(&ubd_lock);
 
-       if(ubd_gendisk[n] == NULL)
-               goto out;
-
        ubd_dev = &ubd_devs[n];
 
        if(ubd_dev->file == NULL)
@@ -806,9 +832,11 @@ static int ubd_remove(int n, char **error_out)
        if(ubd_dev->count > 0)
                goto out;
 
-       del_gendisk(ubd_gendisk[n]);
-       put_disk(ubd_gendisk[n]);
        ubd_gendisk[n] = NULL;
+       if(disk != NULL){
+               del_gendisk(disk);
+               put_disk(disk);
+       }
 
        if(fake_gendisk[n] != NULL){
                del_gendisk(fake_gendisk[n]);
@@ -816,10 +844,8 @@ static int ubd_remove(int n, char **error_out)
                fake_gendisk[n] = NULL;
        }
 
-       blk_cleanup_queue(ubd_dev->queue);
-       platform_device_unregister(&ubd_dev->pdev);
-       *ubd_dev = ((struct ubd) DEFAULT_UBD);
        err = 0;
+       platform_device_unregister(&ubd_dev->pdev);
 out:
        mutex_unlock(&ubd_lock);
        return err;
@@ -832,7 +858,7 @@ static struct mc_device ubd_mc = {
        .list           = LIST_HEAD_INIT(ubd_mc.list),
        .name           = "ubd",
        .config         = ubd_config,
-       .get_config     = ubd_get_config,
+       .get_config     = ubd_get_config,
        .id             = ubd_id,
        .remove         = ubd_remove,
 };
@@ -854,7 +880,7 @@ static int __init ubd0_init(void)
                ubd_dev->file = "root_fs";
        mutex_unlock(&ubd_lock);
 
-       return(0);
+       return 0;
 }
 
 __initcall(ubd0_init);
@@ -882,14 +908,14 @@ static int __init ubd_init(void)
                        return -1;
        }
        platform_driver_register(&ubd_driver);
-       mutex_lock(&ubd_lock);
+       mutex_lock(&ubd_lock);
        for (i = 0; i < MAX_DEV; i++){
                err = ubd_add(i, &error);
                if(err)
                        printk(KERN_ERR "Failed to initialize ubd device %d :"
                               "%s\n", i, error);
        }
-       mutex_unlock(&ubd_lock);
+       mutex_unlock(&ubd_lock);
        return 0;
 }
 
@@ -913,7 +939,7 @@ static int __init ubd_driver_init(void){
                       "ubd : Failed to start I/O thread (errno = %d) - "
                       "falling back to synchronous I/O\n", -io_pid);
                io_pid = -1;
-               return(0);
+               return 0;
        }
        err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
                             IRQF_DISABLED, "ubd", ubd_devs);
@@ -948,7 +974,7 @@ static int ubd_open(struct inode *inode, struct file *filp)
                err = -EROFS;
        }*/
  out:
-       return(err);
+       return err;
 }
 
 static int ubd_release(struct inode * inode, struct file * file)
@@ -958,7 +984,7 @@ static int ubd_release(struct inode * inode, struct file * file)
 
        if(--ubd_dev->count == 0)
                ubd_close_dev(ubd_dev);
-       return(0);
+       return 0;
 }
 
 static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
@@ -1014,7 +1040,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
                        if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
                                ubd_set_bit(i, (unsigned char *)
                                            &req->sector_mask);
-                }
+               }
        }
        else cowify_bitmap(req->offset, req->length, &req->sector_mask,
                           &req->cow_offset, bitmap, bitmap_offset,
@@ -1022,26 +1048,16 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
 }
 
 /* Called with dev->lock held */
-static int prepare_request(struct request *req, struct io_thread_req *io_req)
+static void prepare_request(struct request *req, struct io_thread_req *io_req,
+                           unsigned long long offset, int page_offset,
+                           int len, struct page *page)
 {
        struct gendisk *disk = req->rq_disk;
        struct ubd *ubd_dev = disk->private_data;
-       __u64 offset;
-       int len;
-
-       /* This should be impossible now */
-       if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){
-               printk("Write attempted on readonly ubd device %s\n",
-                      disk->disk_name);
-               end_request(req, 0);
-               return(1);
-       }
-
-       offset = ((__u64) req->sector) << 9;
-       len = req->current_nr_sectors << 9;
 
        io_req->req = req;
-       io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd;
+       io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd :
+               ubd_dev->fd;
        io_req->fds[1] = ubd_dev->fd;
        io_req->cow_offset = -1;
        io_req->offset = offset;
@@ -1052,45 +1068,66 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
        io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
        io_req->offsets[0] = 0;
        io_req->offsets[1] = ubd_dev->cow.data_offset;
-       io_req->buffer = req->buffer;
+       io_req->buffer = page_address(page) + page_offset;
        io_req->sectorsize = 1 << 9;
 
        if(ubd_dev->cow.file != NULL)
-               cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset,
-                          ubd_dev->cow.bitmap_len);
+               cowify_req(io_req, ubd_dev->cow.bitmap,
+                          ubd_dev->cow.bitmap_offset, ubd_dev->cow.bitmap_len);
 
-       return(0);
 }
 
 /* Called with dev->lock held */
 static void do_ubd_request(request_queue_t *q)
 {
-       struct io_thread_req io_req;
+       struct io_thread_req *io_req;
        struct request *req;
-       int err, n;
-
-       if(thread_fd == -1){
-               while((req = elv_next_request(q)) != NULL){
-                       err = prepare_request(req, &io_req);
-                       if(!err){
-                               do_io(&io_req);
-                               __ubd_finish(req, io_req.error);
-                       }
-               }
-       }
-       else {
+       int n;
+
+       while(1){
                struct ubd *dev = q->queuedata;
-               if(dev->active || (req = elv_next_request(q)) == NULL)
-                       return;
-               err = prepare_request(req, &io_req);
-               if(!err){
-                       dev->active = 1;
-                       n = os_write_file(thread_fd, (char *) &io_req,
-                                        sizeof(io_req));
-                       if(n != sizeof(io_req))
-                               printk("write to io thread failed, "
-                                      "errno = %d\n", -n);
+               if(dev->end_sg == 0){
+                       struct request *req = elv_next_request(q);
+                       if(req == NULL)
+                               return;
+
+                       dev->request = req;
+                       blkdev_dequeue_request(req);
+                       dev->start_sg = 0;
+                       dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
                }
+
+               req = dev->request;
+               while(dev->start_sg < dev->end_sg){
+                       struct scatterlist *sg = &dev->sg[dev->start_sg];
+
+                       io_req = kmalloc(sizeof(struct io_thread_req),
+                                        GFP_ATOMIC);
+                       if(io_req == NULL){
+                               if(list_empty(&dev->restart))
+                                       list_add(&dev->restart, &restart);
+                               return;
+                       }
+                       prepare_request(req, io_req,
+                                       (unsigned long long) req->sector << 9,
+                                       sg->offset, sg->length, sg->page);
+
+                       n = os_write_file(thread_fd, &io_req,
+                                         sizeof(struct io_thread_req *));
+                       if(n != sizeof(struct io_thread_req *)){
+                               if(n != -EAGAIN)
+                                       printk("write to io thread failed, "
+                                              "errno = %d\n", -n);
+                               else if(list_empty(&dev->restart))
+                                       list_add(&dev->restart, &restart);
+                               return;
+                       }
+
+                       req->sector += sg->length >> 9;
+                       dev->start_sg++;
+               }
+               dev->end_sg = 0;
+               dev->request = NULL;
        }
 }
 
@@ -1120,21 +1157,21 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
                ubd_id.cyls = ubd_dev->size / (128 * 32 * 512);
                if(copy_to_user((char __user *) arg, (char *) &ubd_id,
                                 sizeof(ubd_id)))
-                       return(-EFAULT);
-               return(0);
+                       return -EFAULT;
+               return 0;
 
        case CDROMVOLREAD:
                if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
-                       return(-EFAULT);
+                       return -EFAULT;
                volume.channel0 = 255;
                volume.channel1 = 255;
                volume.channel2 = 255;
                volume.channel3 = 255;
                if(copy_to_user((char __user *) arg, &volume, sizeof(volume)))
-                       return(-EFAULT);
-               return(0);
+                       return -EFAULT;
+               return 0;
        }
-       return(-EINVAL);
+       return -EINVAL;
 }
 
 static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
@@ -1176,29 +1213,29 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
        if(err < 0){
                printk("Failed to get modification time of backing file "
                       "\"%s\", err = %d\n", file, -err);
-               return(err);
+               return err;
        }
 
        err = os_file_size(file, &actual);
        if(err < 0){
                printk("Failed to get size of backing file \"%s\", "
                       "err = %d\n", file, -err);
-               return(err);
+               return err;
        }
 
-       if(actual != size){
+       if(actual != size){
                /*__u64 can be a long on AMD64 and with %lu GCC complains; so
                 * the typecast.*/
                printk("Size mismatch (%llu vs %llu) of COW header vs backing "
                       "file\n", (unsigned long long) size, actual);
-               return(-EINVAL);
+               return -EINVAL;
        }
        if(modtime != mtime){
                printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
                       "file\n", mtime, modtime);
-               return(-EINVAL);
+               return -EINVAL;
        }
-       return(0);
+       return 0;
 }
 
 int read_cow_bitmap(int fd, void *buf, int offset, int len)
@@ -1207,13 +1244,13 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
 
        err = os_seek_file(fd, offset);
        if(err < 0)
-               return(err);
+               return err;
 
        err = os_read_file(fd, buf, len);
        if(err < 0)
-               return(err);
+               return err;
 
-       return(0);
+       return 0;
 }
 
 int open_ubd_file(char *file, struct openflags *openflags, int shared,
@@ -1231,14 +1268,14 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
        if (fd < 0) {
                if ((fd == -ENOENT) && (create_cow_out != NULL))
                        *create_cow_out = 1;
-                if (!openflags->w ||
-                   ((fd != -EROFS) && (fd != -EACCES)))
+               if (!openflags->w ||
+                   ((fd != -EROFS) && (fd != -EACCES)))
                        return fd;
                openflags->w = 0;
                fd = os_open_file(file, *openflags, mode);
                if (fd < 0)
                        return fd;
-        }
+       }
 
        if(shared)
                printk("Not locking \"%s\" on the host\n", file);
@@ -1252,7 +1289,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
 
        /* Successful return case! */
        if(backing_file_out == NULL)
-               return(fd);
+               return fd;
 
        err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
                              &size, &sectorsize, &align, bitmap_offset_out);
@@ -1262,7 +1299,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
                goto out_close;
        }
        if(err)
-               return(fd);
+               return fd;
 
        asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
 
@@ -1285,7 +1322,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
        cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
                  bitmap_len_out, data_offset_out);
 
-        return fd;
+       return fd;
  out_close:
        os_close_file(fd);
        return err;
@@ -1310,10 +1347,10 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
                            bitmap_offset_out, bitmap_len_out,
                            data_offset_out);
        if(!err)
-               return(fd);
+               return fd;
        os_close_file(fd);
  out:
-       return(err);
+       return err;
 }
 
 static int update_bitmap(struct io_thread_req *req)
@@ -1321,23 +1358,23 @@ static int update_bitmap(struct io_thread_req *req)
        int n;
 
        if(req->cow_offset == -1)
-               return(0);
+               return 0;
 
        n = os_seek_file(req->fds[1], req->cow_offset);
        if(n < 0){
                printk("do_io - bitmap lseek failed : err = %d\n", -n);
-               return(1);
+               return 1;
        }
 
        n = os_write_file(req->fds[1], &req->bitmap_words,
-                         sizeof(req->bitmap_words));
+                         sizeof(req->bitmap_words));
        if(n != sizeof(req->bitmap_words)){
                printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
                       req->fds[1]);
-               return(1);
+               return 1;
        }
 
-       return(0);
+       return 0;
 }
 
 void do_io(struct io_thread_req *req)
@@ -1409,13 +1446,14 @@ static int io_count = 0;
 
 int io_thread(void *arg)
 {
-       struct io_thread_req req;
+       struct io_thread_req *req;
        int n;
 
        ignore_sigwinch_sig();
        while(1){
-               n = os_read_file(kernel_fd, &req, sizeof(req));
-               if(n != sizeof(req)){
+               n = os_read_file(kernel_fd, &req,
+                                sizeof(struct io_thread_req *));
+               if(n != sizeof(struct io_thread_req *)){
                        if(n < 0)
                                printk("io_thread - read failed, fd = %d, "
                                       "err = %d\n", kernel_fd, -n);
@@ -1426,9 +1464,10 @@ int io_thread(void *arg)
                        continue;
                }
                io_count++;
-               do_io(&req);
-               n = os_write_file(kernel_fd, &req, sizeof(req));
-               if(n != sizeof(req))
+               do_io(req);
+               n = os_write_file(kernel_fd, &req,
+                                 sizeof(struct io_thread_req *));
+               if(n != sizeof(struct io_thread_req *))
                        printk("io_thread - write failed, fd = %d, err = %d\n",
                               kernel_fd, -n);
        }
index b94d2bc..4707b3f 100644 (file)
@@ -16,7 +16,6 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "ubd_user.h"
@@ -47,8 +46,8 @@ int start_io_thread(unsigned long sp, int *fd_out)
        pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
                    NULL);
        if(pid < 0){
-               printk("start_io_thread - clone failed : errno = %d\n", errno);
                err = -errno;
+               printk("start_io_thread - clone failed : errno = %d\n", errno);
                goto out_close;
        }
 
@@ -60,16 +59,5 @@ int start_io_thread(unsigned long sp, int *fd_out)
        kernel_fd = -1;
        *fd_out = -1;
  out:
-       return(err);
+       return err;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 850221d..571c2b3 100644 (file)
@@ -14,7 +14,6 @@
 #include <sys/socket.h>
 #include "kern_util.h"
 #include "chan_user.h"
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 #include "xterm.h"
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
new file mode 100644 (file)
index 0000000..10ad52d
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __ARCH_H__
+#define __ARCH_H__
+
+#include "sysdep/ptrace.h"
+
+extern void arch_check_bugs(void);
+extern int arch_fixup(unsigned long address, union uml_pt_regs *regs);
+extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
+
+#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
new file mode 100644 (file)
index 0000000..fccf187
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __START_H__
+#define __START_H__
+
+#include "sysdep/ptrace.h"
+
+struct cpu_task {
+       int pid;
+       void *task;
+};
+
+extern struct cpu_task cpu_tasks[];
+
+extern unsigned long low_physmem;
+extern unsigned long high_physmem;
+extern unsigned long uml_physmem;
+extern unsigned long uml_reserved;
+extern unsigned long end_vm;
+extern unsigned long start_vm;
+extern unsigned long long highmem;
+
+extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
+extern unsigned long _unprotected_end;
+extern unsigned long brk_start;
+
+extern int linux_main(int argc, char **argv);
+extern void set_cmdline(char *cmd);
+
+extern void (*sig_info[])(int, union uml_pt_regs *);
+
+#endif
index 461175f..5593a80 100644 (file)
@@ -24,5 +24,7 @@ DEFINE(UM_ELF_CLASS, ELF_CLASS);
 DEFINE(UM_ELFCLASS32, ELFCLASS32);
 DEFINE(UM_ELFCLASS64, ELFCLASS64);
 
+DEFINE(UM_NR_CPUS, NR_CPUS);
+
 /* For crypto assembler code. */
 DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
index 173af02..50a4969 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "sysdep/ptrace.h"
 #include "sysdep/faultinfo.h"
+#include "uml-config.h"
 
 typedef void (*kern_hndl)(int, union uml_pt_regs *);
 
@@ -23,7 +24,6 @@ struct kern_handlers {
 extern const struct kern_handlers handlinfo_kern;
 
 extern int ncpus;
-extern char *linux_prog;
 extern char *gdb_init;
 extern int kmalloc_ok;
 extern int jail;
@@ -34,7 +34,9 @@ extern int nsyscalls;
        UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
 
 extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
+#ifdef UML_CONFIG_MODE_TT
 extern unsigned long stack_sp(unsigned long page);
+#endif
 extern int kernel_thread_proc(void *data);
 extern void syscall_segv(int sig);
 extern int current_pid(void);
@@ -42,7 +44,7 @@ extern unsigned long alloc_stack(int order, int atomic);
 extern int do_signal(void);
 extern int is_stack_fault(unsigned long sp);
 extern unsigned long segv(struct faultinfo fi, unsigned long ip,
-                         int is_user, void *sc);
+                         int is_user, union uml_pt_regs *regs);
 extern int handle_page_fault(unsigned long address, unsigned long ip,
                             int is_write, int is_user, int *code_out);
 extern void syscall_ready(void);
@@ -50,7 +52,6 @@ extern void set_tracing(void *t, int tracing);
 extern int is_tracing(void *task);
 extern int segv_syscall(void);
 extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
-extern int page_size(void);
 extern unsigned long page_mask(void);
 extern int need_finish_fork(void);
 extern void free_stack(unsigned long stack, int order);
@@ -58,7 +59,6 @@ extern void add_input_request(int op, void (*proc)(int), void *arg);
 extern char *current_cmd(void);
 extern void timer_handler(int sig, union uml_pt_regs *regs);
 extern int set_signals(int enable);
-extern void force_sigbus(void);
 extern int pid_to_processor_id(int pid);
 extern void deliver_signals(void *t);
 extern int next_trap_index(int max);
@@ -70,7 +70,6 @@ extern void *syscall_sp(void *t);
 extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
 extern int hz(void);
 extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
-extern int external_pid(void *t);
 extern void interrupt_end(void);
 extern void initial_thread_cb(void (*proc)(void *), void *arg);
 extern int debugger_signal(int status, int pid);
@@ -81,7 +80,6 @@ extern int init_parent_proxy(int pid);
 extern int singlestepping(void *t);
 extern void check_stack_overflow(void *ptr);
 extern void relay_signal(int sig, union uml_pt_regs *regs);
-extern void not_implemented(void);
 extern int user_context(unsigned long sp);
 extern void timer_irq(union uml_pt_regs *regs);
 extern void unprotect_stack(unsigned long stack);
@@ -93,7 +91,6 @@ extern char *uml_strdup(char *string);
 extern void unprotect_kernel_mem(void);
 extern void protect_kernel_mem(void);
 extern void uml_cleanup(void);
-extern void set_current(void *t);
 extern void lock_signalled_task(void *t);
 extern void IPI_handler(int cpu);
 extern int jail_setup(char *line, int *add);
@@ -118,4 +115,6 @@ extern void time_init_kern(void);
 extern int __cant_sleep(void);
 extern void sigio_handler(int sig, union uml_pt_regs *regs);
 
+extern void copy_sc(union uml_pt_regs *regs, void *from);
+
 #endif
index 125ab42..9237056 100644 (file)
@@ -40,7 +40,7 @@ struct uml_net_private {
        void (*add_address)(unsigned char *, unsigned char *, void *);
        void (*delete_address)(unsigned char *, unsigned char *, void *);
        int (*set_mtu)(int mtu, void *);
-       int user[1];
+       char user[0];
 };
 
 struct net_kern_info {
index 19f207c..cfe7c50 100644 (file)
@@ -14,7 +14,7 @@
 #define UML_NET_VERSION (4)
 
 struct net_user_info {
-       void (*init)(void *, void *);
+       int (*init)(void *, void *);
        int (*open)(void *);
        void (*close)(int, void *);
        void (*remove)(void *);
index 5c74da4..688d181 100644 (file)
@@ -16,6 +16,8 @@
 #include "sysdep/tls.h"
 #include "sysdep/archsetjmp.h"
 
+#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
+
 #define OS_TYPE_FILE 1
 #define OS_TYPE_DIR 2
 #define OS_TYPE_SYMLINK 3
@@ -273,8 +275,9 @@ extern void stack_protections(unsigned long address);
 extern void task_protections(unsigned long address);
 extern int raw(int fd);
 extern void setup_machinename(char *machine_out);
-extern void setup_hostinfo(void);
+extern void setup_hostinfo(char *buf, int len);
 extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
+extern void os_dump_core(void);
 
 /* time.c */
 #define BILLION (1000 * 1000 * 1000)
@@ -297,13 +300,12 @@ extern long syscall_stub_data(struct mm_id * mm_idp,
                              unsigned long *data, int data_count,
                              void **addr, void **stub_addr);
 extern int map(struct mm_id * mm_idp, unsigned long virt,
-              unsigned long len, int r, int w, int x, int phys_fd,
+              unsigned long len, int prot, int phys_fd,
               unsigned long long offset, int done, void **data);
-extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
+extern int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
                 int done, void **data);
 extern int protect(struct mm_id * mm_idp, unsigned long addr,
-                  unsigned long len, int r, int w, int x, int done,
-                  void **data);
+                  unsigned long len, unsigned int prot, int done, void **data);
 
 /* skas/process.c */
 extern int is_skas_winch(int pid, int fd, void *data);
@@ -339,8 +341,11 @@ extern void maybe_sigio_broken(int fd, int read);
 
 /* skas/trap */
 extern void sig_handler_common_skas(int sig, void *sc_ptr);
-extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
 
+/* sys-x86_64/prctl.c */
 extern int os_arch_prctl(int pid, int code, unsigned long *addr);
 
+/* tty.c */
+int get_pty(void);
+
 #endif
index 9cd9c6e..8ee6285 100644 (file)
@@ -33,6 +33,8 @@ extern unsigned long set_task_sizes_skas(unsigned long *task_size_out);
 extern int start_uml_skas(void);
 extern int external_pid_skas(struct task_struct *task);
 extern int thread_pid_skas(struct task_struct *task);
+extern void flush_tlb_page_skas(struct vm_area_struct *vma,
+                               unsigned long address);
 
 #define kmem_end_skas (host_task_size - 1024 * 1024)
 
index 8efc1e0..bcd1a4a 100644 (file)
@@ -14,9 +14,7 @@ struct host_vm_op {
                struct {
                        unsigned long addr;
                        unsigned long len;
-                       unsigned int r:1;
-                       unsigned int w:1;
-                       unsigned int x:1;
+                       unsigned int prot;
                        int fd;
                        __u64 offset;
                } mmap;
@@ -27,9 +25,7 @@ struct host_vm_op {
                struct {
                        unsigned long addr;
                        unsigned long len;
-                       unsigned int r:1;
-                       unsigned int w:1;
-                       unsigned int x:1;
+                       unsigned int prot;
                } mprotect;
        } u;
 };
index b19645f..13a64f6 100644 (file)
@@ -27,8 +27,6 @@ extern unsigned long uml_physmem;
 #define access_ok_tt(type, addr, size) \
        (is_stack(addr, size))
 
-extern unsigned long get_fault_addr(void);
-
 extern int __do_copy_from_user(void *to, const void *from, int n,
                               void **fault_addr, void **fault_catcher);
 extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
index 0363a9b..e6d7c5a 100644 (file)
@@ -11,7 +11,6 @@ extern void *um_kmalloc_atomic(int size);
 extern void kfree(const void *ptr);
 
 extern void *um_vmalloc(int size);
-extern void *um_vmalloc_atomic(int size);
 extern void vfree(void *ptr);
 
 #endif /* __UM_MALLOC_H__ */
index acadce3..d380e6d 100644 (file)
@@ -6,6 +6,19 @@
 #ifndef __USER_H__
 #define __USER_H__
 
+/*
+ * The usual definition - copied here because the kernel provides its own,
+ * fancier, type-safe, definition.  Using that one would require
+ * copying too much infrastructure for my taste, so userspace files
+ * get less checking than kernel files.
+ */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/*
+ * This will provide the size_t definition in both kernel and userspace builds
+ */
+#include <linux/types.h>
+
 extern void panic(const char *fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
 extern int printk(const char *fmt, ...)
@@ -13,19 +26,7 @@ extern int printk(const char *fmt, ...)
 extern void schedule(void);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
-/* These use size_t, however unsigned long is correct on both i386 and x86_64. */
-extern unsigned long strlcpy(char *, const char *, unsigned long);
-extern unsigned long strlcat(char *, const char *, unsigned long);
+extern size_t strlcpy(char *, const char *, size_t);
+extern size_t strlcat(char *, const char *, size_t);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
deleted file mode 100644 (file)
index 023575f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __USER_UTIL_H__
-#define __USER_UTIL_H__
-
-#include "sysdep/ptrace.h"
-
-/* Copied from kernel.h */
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
-
-extern int mode_tt;
-
-extern int grantpt(int __fd);
-extern int unlockpt(int __fd);
-extern char *ptsname(int __fd);
-
-struct cpu_task {
-       int pid;
-       void *task;
-};
-
-extern struct cpu_task cpu_tasks[];
-
-extern void (*sig_info[])(int, union uml_pt_regs *);
-
-extern unsigned long low_physmem;
-extern unsigned long high_physmem;
-extern unsigned long uml_physmem;
-extern unsigned long uml_reserved;
-extern unsigned long end_vm;
-extern unsigned long start_vm;
-extern unsigned long long highmem;
-
-extern char host_info[];
-
-extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
-extern unsigned long _unprotected_end;
-extern unsigned long brk_start;
-
-extern int pty_output_sigio;
-extern int pty_close_sigio;
-
-extern void *add_signal_handler(int sig, void (*handler)(int));
-extern int linux_main(int argc, char **argv);
-extern void set_cmdline(char *cmd);
-extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
-extern int get_pty(void);
-extern int switcheroo(int fd, int prot, void *from, void *to, int size);
-extern void do_exec(int old_pid, int new_pid);
-extern void tracer_panic(char *msg, ...)
-       __attribute__ ((format (printf, 1, 2)));
-extern int detach(int pid, int sig);
-extern int attach(int pid);
-extern void kill_child_dead(int pid);
-extern int cont(int pid);
-extern void check_sigio(void);
-extern void arch_check_bugs(void);
-extern int cpu_feature(char *what, char *buf, int len);
-extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
-extern int arch_fixup(unsigned long address, void *sc_ptr);
-extern void arch_init_thread(void);
-extern int raw(int fd);
-
-#endif
index 1211664..356e50f 100644 (file)
@@ -10,8 +10,8 @@
 #include "asm/pgtable.h"
 #include "asm/tlbflush.h"
 #include "asm/uaccess.h"
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
 #include "mem_user.h"
 #include "kern.h"
 #include "irq_user.h"
index 8cde431..cda91aa 100644 (file)
@@ -10,7 +10,6 @@
 #include "linux/mqueue.h"
 #include "asm/uaccess.h"
 #include "asm/pgtable.h"
-#include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
 
index 82ecf90..16dc43e 100644 (file)
@@ -7,7 +7,6 @@
 #include "linux/bootmem.h"
 #include "linux/initrd.h"
 #include "asm/types.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "initrd.h"
 #include "init.h"
@@ -22,12 +21,20 @@ static int __init read_initrd(void)
        long long size;
        int err;
 
-       if(initrd == NULL) return 0;
+       if(initrd == NULL)
+               return 0;
+
        err = os_file_size(initrd, &size);
-       if(err) return 0;
+       if(err)
+               return 0;
+
        area = alloc_bootmem(size);
-       if(area == NULL) return 0;
-       if(load_initrd(initrd, area, size) == -1) return 0;
+       if(area == NULL)
+               return 0;
+
+       if(load_initrd(initrd, area, size) == -1)
+               return 0;
+
        initrd_start = (unsigned long) area;
        initrd_end = initrd_start + size;
        return 0;
@@ -54,25 +61,15 @@ int load_initrd(char *filename, void *buf, int size)
        fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
        if(fd < 0){
                printk("Opening '%s' failed - err = %d\n", filename, -fd);
-               return(-1);
+               return -1;
        }
        n = os_read_file(fd, buf, size);
        if(n != size){
                printk("Read of %d bytes from '%s' failed, err = %d\n", size,
                       filename, -n);
-               return(-1);
+               return -1;
        }
 
        os_close_file(fd);
-       return(0);
+       return 0;
 }
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index dbf2f5b..8f2ed36 100644 (file)
@@ -25,7 +25,6 @@
 #include "asm/system.h"
 #include "asm/errno.h"
 #include "asm/uaccess.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
 #include "irq_kern.h"
@@ -79,6 +78,14 @@ skip:
        return 0;
 }
 
+/*
+ * This list is accessed under irq_lock, except in sigio_handler,
+ * where it is safe from being modified.  IRQ handlers won't change it -
+ * if an IRQ source has vanished, it will be freed by free_irqs just
+ * before returning from sigio_handler.  That will process a separate
+ * list of irqs to free, with its own locking, coming back here to
+ * remove list elements, taking the irq_lock to do so.
+ */
 static struct irq_fd *active_fds = NULL;
 static struct irq_fd **last_irq_ptr = &active_fds;
 
@@ -244,6 +251,7 @@ void free_irq_by_fd(int fd)
        free_irq_by_cb(same_fd, &fd);
 }
 
+/* Must be called with irq_lock held */
 static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
 {
        struct irq_fd *irq;
@@ -309,6 +317,12 @@ void deactivate_fd(int fd, int irqnum)
        ignore_sigio_fd(fd);
 }
 
+/*
+ * Called just before shutdown in order to provide a clean exec
+ * environment in case the system is rebooting.  No locking because
+ * that would cause a pointless shutdown hang if something hadn't
+ * released the lock.
+ */
 int deactivate_all_fds(void)
 {
        struct irq_fd *irq;
index 0e00cf9..7b3e53f 100644 (file)
@@ -16,7 +16,7 @@
 #include "asm/page.h"
 #include "asm/tlbflush.h"
 #include "kern_util.h"
-#include "user_util.h"
+#include "as-layout.h"
 #include "mem_user.h"
 #include "os.h"
 
index df7d662..72ff856 100644 (file)
@@ -13,8 +13,8 @@
 #include "asm/page.h"
 #include "asm/fixmap.h"
 #include "asm/pgalloc.h"
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
 #include "kern.h"
 #include "mem_user.h"
 #include "uml_uaccess.h"
@@ -216,7 +216,7 @@ static void __init fixaddr_user_init( void)
 #endif
 }
 
-void paging_init(void)
+void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES], vaddr;
        int i;
index 638f3b5..3ba6e4c 100644 (file)
@@ -13,7 +13,7 @@
 #include "asm/types.h"
 #include "asm/pgtable.h"
 #include "kern_util.h"
-#include "user_util.h"
+#include "as-layout.h"
 #include "mode_kern.h"
 #include "mem.h"
 #include "mem_user.h"
 #include "kern.h"
 #include "init.h"
 
-struct phys_desc {
-       struct rb_node rb;
-       int fd;
-       __u64 offset;
-       void *virt;
-       unsigned long phys;
-       struct list_head list;
-};
-
-static struct rb_root phys_mappings = RB_ROOT;
-
-static struct rb_node **find_rb(void *virt)
-{
-       struct rb_node **n = &phys_mappings.rb_node;
-       struct phys_desc *d;
-
-       while(*n != NULL){
-               d = rb_entry(*n, struct phys_desc, rb);
-               if(d->virt == virt)
-                       return n;
-
-               if(d->virt > virt)
-                       n = &(*n)->rb_left;
-               else
-                       n = &(*n)->rb_right;
-       }
-
-       return n;
-}
-
-static struct phys_desc *find_phys_mapping(void *virt)
-{
-       struct rb_node **n = find_rb(virt);
-
-       if(*n == NULL)
-               return NULL;
-
-       return rb_entry(*n, struct phys_desc, rb);
-}
-
-static void insert_phys_mapping(struct phys_desc *desc)
-{
-       struct rb_node **n = find_rb(desc->virt);
-
-       if(*n != NULL)
-               panic("Physical remapping for %p already present",
-                     desc->virt);
-
-       rb_link_node(&desc->rb, rb_parent(*n), n);
-       rb_insert_color(&desc->rb, &phys_mappings);
-}
-
-LIST_HEAD(descriptor_mappings);
-
-struct desc_mapping {
-       int fd;
-       struct list_head list;
-       struct list_head pages;
-};
-
-static struct desc_mapping *find_mapping(int fd)
-{
-       struct desc_mapping *desc;
-       struct list_head *ele;
-
-       list_for_each(ele, &descriptor_mappings){
-               desc = list_entry(ele, struct desc_mapping, list);
-               if(desc->fd == fd)
-                       return desc;
-       }
-
-       return NULL;
-}
-
-static struct desc_mapping *descriptor_mapping(int fd)
-{
-       struct desc_mapping *desc;
-
-       desc = find_mapping(fd);
-       if(desc != NULL)
-               return desc;
-
-       desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
-       if(desc == NULL)
-               return NULL;
-
-       *desc = ((struct desc_mapping)
-               { .fd =         fd,
-                 .list =       LIST_HEAD_INIT(desc->list),
-                 .pages =      LIST_HEAD_INIT(desc->pages) });
-       list_add(&desc->list, &descriptor_mappings);
-
-       return desc;
-}
-
-int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
-{
-       struct desc_mapping *fd_maps;
-       struct phys_desc *desc;
-       unsigned long phys;
-       int err;
-
-       fd_maps = descriptor_mapping(fd);
-       if(fd_maps == NULL)
-               return -ENOMEM;
-
-       phys = __pa(virt);
-       desc = find_phys_mapping(virt);
-       if(desc != NULL)
-               panic("Address 0x%p is already substituted\n", virt);
-
-       err = -ENOMEM;
-       desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
-       if(desc == NULL)
-               goto out;
-
-       *desc = ((struct phys_desc)
-               { .fd =                 fd,
-                 .offset =             offset,
-                 .virt =               virt,
-                 .phys =               __pa(virt),
-                 .list =               LIST_HEAD_INIT(desc->list) });
-       insert_phys_mapping(desc);
-
-       list_add(&desc->list, &fd_maps->pages);
-
-       virt = (void *) ((unsigned long) virt & PAGE_MASK);
-       err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
-       if(!err)
-               goto out;
-
-       rb_erase(&desc->rb, &phys_mappings);
-       kfree(desc);
- out:
-       return err;
-}
-
 static int physmem_fd = -1;
 
-static void remove_mapping(struct phys_desc *desc)
-{
-       void *virt = desc->virt;
-       int err;
-
-       rb_erase(&desc->rb, &phys_mappings);
-       list_del(&desc->list);
-       kfree(desc);
-
-       err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
-       if(err)
-               panic("Failed to unmap block device page from physical memory, "
-                     "errno = %d", -err);
-}
-
-int physmem_remove_mapping(void *virt)
-{
-       struct phys_desc *desc;
-
-       virt = (void *) ((unsigned long) virt & PAGE_MASK);
-       desc = find_phys_mapping(virt);
-       if(desc == NULL)
-               return 0;
-
-       remove_mapping(desc);
-       return 1;
-}
-
-void physmem_forget_descriptor(int fd)
-{
-       struct desc_mapping *desc;
-       struct phys_desc *page;
-       struct list_head *ele, *next;
-       __u64 offset;
-       void *addr;
-       int err;
-
-       desc = find_mapping(fd);
-       if(desc == NULL)
-               return;
-
-       list_for_each_safe(ele, next, &desc->pages){
-               page = list_entry(ele, struct phys_desc, list);
-               offset = page->offset;
-               addr = page->virt;
-               remove_mapping(page);
-               err = os_seek_file(fd, offset);
-               if(err)
-                       panic("physmem_forget_descriptor - failed to seek "
-                             "to %lld in fd %d, error = %d\n",
-                             offset, fd, -err);
-               err = os_read_file(fd, addr, PAGE_SIZE);
-               if(err < 0)
-                       panic("physmem_forget_descriptor - failed to read "
-                             "from fd %d to 0x%p, error = %d\n",
-                             fd, addr, -err);
-       }
-
-       list_del(&desc->list);
-       kfree(desc);
-}
-
-EXPORT_SYMBOL(physmem_forget_descriptor);
-EXPORT_SYMBOL(physmem_remove_mapping);
-EXPORT_SYMBOL(physmem_subst_mapping);
-
-void arch_free_page(struct page *page, int order)
-{
-       void *virt;
-       int i;
-
-       for(i = 0; i < (1 << order); i++){
-               virt = __va(page_to_phys(page + i));
-               physmem_remove_mapping(virt);
-       }
-}
-
-int is_remapped(void *virt)
-{
-       struct phys_desc *desc = find_phys_mapping(virt);
-
-       return desc != NULL;
-}
-
 /* Changed during early boot */
 unsigned long high_physmem;
 
@@ -350,14 +129,9 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
 
 int phys_mapping(unsigned long phys, __u64 *offset_out)
 {
-       struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));
        int fd = -1;
 
-       if(desc != NULL){
-               fd = desc->fd;
-               *offset_out = desc->offset;
-       }
-       else if(phys < physmem_size){
+       if(phys < physmem_size){
                fd = physmem_fd;
                *offset_out = phys;
        }
index 348b272..8d2c549 100644 (file)
@@ -32,8 +32,8 @@
 #include "asm/tlbflush.h"
 #include "asm/uaccess.h"
 #include "asm/user.h"
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
 #include "kern.h"
 #include "signal_kern.h"
 #include "init.h"
  */
 struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
 
-int external_pid(void *t)
+static inline int external_pid(struct task_struct *task)
 {
-       struct task_struct *task = t ? t : current;
-
-       return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
+       return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task);
 }
 
 int pid_to_processor_id(int pid)
@@ -66,9 +64,10 @@ int pid_to_processor_id(int pid)
        int i;
 
        for(i = 0; i < ncpus; i++){
-               if(cpu_tasks[i].pid == pid) return(i);
+               if(cpu_tasks[i].pid == pid)
+                       return i;
        }
-       return(-1);
+       return -1;
 }
 
 void free_stack(unsigned long stack, int order)
@@ -85,9 +84,9 @@ unsigned long alloc_stack(int order, int atomic)
                flags = GFP_ATOMIC;
        page = __get_free_pages(flags, order);
        if(page == 0)
-               return(0);
+               return 0;
        stack_protections(page);
-       return(page);
+       return page;
 }
 
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
@@ -98,15 +97,11 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        current->thread.request.u.thread.arg = arg;
        pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
                      &current->thread.regs, 0, NULL, NULL);
-       if(pid < 0)
-               panic("do_fork failed in kernel_thread, errno = %d", pid);
-       return(pid);
+       return pid;
 }
 
-void set_current(void *t)
+static inline void set_current(struct task_struct *task)
 {
-       struct task_struct *task = t;
-
        cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
                { external_pid(task), task });
 }
@@ -128,14 +123,16 @@ void *_switch_to(void *prev, void *next, void *last)
                prev= current;
        } while(current->thread.saved_task);
 
-       return(current->thread.prev_sched);
+       return current->thread.prev_sched;
 
 }
 
 void interrupt_end(void)
 {
-       if(need_resched()) schedule();
-       if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
+       if(need_resched())
+               schedule();
+       if(test_tsk_thread_flag(current, TIF_SIGPENDING))
+               do_signal();
 }
 
 void release_thread(struct task_struct *task)
@@ -150,7 +147,7 @@ void exit_thread(void)
 
 void *get_current(void)
 {
-       return(current);
+       return current;
 }
 
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
@@ -188,15 +185,12 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
        kmalloc_ok = save_kmalloc_ok;
 }
 
+#ifdef CONFIG_MODE_TT
 unsigned long stack_sp(unsigned long page)
 {
-       return(page + PAGE_SIZE - sizeof(void *));
-}
-
-int current_pid(void)
-{
-       return(current->pid);
+       return page + PAGE_SIZE - sizeof(void *);
 }
+#endif
 
 void default_idle(void)
 {
@@ -221,11 +215,6 @@ void cpu_idle(void)
        CHOOSE_MODE(init_idle_tt(), init_idle_skas());
 }
 
-int page_size(void)
-{
-       return(PAGE_SIZE);
-}
-
 void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
                      pte_t *pte_out)
 {
@@ -236,68 +225,43 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
        pte_t ptent;
 
        if(task->mm == NULL)
-               return(ERR_PTR(-EINVAL));
+               return ERR_PTR(-EINVAL);
        pgd = pgd_offset(task->mm, addr);
        if(!pgd_present(*pgd))
-               return(ERR_PTR(-EINVAL));
+               return ERR_PTR(-EINVAL);
 
        pud = pud_offset(pgd, addr);
        if(!pud_present(*pud))
-               return(ERR_PTR(-EINVAL));
+               return ERR_PTR(-EINVAL);
 
        pmd = pmd_offset(pud, addr);
        if(!pmd_present(*pmd))
-               return(ERR_PTR(-EINVAL));
+               return ERR_PTR(-EINVAL);
 
        pte = pte_offset_kernel(pmd, addr);
        ptent = *pte;
        if(!pte_present(ptent))
-               return(ERR_PTR(-EINVAL));
+               return ERR_PTR(-EINVAL);
 
        if(pte_out != NULL)
                *pte_out = ptent;
-       return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
+       return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
 }
 
 char *current_cmd(void)
 {
 #if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
-       return("(Unknown)");
+       return "(Unknown)";
 #else
        void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
        return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
 #endif
 }
 
-void force_sigbus(void)
-{
-       printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
-              current->pid);
-       lock_kernel();
-       sigaddset(&current->pending.signal, SIGBUS);
-       recalc_sigpending();
-       current->flags |= PF_SIGNALED;
-       do_exit(SIGBUS | 0x80);
-}
-
 void dump_thread(struct pt_regs *regs, struct user *u)
 {
 }
 
-void enable_hlt(void)
-{
-       panic("enable_hlt");
-}
-
-EXPORT_SYMBOL(enable_hlt);
-
-void disable_hlt(void)
-{
-       panic("disable_hlt");
-}
-
-EXPORT_SYMBOL(disable_hlt);
-
 void *um_kmalloc(int size)
 {
        return kmalloc(size, GFP_KERNEL);
@@ -313,36 +277,17 @@ void *um_vmalloc(int size)
        return vmalloc(size);
 }
 
-void *um_vmalloc_atomic(int size)
-{
-       return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
-}
-
 int __cant_sleep(void) {
        return in_atomic() || irqs_disabled() || in_interrupt();
        /* Is in_interrupt() really needed? */
 }
 
-unsigned long get_fault_addr(void)
-{
-       return((unsigned long) current->thread.fault_addr);
-}
-
-EXPORT_SYMBOL(get_fault_addr);
-
-void not_implemented(void)
-{
-       printk(KERN_DEBUG "Something isn't implemented in here\n");
-}
-
-EXPORT_SYMBOL(not_implemented);
-
 int user_context(unsigned long sp)
 {
        unsigned long stack;
 
        stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-       return(stack != (unsigned long) current_thread);
+       return stack != (unsigned long) current_thread;
 }
 
 extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -363,22 +308,22 @@ char *uml_strdup(char *string)
 
 int copy_to_user_proc(void __user *to, void *from, int size)
 {
-       return(copy_to_user(to, from, size));
+       return copy_to_user(to, from, size);
 }
 
 int copy_from_user_proc(void *to, void __user *from, int size)
 {
-       return(copy_from_user(to, from, size));
+       return copy_from_user(to, from, size);
 }
 
 int clear_user_proc(void __user *buf, int size)
 {
-       return(clear_user(buf, size));
+       return clear_user(buf, size);
 }
 
 int strlen_user_proc(char __user *str)
 {
-       return(strlen_user(str));
+       return strlen_user(str);
 }
 
 int smp_sigio_handler(void)
@@ -387,14 +332,14 @@ int smp_sigio_handler(void)
        int cpu = current_thread->cpu;
        IPI_handler(cpu);
        if(cpu != 0)
-               return(1);
+               return 1;
 #endif
-       return(0);
+       return 0;
 }
 
 int cpu(void)
 {
-       return(current_thread->cpu);
+       return current_thread->cpu;
 }
 
 static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -443,7 +388,7 @@ int __init make_proc_sysemu(void)
        if (ent == NULL)
        {
                printk(KERN_WARNING "Failed to register /proc/sysemu\n");
-               return(0);
+               return 0;
        }
 
        ent->read_proc  = proc_read_sysemu;
index f602623..7e4305a 100644 (file)
@@ -6,7 +6,6 @@
 #include "linux/module.h"
 #include "linux/sched.h"
 #include "asm/smp.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "os.h"
index 3c798cd..c4020c3 100644 (file)
@@ -17,7 +17,6 @@
 #include "asm/signal.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
-#include "user_util.h"
 #include "asm/ucontext.h"
 #include "kern_util.h"
 #include "signal_kern.h"
index 54b7959..580eb64 100644 (file)
 
 void flush_thread_skas(void)
 {
-       force_flush_all();
+       void *data = NULL;
+       unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
+       int ret;
+
+       ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
+       if(ret){
+               printk("flush_thread_skas - clearing address space failed, "
+                      "err = %d\n", ret);
+               force_sig(SIGKILL, current);
+       }
+
        switch_mm_skas(&current->mm->context.skas.id);
 }
 
index ae4fa71..ef36fac 100644 (file)
@@ -13,9 +13,9 @@
 #include "asm/uaccess.h"
 #include "asm/atomic.h"
 #include "kern_util.h"
+#include "as-layout.h"
 #include "skas.h"
 #include "os.h"
-#include "user_util.h"
 #include "tlb.h"
 #include "kern.h"
 #include "mode.h"
index 27eb29c..c0f0693 100644 (file)
@@ -10,7 +10,6 @@
 #include "asm/page.h"
 #include "asm/pgtable.h"
 #include "asm/mmu.h"
-#include "user_util.h"
 #include "mem_user.h"
 #include "mem.h"
 #include "skas.h"
@@ -28,19 +27,17 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
                switch(op->type){
                case MMAP:
                        ret = map(&mmu->skas.id, op->u.mmap.addr,
-                                 op->u.mmap.len, op->u.mmap.r, op->u.mmap.w,
-                                 op->u.mmap.x, op->u.mmap.fd,
-                                 op->u.mmap.offset, finished, flush);
+                                 op->u.mmap.len, op->u.mmap.prot,
+                                 op->u.mmap.fd, op->u.mmap.offset, finished,
+                                 flush);
                        break;
                case MUNMAP:
-                       ret = unmap(&mmu->skas.id,
-                                   (void *) op->u.munmap.addr,
+                       ret = unmap(&mmu->skas.id, op->u.munmap.addr,
                                    op->u.munmap.len, finished, flush);
                        break;
                case MPROTECT:
                        ret = protect(&mmu->skas.id, op->u.mprotect.addr,
-                                     op->u.mprotect.len, op->u.mprotect.r,
-                                     op->u.mprotect.w, op->u.mprotect.x,
+                                     op->u.mprotect.len, op->u.mprotect.prot,
                                      finished, flush);
                        break;
                default:
@@ -92,6 +89,76 @@ void flush_tlb_mm_skas(struct mm_struct *mm)
 
 void force_flush_all_skas(void)
 {
-       unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
-        fix_range(current->mm, 0, end, 1);
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma = mm->mmap;
+
+       while(vma != NULL) {
+               fix_range(mm, vma->vm_start, vma->vm_end, 1);
+               vma = vma->vm_next;
+       }
+}
+
+void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       struct mm_struct *mm = vma->vm_mm;
+       void *flush = NULL;
+       int r, w, x, prot, err = 0;
+       struct mm_id *mm_id;
+
+       pgd = pgd_offset(mm, address);
+       if(!pgd_present(*pgd))
+               goto kill;
+
+       pud = pud_offset(pgd, address);
+       if(!pud_present(*pud))
+               goto kill;
+
+       pmd = pmd_offset(pud, address);
+       if(!pmd_present(*pmd))
+               goto kill;
+
+       pte = pte_offset_kernel(pmd, address);
+
+       r = pte_read(*pte);
+       w = pte_write(*pte);
+       x = pte_exec(*pte);
+       if (!pte_young(*pte)) {
+               r = 0;
+               w = 0;
+       } else if (!pte_dirty(*pte)) {
+               w = 0;
+       }
+
+       mm_id = &mm->context.skas.id;
+       prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
+               (x ? UM_PROT_EXEC : 0));
+       if(pte_newpage(*pte)){
+               if(pte_present(*pte)){
+                       unsigned long long offset;
+                       int fd;
+
+                       fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
+                       err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
+                                 1, &flush);
+               }
+               else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
+       }
+       else if(pte_newprot(*pte))
+               err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
+
+       if(err)
+               goto kill;
+
+       *pte = pte_mkuptodate(*pte);
+
+       return;
+
+kill:
+       printk("Failed to flush page for address 0x%lx\n", address);
+       force_sig(SIGKILL, current);
 }
+
index 759b070..e6a7778 100644 (file)
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 #include "asm/smp.h"
 #include "asm/processor.h"
 #include "asm/spinlock.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "irq_user.h"
@@ -90,7 +89,7 @@ static int idle_proc(void *cpup)
 
        cpu_set(cpu, cpu_online_map);
        default_idle();
-       return(0);
+       return 0;
 }
 
 static struct task_struct *idle_thread(int cpu)
@@ -98,8 +97,8 @@ static struct task_struct *idle_thread(int cpu)
        struct task_struct *new_task;
        unsigned char c;
 
-        current->thread.request.u.thread.proc = idle_proc;
-        current->thread.request.u.thread.arg = (void *) cpu;
+       current->thread.request.u.thread.proc = idle_proc;
+       current->thread.request.u.thread.arg = (void *) cpu;
        new_task = fork_idle(cpu);
        if(IS_ERR(new_task))
                panic("copy_process failed in idle_thread, error = %ld",
@@ -110,9 +109,9 @@ static struct task_struct *idle_thread(int cpu)
                            .task =     new_task } );
        idle_threads[cpu] = new_task;
        CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
-                         sizeof(c)),
+                                 sizeof(c)),
                    ({ panic("skas mode doesn't support SMP"); }));
-       return(new_task);
+       return new_task;
 }
 
 void smp_prepare_cpus(unsigned int maxcpus)
@@ -163,13 +162,13 @@ int __cpu_up(unsigned int cpu)
        cpu_set(cpu, smp_commenced_mask);
        while (!cpu_isset(cpu, cpu_online_map))
                mb();
-       return(0);
+       return 0;
 }
 
 int setup_profiling_timer(unsigned int multiplier)
 {
        printk(KERN_INFO "setup_profiling_timer\n");
-       return(0);
+       return 0;
 }
 
 void smp_call_function_slave(int cpu);
@@ -205,7 +204,7 @@ void IPI_handler(int cpu)
 
 int hard_smp_processor_id(void)
 {
-       return(pid_to_processor_id(os_getpid()));
+       return pid_to_processor_id(os_getpid());
 }
 
 static DEFINE_SPINLOCK(call_lock);
@@ -254,14 +253,3 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
 }
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 2828c52..237c4ea 100644 (file)
@@ -18,7 +18,6 @@
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "sysdep/syscalls.h"
 #include "mode_kern.h"
 #include "choose-mode.h"
index f9e02b3..9326357 100644 (file)
@@ -10,7 +10,6 @@
 #include "asm/page.h"
 #include "asm/processor.h"
 #include "sysrq.h"
-#include "user_util.h"
 
 /* Catch non-i386 SUBARCH's. */
 #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
index b1f8b07..cd7349d 100644 (file)
@@ -18,7 +18,6 @@
 #include "asm/param.h"
 #include "asm/current.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "mode.h"
 #include "os.h"
 
@@ -35,8 +34,8 @@ unsigned long long sched_clock(void)
        return (unsigned long long)jiffies_64 * (1000000000 / HZ);
 }
 
-static unsigned long long prev_nsecs[NR_CPUS];
 #ifdef CONFIG_UML_REAL_TIME_CLOCK
+static unsigned long long prev_nsecs[NR_CPUS];
 static long long delta[NR_CPUS];               /* Deviation per interval */
 #endif
 
@@ -95,7 +94,12 @@ irqreturn_t um_timer(int irq, void *dev)
 
        do_timer(1);
 
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
        nsecs = get_time();
+#else
+       nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec +
+               BILLION / HZ;
+#endif
        xtime.tv_sec = nsecs / NSEC_PER_SEC;
        xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
 
@@ -128,13 +132,18 @@ void time_init(void)
        nsecs = os_nsecs();
        set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
                                -nsecs % BILLION);
+       set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION);
        late_time_init = register_timer;
 }
 
 void do_gettimeofday(struct timeval *tv)
 {
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
        unsigned long long nsecs = get_time();
-
+#else
+       unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION +
+               xtime.tv_nsec;
+#endif
        tv->tv_sec = nsecs / NSEC_PER_SEC;
        /* Careful about calculations here - this was originally done as
         * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
index 54a5ff2..8a8d528 100644 (file)
@@ -6,17 +6,18 @@
 #include "linux/mm.h"
 #include "asm/page.h"
 #include "asm/pgalloc.h"
+#include "asm/pgtable.h"
 #include "asm/tlbflush.h"
 #include "choose-mode.h"
 #include "mode_kern.h"
-#include "user_util.h"
+#include "as-layout.h"
 #include "tlb.h"
 #include "mem.h"
 #include "mem_user.h"
 #include "os.h"
 
 static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
-                   int r, int w, int x, struct host_vm_op *ops, int *index,
+                   unsigned int prot, struct host_vm_op *ops, int *index,
                    int last_filled, union mm_context *mmu, void **flush,
                    int (*do_ops)(union mm_context *, struct host_vm_op *,
                                  int, int, void **))
@@ -30,8 +31,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
                last = &ops[*index];
                if((last->type == MMAP) &&
                   (last->u.mmap.addr + last->u.mmap.len == virt) &&
-                  (last->u.mmap.r == r) && (last->u.mmap.w == w) &&
-                  (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
+                  (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&
                   (last->u.mmap.offset + last->u.mmap.len == offset)){
                        last->u.mmap.len += len;
                        return 0;
@@ -47,9 +47,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
                                                .u = { .mmap = {
                                                       .addr    = virt,
                                                       .len     = len,
-                                                      .r       = r,
-                                                      .w       = w,
-                                                      .x       = x,
+                                                      .prot    = prot,
                                                       .fd      = fd,
                                                       .offset  = offset }
                           } });
@@ -86,8 +84,8 @@ static int add_munmap(unsigned long addr, unsigned long len,
        return ret;
 }
 
-static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
-                       int x, struct host_vm_op *ops, int *index,
+static int add_mprotect(unsigned long addr, unsigned long len,
+                       unsigned int prot, struct host_vm_op *ops, int *index,
                        int last_filled, union mm_context *mmu, void **flush,
                        int (*do_ops)(union mm_context *, struct host_vm_op *,
                                      int, int, void **))
@@ -99,8 +97,7 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
                last = &ops[*index];
                if((last->type == MPROTECT) &&
                   (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
-                  (last->u.mprotect.r == r) && (last->u.mprotect.w == w) &&
-                  (last->u.mprotect.x == x)){
+                  (last->u.mprotect.prot == prot)){
                        last->u.mprotect.len += len;
                        return 0;
                }
@@ -115,114 +112,145 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
                                               .u = { .mprotect = {
                                                       .addr    = addr,
                                                       .len     = len,
-                                                      .r       = r,
-                                                      .w       = w,
-                                                      .x       = x } } });
+                                                      .prot    = prot } } });
        return ret;
 }
 
 #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
 
+static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
+                                  unsigned long end, struct host_vm_op *ops,
+                                  int last_op, int *op_index, int force,
+                                  union mm_context *mmu, void **flush,
+                                  int (*do_ops)(union mm_context *,
+                                                struct host_vm_op *, int, int,
+                                                void **))
+{
+       pte_t *pte;
+       int r, w, x, prot, ret = 0;
+
+       pte = pte_offset_kernel(pmd, addr);
+       do {
+               r = pte_read(*pte);
+               w = pte_write(*pte);
+               x = pte_exec(*pte);
+               if (!pte_young(*pte)) {
+                       r = 0;
+                       w = 0;
+               } else if (!pte_dirty(*pte)) {
+                       w = 0;
+               }
+               prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
+                       (x ? UM_PROT_EXEC : 0));
+               if(force || pte_newpage(*pte)){
+                       if(pte_present(*pte))
+                               ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
+                                              PAGE_SIZE, prot, ops, op_index,
+                                              last_op, mmu, flush, do_ops);
+                       else ret = add_munmap(addr, PAGE_SIZE, ops, op_index,
+                                             last_op, mmu, flush, do_ops);
+               }
+               else if(pte_newprot(*pte))
+                       ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index,
+                                          last_op, mmu, flush, do_ops);
+               *pte = pte_mkuptodate(*pte);
+       } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
+       return ret;
+}
+
+static inline int update_pmd_range(pud_t *pud, unsigned long addr,
+                                  unsigned long end, struct host_vm_op *ops,
+                                  int last_op, int *op_index, int force,
+                                  union mm_context *mmu, void **flush,
+                                  int (*do_ops)(union mm_context *,
+                                                struct host_vm_op *, int, int,
+                                                void **))
+{
+       pmd_t *pmd;
+       unsigned long next;
+       int ret = 0;
+
+       pmd = pmd_offset(pud, addr);
+       do {
+               next = pmd_addr_end(addr, end);
+               if(!pmd_present(*pmd)){
+                       if(force || pmd_newpage(*pmd)){
+                               ret = add_munmap(addr, next - addr, ops,
+                                                op_index, last_op, mmu,
+                                                flush, do_ops);
+                               pmd_mkuptodate(*pmd);
+                       }
+               }
+               else ret = update_pte_range(pmd, addr, next, ops, last_op,
+                                           op_index, force, mmu, flush,
+                                           do_ops);
+       } while (pmd++, addr = next, ((addr != end) && !ret));
+       return ret;
+}
+
+static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
+                                  unsigned long end, struct host_vm_op *ops,
+                                  int last_op, int *op_index, int force,
+                                  union mm_context *mmu, void **flush,
+                                  int (*do_ops)(union mm_context *,
+                                                struct host_vm_op *, int, int,
+                                                void **))
+{
+       pud_t *pud;
+       unsigned long next;
+       int ret = 0;
+
+       pud = pud_offset(pgd, addr);
+       do {
+               next = pud_addr_end(addr, end);
+               if(!pud_present(*pud)){
+                       if(force || pud_newpage(*pud)){
+                               ret = add_munmap(addr, next - addr, ops,
+                                                op_index, last_op, mmu,
+                                                flush, do_ops);
+                               pud_mkuptodate(*pud);
+                       }
+               }
+               else ret = update_pmd_range(pud, addr, next, ops, last_op,
+                                           op_index, force, mmu, flush,
+                                           do_ops);
+       } while (pud++, addr = next, ((addr != end) && !ret));
+       return ret;
+}
+
 void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                      unsigned long end_addr, int force,
                      int (*do_ops)(union mm_context *, struct host_vm_op *,
                                    int, int, void **))
 {
-       pgd_t *npgd;
-       pud_t *npud;
-       pmd_t *npmd;
-       pte_t *npte;
+       pgd_t *pgd;
        union mm_context *mmu = &mm->context;
-       unsigned long addr, end;
-       int r, w, x;
        struct host_vm_op ops[1];
+       unsigned long addr = start_addr, next;
+       int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1;
        void *flush = NULL;
-       int op_index = -1, last_op = ARRAY_SIZE(ops) - 1;
-       int ret = 0;
-
-       if(mm == NULL)
-               return;
 
        ops[0].type = NONE;
-       for(addr = start_addr; addr < end_addr && !ret;){
-               npgd = pgd_offset(mm, addr);
-               if(!pgd_present(*npgd)){
-                       end = ADD_ROUND(addr, PGDIR_SIZE);
-                       if(end > end_addr)
-                               end = end_addr;
-                       if(force || pgd_newpage(*npgd)){
-                               ret = add_munmap(addr, end - addr, ops,
-                                                &op_index, last_op, mmu,
-                                                &flush, do_ops);
-                               pgd_mkuptodate(*npgd);
-                       }
-                       addr = end;
-                       continue;
-               }
-
-               npud = pud_offset(npgd, addr);
-               if(!pud_present(*npud)){
-                       end = ADD_ROUND(addr, PUD_SIZE);
-                       if(end > end_addr)
-                               end = end_addr;
-                       if(force || pud_newpage(*npud)){
-                               ret = add_munmap(addr, end - addr, ops,
-                                                &op_index, last_op, mmu,
-                                                &flush, do_ops);
-                               pud_mkuptodate(*npud);
-                       }
-                       addr = end;
-                       continue;
-               }
-
-               npmd = pmd_offset(npud, addr);
-               if(!pmd_present(*npmd)){
-                       end = ADD_ROUND(addr, PMD_SIZE);
-                       if(end > end_addr)
-                               end = end_addr;
-                       if(force || pmd_newpage(*npmd)){
-                               ret = add_munmap(addr, end - addr, ops,
+       pgd = pgd_offset(mm, addr);
+       do {
+               next = pgd_addr_end(addr, end_addr);
+               if(!pgd_present(*pgd)){
+                       if (force || pgd_newpage(*pgd)){
+                               ret = add_munmap(addr, next - addr, ops,
                                                 &op_index, last_op, mmu,
                                                 &flush, do_ops);
-                               pmd_mkuptodate(*npmd);
+                               pgd_mkuptodate(*pgd);
                        }
-                       addr = end;
-                       continue;
-               }
-
-               npte = pte_offset_kernel(npmd, addr);
-               r = pte_read(*npte);
-               w = pte_write(*npte);
-               x = pte_exec(*npte);
-               if (!pte_young(*npte)) {
-                       r = 0;
-                       w = 0;
-               } else if (!pte_dirty(*npte)) {
-                       w = 0;
-               }
-               if(force || pte_newpage(*npte)){
-                       if(pte_present(*npte))
-                               ret = add_mmap(addr,
-                                              pte_val(*npte) & PAGE_MASK,
-                                              PAGE_SIZE, r, w, x, ops,
-                                              &op_index, last_op, mmu,
-                                              &flush, do_ops);
-                       else ret = add_munmap(addr, PAGE_SIZE, ops,
-                                             &op_index, last_op, mmu,
-                                             &flush, do_ops);
                }
-               else if(pte_newprot(*npte))
-                       ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
-                                          &op_index, last_op, mmu,
-                                          &flush, do_ops);
+               else ret = update_pud_range(pgd, addr, next, ops, last_op,
+                                           &op_index, force, mmu, &flush,
+                                           do_ops);
+       } while (pgd++, addr = next, ((addr != end_addr) && !ret));
 
-               *npte = pte_mkuptodate(*npte);
-               addr += PAGE_SIZE;
-       }
        if(!ret)
                ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
 
-/* This is not an else because ret is modified above */
+       /* This is not an else because ret is modified above */
        if(ret) {
                printk("fix_range_common: failed, killing current process\n");
                force_sig(SIGKILL, current);
@@ -343,12 +371,6 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
        return(pte_offset_map(pmd, addr));
 }
 
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
-{
-       address &= PAGE_MASK;
-       flush_tlb_range(vma, address, address + PAGE_SIZE);
-}
-
 void flush_tlb_all(void)
 {
        flush_tlb_mm(current->mm);
index 26f15c4..abab90c 100644 (file)
@@ -18,8 +18,9 @@
 #include "asm/current.h"
 #include "asm/irq.h"
 #include "sysdep/sigcontext.h"
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
+#include "arch.h"
 #include "kern.h"
 #include "chan_kern.h"
 #include "mconsole_kern.h"
@@ -71,8 +72,8 @@ good_area:
                goto out;
 
        /* Don't require VM_READ|VM_EXEC for write faults! */
-        if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
-                goto out;
+       if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
+               goto out;
 
        do {
 survive:
@@ -156,20 +157,23 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
  * the info in the regs. A pointer to the info then would
  * give us bad data!
  */
-unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
+unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
+                  union uml_pt_regs *regs)
 {
        struct siginfo si;
        void *catcher;
        int err;
-        int is_write = FAULT_WRITE(fi);
-        unsigned long address = FAULT_ADDRESS(fi);
+       int is_write = FAULT_WRITE(fi);
+       unsigned long address = FAULT_ADDRESS(fi);
 
-        if(!is_user && (address >= start_vm) && (address < end_vm)){
-                flush_tlb_kernel_vm();
-                return(0);
-        }
-       else if(current->mm == NULL)
-               panic("Segfault with no mm");
+       if(!is_user && (address >= start_vm) && (address < end_vm)){
+               flush_tlb_kernel_vm();
+               return 0;
+       }
+       else if(current->mm == NULL) {
+               show_regs(container_of(regs, struct pt_regs, regs));
+               panic("Segfault with no mm");
+       }
 
        if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
                err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
@@ -182,26 +186,28 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
 
        catcher = current->thread.fault_catcher;
        if(!err)
-               return(0);
+               return 0;
        else if(catcher != NULL){
                current->thread.fault_addr = (void *) address;
                do_longjmp(catcher, 1);
        }
        else if(current->thread.fault_addr != NULL)
                panic("fault_addr set but no fault catcher");
-        else if(!is_user && arch_fixup(ip, sc))
-               return(0);
+       else if(!is_user && arch_fixup(ip, regs))
+               return 0;
 
-       if(!is_user)
+       if(!is_user) {
+               show_regs(container_of(regs, struct pt_regs, regs));
                panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
                      address, ip);
+       }
 
        if (err == -EACCES) {
                si.si_signo = SIGBUS;
                si.si_errno = 0;
                si.si_code = BUS_ADRERR;
                si.si_addr = (void __user *)address;
-                current->thread.arch.faultinfo = fi;
+               current->thread.arch.faultinfo = fi;
                force_sig_info(SIGBUS, &si, current);
        } else if (err == -ENOMEM) {
                printk("VM: killing process %s\n", current->comm);
@@ -210,10 +216,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
                BUG_ON(err != -EFAULT);
                si.si_signo = SIGSEGV;
                si.si_addr = (void __user *) address;
-                current->thread.arch.faultinfo = fi;
+               current->thread.arch.faultinfo = fi;
                force_sig_info(SIGSEGV, &si, current);
        }
-       return(0);
+       return 0;
 }
 
 void relay_signal(int sig, union uml_pt_regs *regs)
@@ -223,12 +229,12 @@ void relay_signal(int sig, union uml_pt_regs *regs)
 
        if(!UPT_IS_USER(regs)){
                if(sig == SIGBUS)
-                       printk("Bus error - the /dev/shm or /tmp mount likely "
-                              "just ran out of space\n");
+                       printk("Bus error - the host /dev/shm or /tmp mount "
+                              "likely just ran out of space\n");
                panic("Kernel mode signal %d", sig);
        }
 
-        current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
+       current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
        force_sig(sig, current);
 }
 
index ad66df1..98e2174 100644 (file)
@@ -10,7 +10,6 @@
 #include "asm/uaccess.h"
 #include "asm/pgalloc.h"
 #include "asm/tlbflush.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
 #include "mem_user.h"
index a92c02f..7b5f218 100644 (file)
@@ -10,7 +10,6 @@
 #include <errno.h>
 #include <sys/wait.h>
 #include <signal.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "ptrace_user.h"
index 8eba8f7..030e465 100644 (file)
@@ -17,7 +17,6 @@
 #include "user.h"
 #include "debug.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "tt.h"
 #include "sysdep/thread.h"
 #include "os.h"
@@ -115,6 +114,8 @@ struct gdb_data {
        int err;
 };
 
+extern char *linux_prog;
+
 static void config_gdb_cb(void *arg)
 {
        struct gdb_data *data = arg;
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
deleted file mode 100644 (file)
index 2a35b15..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_MODE_KERN_H__
-#define __TT_MODE_KERN_H__
-
-#include "linux/sched.h"
-#include "asm/page.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-
-extern void switch_to_tt(void *prev, void *next);
-extern void flush_thread_tt(void);
-extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
-                          unsigned long esp);
-extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
-                         unsigned long stack_top, struct task_struct *p,
-                         struct pt_regs *regs);
-extern void release_thread_tt(struct task_struct *task);
-extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
-extern void init_idle_tt(void);
-extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
-extern void flush_tlb_kernel_vm_tt(void);
-extern void __flush_tlb_one_tt(unsigned long addr);
-extern void flush_tlb_range_tt(struct vm_area_struct *vma,
-                              unsigned long start, unsigned long end);
-extern void flush_tlb_mm_tt(struct mm_struct *mm);
-extern void force_flush_all_tt(void);
-extern long execute_syscall_tt(void *r);
-extern void before_mem_tt(unsigned long brk_start);
-extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
-                                      unsigned long *task_size_out);
-extern int start_uml_tt(void);
-extern int external_pid_tt(struct task_struct *task);
-extern int thread_pid_tt(struct task_struct *task);
-
-#define kmem_end_tt (host_task_size - ABOVE_KMEM)
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 4d1929d..d0c3c49 100644 (file)
@@ -8,7 +8,6 @@
 #include "asm/uaccess.h"
 #include "mem_user.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "kern.h"
 #include "tt.h"
 
index 03e5898..9774f63 100644 (file)
@@ -11,7 +11,6 @@
 #include <sys/mman.h>
 #include "tt.h"
 #include "mem_user.h"
-#include "user_util.h"
 #include "os.h"
 
 void remap_data(void *segment_start, void *segment_end, int w)
index 1e86f0b..c631303 100644 (file)
@@ -14,7 +14,6 @@
 #include "asm/tlbflush.h"
 #include "irq_user.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "os.h"
 #include "kern.h"
 #include "sigcontext.h"
@@ -65,7 +64,8 @@ void switch_to_tt(void *prev, void *next)
        if(from->thread.mode.tt.switch_pipe[0] == -1)
                os_kill_process(os_getpid(), 0);
 
-       err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
+       err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c,
+                            sizeof(c));
        if(err != sizeof(c))
                panic("read of switch_pipe failed, errno = %d", -err);
 
index 58800c5..420c23f 100644 (file)
@@ -26,7 +26,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
 #include "sysdep.h"
 #include "wait.h"
 
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 #include "tempfile.h"
@@ -339,11 +338,12 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out)
                               "err = %d\n", -fd);
                        exit(1);
                }
-               os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
+               os_write_file(fd, gdb_init_string,
+                             sizeof(gdb_init_string) - 1);
                if(startup){
                        if(stop){
                                os_write_file(fd, "b start_kernel\n",
-                                     strlen("b start_kernel\n"));
+                                               strlen("b start_kernel\n"));
                        }
                        os_write_file(fd, "c\n", strlen("c\n"));
                }
index 0377442..4b4f617 100644 (file)
@@ -16,7 +16,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
 
 #include "ptproxy.h"
 #include "debug.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "ptrace_user.h"
 #include "tt.h"
index 99f1783..e0e1ab0 100644 (file)
@@ -13,7 +13,6 @@ terms and conditions.
 #include <sys/types.h>
 #include <linux/unistd.h>
 #include "ptrace_user.h"
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 
index 12f6319..bdd4af4 100644 (file)
@@ -13,7 +13,6 @@ terms and conditions.
 #include "ptproxy.h"
 #include "sysdep.h"
 #include "wait.h"
-#include "user_util.h"
 #include "ptrace_user.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
index 902987b..f52b47a 100644 (file)
@@ -11,7 +11,6 @@
 #include "sigcontext.h"
 #include "ptrace_user.h"
 #include "task.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "syscall.h"
 #include "tt.h"
index ae6217c..7caa24f 100644 (file)
@@ -12,7 +12,6 @@
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
 #include "asm/tlbflush.h"
-#include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
index b919535..c235883 100644 (file)
@@ -19,7 +19,6 @@
 #include "sigcontext.h"
 #include "sysdep/sigcontext.h"
 #include "os.h"
-#include "user_util.h"
 #include "mem_user.h"
 #include "process.h"
 #include "kern_util.h"
index b5d9d64..3032eb5 100644 (file)
@@ -8,7 +8,6 @@
 #include <signal.h>
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "task.h"
 #include "tt.h"
index ed1abcf..0e5c82c 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <string.h>
-#include "user_util.h"
 #include "uml_uaccess.h"
 #include "task.h"
 #include "kern_util.h"
index 89c6dba..1cf954a 100644 (file)
@@ -17,6 +17,7 @@
 #include "linux/seq_file.h"
 #include "linux/delay.h"
 #include "linux/module.h"
+#include "linux/utsname.h"
 #include "asm/page.h"
 #include "asm/pgtable.h"
 #include "asm/ptrace.h"
@@ -25,8 +26,9 @@
 #include "asm/setup.h"
 #include "ubd_user.h"
 #include "asm/current.h"
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
+#include "arch.h"
 #include "kern.h"
 #include "mem_user.h"
 #include "mem.h"
@@ -42,7 +44,7 @@
 
 #define DEFAULT_COMMAND_LINE "root=98:0"
 
-/* Changed in linux_main and setup_arch, which run before SMP is started */
+/* Changed in add_arg and setup_arch, which run before SMP is started */
 static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
 
 static void __init add_arg(char *arg)
@@ -56,17 +58,25 @@ static void __init add_arg(char *arg)
        strcat(command_line, arg);
 }
 
-struct cpuinfo_um boot_cpu_data = { 
+/*
+ * These fields are initialized at boot time and not changed.
+ * XXX This structure is used only in the non-SMP case.  Maybe this
+ * should be moved to smp.c.
+ */
+struct cpuinfo_um boot_cpu_data = {
        .loops_per_jiffy        = 0,
        .ipi_pipe               = { -1, -1 }
 };
 
 unsigned long thread_saved_pc(struct task_struct *task)
 {
-       return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
-                                             task)));
+       return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
+                                             task));
 }
 
+/* Changed in setup_arch, which is called in early boot */
+static char host_info[(__NEW_UTS_LEN + 1) * 5];
+
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
        int index = 0;
@@ -86,7 +96,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                   loops_per_jiffy/(500000/HZ),
                   (loops_per_jiffy/(5000/HZ)) % 100);
 
-       return(0);
+       return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
@@ -114,14 +124,12 @@ const struct seq_operations cpuinfo_op = {
 /* Set in linux_main */
 unsigned long host_task_size;
 unsigned long task_size;
-
-unsigned long uml_start;
-
-/* Set in early boot */
 unsigned long uml_physmem;
-unsigned long uml_reserved;
+unsigned long uml_reserved; /* Also modified in mem_init */
 unsigned long start_vm;
 unsigned long end_vm;
+
+/* Set in uml_ncpus_setup */
 int ncpus = 1;
 
 #ifdef CONFIG_CMDLINE_ON_HOST
@@ -135,6 +143,8 @@ static char *argv1_end = NULL;
 
 /* Set in early boot */
 static int have_root __initdata = 0;
+
+/* Set in uml_mem_setup and modified in linux_main */
 long long physmem_size = 32 * 1024 * 1024;
 
 void set_cmdline(char *cmd)
@@ -212,12 +222,12 @@ __uml_setup("debug", no_skas_debug_setup,
 #ifdef CONFIG_SMP
 static int __init uml_ncpus_setup(char *line, int *add)
 {
-       if (!sscanf(line, "%d", &ncpus)) {
-               printf("Couldn't parse [%s]\n", line);
-               return -1;
-       }
+       if (!sscanf(line, "%d", &ncpus)) {
+               printf("Couldn't parse [%s]\n", line);
+               return -1;
+       }
 
-       return 0;
+       return 0;
 }
 
 __uml_setup("ncpus=", uml_ncpus_setup,
@@ -234,7 +244,7 @@ static int force_tt = 0;
 static int __init mode_tt_setup(char *line, int *add)
 {
        force_tt = 1;
-       return(0);
+       return 0;
 }
 
 #else
@@ -245,7 +255,7 @@ static int __init mode_tt_setup(char *line, int *add)
 static int __init mode_tt_setup(char *line, int *add)
 {
        printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
-       return(0);
+       return 0;
 }
 
 #else
@@ -256,7 +266,7 @@ static int __init mode_tt_setup(char *line, int *add)
 static int __init mode_tt_setup(char *line, int *add)
 {
        printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
-       return(0);
+       return 0;
 }
 
 #endif
@@ -274,16 +284,15 @@ int mode_tt = DEFAULT_TT;
 
 static int __init Usage(char *line, int *add)
 {
-       const char **p;
+       const char **p;
 
        printf(usage_string, init_utsname()->release);
-       p = &__uml_help_start;
-       while (p < &__uml_help_end) {
-               printf("%s", *p);
-               p++;
-       }
+       p = &__uml_help_start;
+       while (p < &__uml_help_end) {
+               printf("%s", *p);
+               p++;
+       }
        exit(0);
-
        return 0;
 }
 
@@ -374,13 +383,12 @@ int __init linux_main(int argc, char **argv)
 
        printf("UML running in %s mode\n", mode);
 
-       uml_start = (unsigned long) &__binary_start;
        host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,
                                          set_task_sizes_skas, &task_size);
 
        /*
-        * Setting up handlers to 'sig_info' struct
-        */
+        * Setting up handlers to 'sig_info' struct
+        */
        os_fill_handlinfo(handlinfo_kern);
 
        brk_start = (unsigned long) sbrk(0);
@@ -396,7 +404,7 @@ int __init linux_main(int argc, char **argv)
                physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
        }
 
-       uml_physmem = uml_start & PAGE_MASK;
+       uml_physmem = (unsigned long) &__binary_start & PAGE_MASK;
 
        /* Reserve up to 4M after the current brk */
        uml_reserved = ROUND_4M(brk_start) + (1 << 22);
@@ -407,7 +415,7 @@ int __init linux_main(int argc, char **argv)
        argv1_begin = argv[1];
        argv1_end = &argv[1][strlen(argv[1])];
 #endif
-  
+
        highmem = 0;
        iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
        max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
@@ -449,12 +457,12 @@ int __init linux_main(int argc, char **argv)
                printf("Kernel virtual memory size shrunk to %lu bytes\n",
                       virtmem_size);
 
-       uml_postsetup();
+       uml_postsetup();
 
        task_protections((unsigned long) &init_thread_info);
        os_flush_stdout();
 
-       return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
+       return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
 }
 
 extern int uml_exitcode;
@@ -466,8 +474,8 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1,
        show_regs(&(current->thread.regs));
        bust_spinlocks(0);
        uml_exitcode = 1;
-       machine_halt();
-       return(0);
+       os_dump_core();
+       return 0;
 }
 
 static struct notifier_block panic_exit_notifier = {
@@ -482,14 +490,14 @@ void __init setup_arch(char **cmdline_p)
                        &panic_exit_notifier);
        paging_init();
        strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
-       *cmdline_p = command_line;
-       setup_hostinfo();
+       *cmdline_p = command_line;
+       setup_hostinfo(host_info, sizeof host_info);
 }
 
 void __init check_bugs(void)
 {
        arch_check_bugs();
-       os_check_bugs();
+       os_check_bugs();
 }
 
 void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
index 6ff1274..9bf944f 100644 (file)
@@ -132,10 +132,10 @@ static int aio_thread(void *arg)
                                { .data = (void *) (long) event.data,
                                                .err    = event.res });
                        reply_fd = ((struct aio_context *) reply.data)->reply_fd;
-                       err = os_write_file(reply_fd, &reply, sizeof(reply));
+                       err = write(reply_fd, &reply, sizeof(reply));
                        if(err != sizeof(reply))
                                printk("aio_thread - write failed, fd = %d, "
-                                      "err = %d\n", reply_fd, -err);
+                                      "err = %d\n", reply_fd, errno);
                }
        }
        return 0;
@@ -146,38 +146,31 @@ static int aio_thread(void *arg)
 static int do_not_aio(struct aio_thread_req *req)
 {
        char c;
-       int err;
+       unsigned long long actual;
+       int n;
+
+       actual = lseek64(req->io_fd, req->offset, SEEK_SET);
+       if(actual != req->offset)
+               return -errno;
 
        switch(req->type){
        case AIO_READ:
-               err = os_seek_file(req->io_fd, req->offset);
-               if(err)
-                       goto out;
-
-               err = os_read_file(req->io_fd, req->buf, req->len);
+               n = read(req->io_fd, req->buf, req->len);
                break;
        case AIO_WRITE:
-               err = os_seek_file(req->io_fd, req->offset);
-               if(err)
-                       goto out;
-
-               err = os_write_file(req->io_fd, req->buf, req->len);
+               n = write(req->io_fd, req->buf, req->len);
                break;
        case AIO_MMAP:
-               err = os_seek_file(req->io_fd, req->offset);
-               if(err)
-                       goto out;
-
-               err = os_read_file(req->io_fd, &c, sizeof(c));
+               n = read(req->io_fd, &c, sizeof(c));
                break;
        default:
                printk("do_not_aio - bad request type : %d\n", req->type);
-               err = -EINVAL;
-               break;
+               return -EINVAL;
        }
 
-out:
-       return err;
+       if(n < 0)
+               return -errno;
+       return 0;
 }
 
 /* These are initialized in initcalls and not changed */
@@ -193,12 +186,12 @@ static int not_aio_thread(void *arg)
 
        signal(SIGWINCH, SIG_IGN);
        while(1){
-               err = os_read_file(aio_req_fd_r, &req, sizeof(req));
+               err = read(aio_req_fd_r, &req, sizeof(req));
                if(err != sizeof(req)){
                        if(err < 0)
                                printk("not_aio_thread - read failed, "
                                       "fd = %d, err = %d\n", aio_req_fd_r,
-                                      -err);
+                                      errno);
                        else {
                                printk("not_aio_thread - short read, fd = %d, "
                                       "length = %d\n", aio_req_fd_r, err);
@@ -207,11 +200,11 @@ static int not_aio_thread(void *arg)
                }
                err = do_not_aio(&req);
                reply = ((struct aio_thread_reply) { .data      = req.aio,
-                                        .err   = err });
-               err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
+                                                    .err       = err });
+               err = write(req.aio->reply_fd, &reply, sizeof(reply));
                if(err != sizeof(reply))
                        printk("not_aio_thread - write failed, fd = %d, "
-                              "err = %d\n", req.aio->reply_fd, -err);
+                              "err = %d\n", req.aio->reply_fd, errno);
        }
 
        return 0;
@@ -228,6 +221,11 @@ static int init_aio_24(void)
 
        aio_req_fd_w = fds[0];
        aio_req_fd_r = fds[1];
+
+       err = os_set_fd_block(aio_req_fd_w, 0);
+       if(err)
+               goto out_close_pipe;
+
        err = run_helper_thread(not_aio_thread, NULL,
                                CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
        if(err < 0)
@@ -285,10 +283,12 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
        if(err){
                reply = ((struct aio_thread_reply) { .data = aio,
                                         .err  = err });
-               err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
-               if(err != sizeof(reply))
+               err = write(aio->reply_fd, &reply, sizeof(reply));
+               if(err != sizeof(reply)){
+                       err = -errno;
                        printk("submit_aio_26 - write failed, "
                               "fd = %d, err = %d\n", aio->reply_fd, -err);
+               }
                else err = 0;
        }
 
@@ -383,9 +383,10 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
        };
        int err;
 
-       err = os_write_file(aio_req_fd_w, &req, sizeof(req));
+       err = write(aio_req_fd_w, &req, sizeof(req));
        if(err == sizeof(req))
                err = 0;
+       else err = -errno;
 
        return err;
 }
index 863981b..acba301 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
  * Licensed under the GPL.
 #include <net/if.h>
 #include "user.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "net_user.h"
 #include "etap.h"
 #include "os.h"
 #include "um_malloc.h"
+#include "kern_constants.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
 
-void etap_user_init(void *data, void *dev)
+static int etap_user_init(void *data, void *dev)
 {
        struct ethertap_data *pri = data;
 
        pri->dev = dev;
+       return 0;
 }
 
 struct addr_change {
@@ -47,13 +48,16 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
        change.what = op;
        memcpy(change.addr, addr, sizeof(change.addr));
        memcpy(change.netmask, netmask, sizeof(change.netmask));
-       n = os_write_file(fd, &change, sizeof(change));
-       if(n != sizeof(change))
-               printk("etap_change - request failed, err = %d\n", -n);
-       output = um_kmalloc(page_size());
+       CATCH_EINTR(n = write(fd, &change, sizeof(change)));
+       if(n != sizeof(change)){
+               printk("etap_change - request failed, err = %d\n", errno);
+               return;
+       }
+
+       output = um_kmalloc(UM_KERN_PAGE_SIZE);
        if(output == NULL)
                printk("etap_change : Failed to allocate output buffer\n");
-       read_output(fd, output, page_size());
+       read_output(fd, output, UM_KERN_PAGE_SIZE);
        if(output != NULL){
                printk("%s", output);
                kfree(output);
@@ -115,13 +119,15 @@ static int etap_tramp(char *dev, char *gate, int control_me,
        pe_data.data_me = data_me;
        pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
 
-       if(pid < 0) err = pid;
+       if(pid < 0)
+               err = pid;
        os_close_file(data_remote);
        os_close_file(control_remote);
-       n = os_read_file(control_me, &c, sizeof(c));
+       CATCH_EINTR(n = read(control_me, &c, sizeof(c)));
        if(n != sizeof(c)){
-               printk("etap_tramp : read of status failed, err = %d\n", -n);
-               return(-EINVAL);
+               err = -errno;
+               printk("etap_tramp : read of status failed, err = %d\n", -err);
+               return err;
        }
        if(c != 1){
                printk("etap_tramp : uml_net failed\n");
@@ -132,7 +138,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
                else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
                        printk("uml_net didn't exit with status 1\n");
        }
-       return(err);
+       return err;
 }
 
 static int etap_open(void *data)
@@ -142,23 +148,24 @@ static int etap_open(void *data)
        int data_fds[2], control_fds[2], err, output_len;
 
        err = tap_open_common(pri->dev, pri->gate_addr);
-       if(err) return(err);
+       if(err)
+               return err;
 
        err = os_pipe(data_fds, 0, 0);
        if(err < 0){
                printk("data os_pipe failed - err = %d\n", -err);
-               return(err);
+               return err;
        }
 
        err = os_pipe(control_fds, 1, 0);
        if(err < 0){
                printk("control os_pipe failed - err = %d\n", -err);
-               return(err);
+               return err;
        }
-       
+
        err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], 
                         control_fds[1], data_fds[0], data_fds[1]);
-       output_len = page_size();
+       output_len = UM_KERN_PAGE_SIZE;
        output = um_kmalloc(output_len);
        read_output(control_fds[0], output, output_len);
 
@@ -171,13 +178,13 @@ static int etap_open(void *data)
 
        if(err < 0){
                printk("etap_tramp failed - err = %d\n", -err);
-               return(err);
+               return err;
        }
 
        pri->data_fd = data_fds[0];
        pri->control_fd = control_fds[0];
        iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
-       return(data_fds[0]);
+       return data_fds[0];
 }
 
 static void etap_close(int fd, void *data)
@@ -195,7 +202,7 @@ static void etap_close(int fd, void *data)
 
 static int etap_set_mtu(int mtu, void *data)
 {
-       return(mtu);
+       return mtu;
 }
 
 static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
@@ -204,7 +211,8 @@ static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
        struct ethertap_data *pri = data;
 
        tap_check_ips(pri->gate_addr, addr);
-       if(pri->control_fd == -1) return;
+       if(pri->control_fd == -1)
+               return;
        etap_open_addr(addr, netmask, &pri->control_fd);
 }
 
@@ -213,7 +221,8 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
 {
        struct ethertap_data *pri = data;
 
-       if(pri->control_fd == -1) return;
+       if(pri->control_fd == -1)
+               return;
        etap_close_addr(addr, netmask, &pri->control_fd);
 }
 
@@ -227,14 +236,3 @@ const struct net_user_info ethertap_user_info = {
        .delete_address = etap_del_addr,
        .max_packet     = MAX_PACKET - ETH_HEADER_ETHERTAP
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index e846b23..11a9779 100644 (file)
 #include "net_user.h"
 #include "tuntap.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "user.h"
 #include "os.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
 
-void tuntap_user_init(void *data, void *dev)
+static int tuntap_user_init(void *data, void *dev)
 {
        struct tuntap_data *pri = data;
 
        pri->dev = dev;
+       return 0;
 }
 
 static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
@@ -37,7 +37,8 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
        struct tuntap_data *pri = data;
 
        tap_check_ips(pri->gate_addr, addr);
-       if((pri->fd == -1) || pri->fixed_config) return;
+       if((pri->fd == -1) || pri->fixed_config)
+               return;
        open_addr(addr, netmask, pri->dev_name);
 }
 
@@ -46,7 +47,8 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
 {
        struct tuntap_data *pri = data;
 
-       if((pri->fd == -1) || pri->fixed_config) return;
+       if((pri->fd == -1) || pri->fixed_config)
+               return;
        close_addr(addr, netmask, pri->dev_name);
 }
 
@@ -58,7 +60,7 @@ struct tuntap_pre_exec_data {
 static void tuntap_pre_exec(void *arg)
 {
        struct tuntap_pre_exec_data *data = arg;
-       
+
        dup2(data->stdout, 1);
        os_close_file(data->close_me);
 }
@@ -83,7 +85,8 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
 
        pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
 
-       if(pid < 0) return(-pid);
+       if(pid < 0)
+               return -pid;
 
        os_close_file(remote);
 
@@ -114,16 +117,16 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
        cmsg = CMSG_FIRSTHDR(&msg);
        if(cmsg == NULL){
                printk("tuntap_open_tramp : didn't receive a message\n");
-               return(-EINVAL);
+               return -EINVAL;
        }
        if((cmsg->cmsg_level != SOL_SOCKET) || 
           (cmsg->cmsg_type != SCM_RIGHTS)){
                printk("tuntap_open_tramp : didn't receive a descriptor\n");
-               return(-EINVAL);
+               return -EINVAL;
        }
        *fd_out = ((int *) CMSG_DATA(cmsg))[0];
        os_set_exec_close(*fd_out, 1);
-       return(0);
+       return 0;
 }
 
 static int tuntap_open(void *data)
@@ -135,7 +138,7 @@ static int tuntap_open(void *data)
 
        err = tap_open_common(pri->dev, pri->gate_addr);
        if(err < 0)
-               return(err);
+               return err;
 
        if(pri->fixed_config){
                pri->fd = os_open_file("/dev/net/tun",
@@ -143,7 +146,7 @@ static int tuntap_open(void *data)
                if(pri->fd < 0){
                        printk("Failed to open /dev/net/tun, err = %d\n",
                               -pri->fd);
-                       return(pri->fd);
+                       return pri->fd;
                }
                memset(&ifr, 0, sizeof(ifr));
                ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@@ -160,7 +163,7 @@ static int tuntap_open(void *data)
                if(err < 0){
                        printk("tuntap_open : os_pipe failed - err = %d\n",
                               -err);
-                       return(err);
+                       return err;
                }
 
                buffer = get_output_buffer(&len);
@@ -175,7 +178,7 @@ static int tuntap_open(void *data)
                        printk("%s", output);
                        free_output_buffer(buffer);
                        printk("tuntap_open_tramp failed - err = %d\n", -err);
-                       return(err);
+                       return err;
                }
 
                pri->dev_name = uml_strdup(buffer);
@@ -187,7 +190,7 @@ static int tuntap_open(void *data)
                iter_addresses(pri->dev, open_addr, pri->dev_name);
        }
 
-       return(pri->fd);
+       return pri->fd;
 }
 
 static void tuntap_close(int fd, void *data)
@@ -202,7 +205,7 @@ static void tuntap_close(int fd, void *data)
 
 static int tuntap_set_mtu(int mtu, void *data)
 {
-       return(mtu);
+       return mtu;
 }
 
 const struct net_user_info tuntap_user_info = {
@@ -215,14 +218,3 @@ const struct net_user_info tuntap_user_info = {
        .delete_address = tuntap_del_addr,
        .max_packet     = MAX_PACKET
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 371b433..6f92f73 100644 (file)
@@ -18,7 +18,6 @@
 #include "os.h"
 #include "user.h"
 #include "kern_util.h"
-#include "user_util.h"
 
 static void copy_stat(struct uml_stat *dst, struct stat64 *src)
 {
@@ -291,54 +290,22 @@ int os_seek_file(int fd, __u64 offset)
        return 0;
 }
 
-static int fault_buffer(void *start, int len,
-                       int (*copy_proc)(void *addr, void *buf, int len))
-{
-       int page = getpagesize(), i;
-       char c;
-
-       for(i = 0; i < len; i += page){
-               if((*copy_proc)(start + i, &c, sizeof(c)))
-                       return -EFAULT;
-       }
-       if((len % page) != 0){
-               if((*copy_proc)(start + len - 1, &c, sizeof(c)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-static int file_io(int fd, void *buf, int len,
-                  int (*io_proc)(int fd, void *buf, int len),
-                  int (*copy_user_proc)(void *addr, void *buf, int len))
+int os_read_file(int fd, void *buf, int len)
 {
-       int n, err;
-
-       do {
-               n = (*io_proc)(fd, buf, len);
-               if((n < 0) && (errno == EFAULT)){
-                       err = fault_buffer(buf, len, copy_user_proc);
-                       if(err)
-                               return err;
-                       n = (*io_proc)(fd, buf, len);
-               }
-       } while((n < 0) && (errno == EINTR));
+       int n = read(fd, buf, len);
 
        if(n < 0)
                return -errno;
        return n;
 }
 
-int os_read_file(int fd, void *buf, int len)
-{
-       return file_io(fd, buf, len, (int (*)(int, void *, int)) read,
-                      copy_from_user_proc);
-}
-
 int os_write_file(int fd, const void *buf, int len)
 {
-       return file_io(fd, (void *) buf, len,
-                      (int (*)(int, void *, int)) write, copy_to_user_proc);
+       int n = write(fd, (void *) buf, len);
+
+       if(n < 0)
+               return -errno;
+       return n;
 }
 
 int os_file_size(char *file, unsigned long long *size_out)
index c7ad630..97bed16 100644 (file)
@@ -13,9 +13,9 @@
 #include <sys/wait.h>
 #include "user.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "os.h"
 #include "um_malloc.h"
+#include "kern_constants.h"
 
 struct helper_data {
        void (*pre_exec)(void*);
@@ -25,28 +25,18 @@ struct helper_data {
        char *buf;
 };
 
-/* Debugging aid, changed only from gdb */
-int helper_pause = 0;
-
-static void helper_hup(int sig)
-{
-}
-
 static int helper_child(void *arg)
 {
        struct helper_data *data = arg;
        char **argv = data->argv;
        int errval;
 
-       if (helper_pause){
-               signal(SIGHUP, helper_hup);
-               pause();
-       }
        if (data->pre_exec != NULL)
                (*data->pre_exec)(data->pre_data);
        errval = execvp_noalloc(data->buf, argv[0], argv);
-       printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval);
-       os_write_file(data->fd, &errval, sizeof(errval));
+       printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0],
+              -errval);
+       write(data->fd, &errval, sizeof(errval));
        kill(os_getpid(), SIGKILL);
        return 0;
 }
@@ -81,7 +71,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
                goto out_close;
        }
 
-       sp = stack + page_size() - sizeof(void *);
+       sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
        data.pre_exec = pre_exec;
        data.pre_data = pre_data;
        data.argv = argv;
@@ -98,13 +88,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
        close(fds[1]);
        fds[1] = -1;
 
-       /* Read the errno value from the child, if the exec failed, or get 0 if
-        * the exec succeeded because the pipe fd was set as close-on-exec. */
-       n = os_read_file(fds[0], &ret, sizeof(ret));
+       /*
+        * Read the errno value from the child, if the exec failed, or get 0 if
+        * the exec succeeded because the pipe fd was set as close-on-exec.
+        */
+       n = read(fds[0], &ret, sizeof(ret));
        if (n == 0) {
                ret = pid;
        } else {
                if (n < 0) {
+                       n = -errno;
                        printk("run_helper : read on pipe failed, ret = %d\n",
                               -n);
                        ret = n;
@@ -135,7 +128,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
        if (stack == 0)
                return -ENOMEM;
 
-       sp = stack + (page_size() << stack_order) - sizeof(void *);
+       sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *);
        pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
        if (pid < 0) {
                err = -errno;
index d1b61d4..a633fa8 100644 (file)
@@ -11,7 +11,6 @@
 #include <sys/poll.h>
 #include <sys/types.h>
 #include <sys/time.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
index 685feaa..ea9a236 100644 (file)
@@ -13,8 +13,8 @@
 #include <sys/mman.h>
 #include <sys/user.h>
 #include <asm/page.h>
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
 #include "mem_user.h"
 #include "irq_user.h"
 #include "user.h"
 #include "os.h"
 #include "um_malloc.h"
 
-/* Set in set_stklim, which is called from main and __wrap_malloc.
- * __wrap_malloc only calls it if main hasn't started.
- */
-unsigned long stacksizelim;
-
-/* Set in main */
+/* Set in main, unchanged thereafter */
 char *linux_prog;
 
 #define PGD_BOUND (4 * 1024 * 1024)
@@ -52,7 +47,6 @@ static void set_stklim(void)
                        exit(1);
                }
        }
-       stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
 }
 
 static __init void do_uml_initcalls(void)
@@ -126,7 +120,7 @@ extern int uml_exitcode;
 
 extern void scan_elf_aux( char **envp);
 
-int main(int argc, char **argv, char **envp)
+int __init main(int argc, char **argv, char **envp)
 {
        char **new_argv;
        int ret, i, err;
@@ -224,7 +218,7 @@ int main(int argc, char **argv, char **envp)
                ret = 1;
        }
        printf("\n");
-       return(uml_exitcode);
+       return uml_exitcode;
 }
 
 #define CAN_KMALLOC() \
@@ -237,7 +231,7 @@ void *__wrap_malloc(int size)
        void *ret;
 
        if(!CAN_KMALLOC())
-               return(__real_malloc(size));
+               return __real_malloc(size);
        else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
                ret = um_kmalloc(size);
        else ret = um_vmalloc(size);
@@ -248,16 +242,17 @@ void *__wrap_malloc(int size)
        if(ret == NULL)
                errno = ENOMEM;
 
-       return(ret);
+       return ret;
 }
 
 void *__wrap_calloc(int n, int size)
 {
        void *ptr = __wrap_malloc(n * size);
 
-       if(ptr == NULL) return(NULL);
+       if(ptr == NULL)
+               return NULL;
        memset(ptr, 0, n * size);
-       return(ptr);
+       return ptr;
 }
 
 extern void __real_free(void *);
index f1ea169..c6378c6 100644 (file)
@@ -11,7 +11,6 @@
 #include <sys/statfs.h>
 #include "kern_util.h"
 #include "user.h"
-#include "user_util.h"
 #include "mem_user.h"
 #include "init.h"
 #include "os.h"
@@ -165,7 +164,8 @@ found:
  * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
  * So it isn't 'static' yet.
  */
-int make_tempfile(const char *template, char **out_tempname, int do_unlink)
+int __init make_tempfile(const char *template, char **out_tempname,
+                        int do_unlink)
 {
        char *tempname;
        int fd;
@@ -206,7 +206,7 @@ out:
  * This proc is used in start_up.c
  * So it isn't 'static'.
  */
-int create_tmp_file(unsigned long long len)
+int __init create_tmp_file(unsigned long long len)
 {
        int fd, err;
        char zero;
@@ -232,17 +232,16 @@ int create_tmp_file(unsigned long long len)
 
        zero = 0;
 
-       err = os_write_file(fd, &zero, 1);
+       err = write(fd, &zero, 1);
        if(err != 1){
-               errno = -err;
-               perror("os_write_file");
+               perror("write");
                exit(1);
        }
 
        return fd;
 }
 
-int create_mem_file(unsigned long long len)
+int __init create_mem_file(unsigned long long len)
 {
        int err, fd;
 
@@ -257,7 +256,7 @@ int create_mem_file(unsigned long long len)
 }
 
 
-void check_tmpexec(void)
+void __init check_tmpexec(void)
 {
        void *addr;
        int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
index 76bdd67..92a7b59 100644 (file)
@@ -14,7 +14,6 @@
 #include "ptrace_user.h"
 #include "os.h"
 #include "user.h"
-#include "user_util.h"
 #include "process.h"
 #include "irq_user.h"
 #include "kern_util.h"
@@ -22,6 +21,7 @@
 #include "skas_ptrace.h"
 #include "kern_constants.h"
 #include "uml-config.h"
+#include "init.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -40,14 +40,14 @@ unsigned long os_process_pc(int pid)
        if(fd < 0){
                printk("os_process_pc - couldn't open '%s', err = %d\n",
                       proc_stat, -fd);
-               return(ARBITRARY_ADDR);
+               return ARBITRARY_ADDR;
        }
-       err = os_read_file(fd, buf, sizeof(buf));
+       CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
        if(err < 0){
                printk("os_process_pc - couldn't read '%s', err = %d\n",
-                      proc_stat, -err);
+                      proc_stat, errno);
                os_close_file(fd);
-               return(ARBITRARY_ADDR);
+               return ARBITRARY_ADDR;
        }
        os_close_file(fd);
        pc = ARBITRARY_ADDR;
@@ -56,7 +56,7 @@ unsigned long os_process_pc(int pid)
                  "%*d %*d %*d %*d %*d %lu", &pc) != 1){
                printk("os_process_pc - couldn't find pc in '%s'\n", buf);
        }
-       return(pc);
+       return pc;
 }
 
 int os_process_parent(int pid)
@@ -65,21 +65,22 @@ int os_process_parent(int pid)
        char data[256];
        int parent, n, fd;
 
-       if(pid == -1) return(-1);
+       if(pid == -1)
+               return -1;
 
        snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
        fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
        if(fd < 0){
                printk("Couldn't open '%s', err = %d\n", stat, -fd);
-               return(FAILURE_PID);
+               return FAILURE_PID;
        }
 
-       n = os_read_file(fd, data, sizeof(data));
+       CATCH_EINTR(n = read(fd, data, sizeof(data)));
        os_close_file(fd);
 
        if(n < 0){
-               printk("Couldn't read '%s', err = %d\n", stat, -n);
-               return(FAILURE_PID);
+               printk("Couldn't read '%s', err = %d\n", stat, errno);
+               return FAILURE_PID;
        }
 
        parent = FAILURE_PID;
@@ -87,7 +88,7 @@ int os_process_parent(int pid)
        if(n != 1)
                printk("Failed to scan '%s'\n", data);
 
-       return(parent);
+       return parent;
 }
 
 void os_stop_process(int pid)
@@ -145,7 +146,7 @@ void os_usr1_process(int pid)
 
 int os_getpid(void)
 {
-       return(syscall(__NR_getpid));
+       return syscall(__NR_getpid);
 }
 
 int os_getpgrp(void)
@@ -165,8 +166,8 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
        loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
                     fd, off);
        if(loc == MAP_FAILED)
-               return(-errno);
-       return(0);
+               return -errno;
+       return 0;
 }
 
 int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
@@ -175,8 +176,8 @@ int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
                    (x ? PROT_EXEC : 0));
 
         if(mprotect(addr, len, prot) < 0)
-               return(-errno);
-        return(0);
+               return -errno;
+        return 0;
 }
 
 int os_unmap_memory(void *addr, int len)
@@ -185,15 +186,15 @@ int os_unmap_memory(void *addr, int len)
 
         err = munmap(addr, len);
        if(err < 0)
-               return(-errno);
-        return(0);
+               return -errno;
+        return 0;
 }
 
 #ifndef MADV_REMOVE
 #define MADV_REMOVE KERNEL_MADV_REMOVE
 #endif
 
-int os_drop_memory(void *addr, int length)
+int __init os_drop_memory(void *addr, int length)
 {
        int err;
 
@@ -203,7 +204,7 @@ int os_drop_memory(void *addr, int length)
        return err;
 }
 
-int can_drop_memory(void)
+int __init can_drop_memory(void)
 {
        void *addr;
        int fd, ok = 0;
@@ -244,7 +245,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
 
        if(sig_stack != NULL){
                pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
-               set_sigstack(sig_stack, pages * page_size());
+               set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE);
                flags = SA_ONSTACK;
        }
        if(usr1_handler){
index 3fc43b3..8d4e0c6 100644 (file)
@@ -8,6 +8,7 @@
 #include <termios.h>
 #include <pty.h>
 #include <signal.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <sched.h>
 #include "init.h"
 #include "user.h"
 #include "kern_util.h"
-#include "user_util.h"
 #include "sigio.h"
 #include "os.h"
 #include "um_malloc.h"
+#include "init.h"
 
 /* Protected by sigio_lock(), also used by sigio_cleanup, which is an
  * exitcall.
@@ -68,11 +69,12 @@ static int write_sigio_thread(void *unused)
                        p = &fds->poll[i];
                        if(p->revents == 0) continue;
                        if(p->fd == sigio_private[1]){
-                               n = os_read_file(sigio_private[1], &c, sizeof(c));
+                               CATCH_EINTR(n = read(sigio_private[1], &c,
+                                                    sizeof(c)));
                                if(n != sizeof(c))
                                        printk("write_sigio_thread : "
                                               "read on socket failed, "
-                                              "err = %d\n", -n);
+                                              "err = %d\n", errno);
                                tmp = current_poll;
                                current_poll = next_poll;
                                next_poll = tmp;
@@ -85,10 +87,10 @@ static int write_sigio_thread(void *unused)
                                        (fds->used - i) * sizeof(*fds->poll));
                        }
 
-                       n = os_write_file(respond_fd, &c, sizeof(c));
+                       CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
                        if(n != sizeof(c))
                                printk("write_sigio_thread : write on socket "
-                                      "failed, err = %d\n", -n);
+                                      "failed, err = %d\n", errno);
                }
        }
 
@@ -126,15 +128,15 @@ static void update_thread(void)
        char c;
 
        flags = set_signals(0);
-       n = os_write_file(sigio_private[0], &c, sizeof(c));
+       n = write(sigio_private[0], &c, sizeof(c));
        if(n != sizeof(c)){
-               printk("update_thread : write failed, err = %d\n", -n);
+               printk("update_thread : write failed, err = %d\n", errno);
                goto fail;
        }
 
-       n = os_read_file(sigio_private[0], &c, sizeof(c));
+       CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
        if(n != sizeof(c)){
-               printk("update_thread : read failed, err = %d\n", -n);
+               printk("update_thread : read failed, err = %d\n", errno);
                goto fail;
        }
 
@@ -320,6 +322,10 @@ out_close1:
        close(l_write_sigio_fds[1]);
 }
 
+/* Changed during early boot */
+static int pty_output_sigio = 0;
+static int pty_close_sigio = 0;
+
 void maybe_sigio_broken(int fd, int read)
 {
        int err;
@@ -357,3 +363,143 @@ static void sigio_cleanup(void)
 }
 
 __uml_exitcall(sigio_cleanup);
+
+/* Used as a flag during SIGIO testing early in boot */
+static volatile int got_sigio = 0;
+
+static void __init handler(int sig)
+{
+       got_sigio = 1;
+}
+
+struct openpty_arg {
+       int master;
+       int slave;
+       int err;
+};
+
+static void openpty_cb(void *arg)
+{
+       struct openpty_arg *info = arg;
+
+       info->err = 0;
+       if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
+               info->err = -errno;
+}
+
+static int async_pty(int master, int slave)
+{
+       int flags;
+
+       flags = fcntl(master, F_GETFL);
+       if(flags < 0)
+               return -errno;
+
+       if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+          (fcntl(master, F_SETOWN, os_getpid()) < 0))
+               return -errno;
+
+       if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+               return -errno;
+
+       return(0);
+}
+
+static void __init check_one_sigio(void (*proc)(int, int))
+{
+       struct sigaction old, new;
+       struct openpty_arg pty = { .master = -1, .slave = -1 };
+       int master, slave, err;
+
+       initial_thread_cb(openpty_cb, &pty);
+       if(pty.err){
+               printk("openpty failed, errno = %d\n", -pty.err);
+               return;
+       }
+
+       master = pty.master;
+       slave = pty.slave;
+
+       if((master == -1) || (slave == -1)){
+               printk("openpty failed to allocate a pty\n");
+               return;
+       }
+
+       /* Not now, but complain so we now where we failed. */
+       err = raw(master);
+       if (err < 0)
+               panic("check_sigio : __raw failed, errno = %d\n", -err);
+
+       err = async_pty(master, slave);
+       if(err < 0)
+               panic("tty_fds : sigio_async failed, err = %d\n", -err);
+
+       if(sigaction(SIGIO, NULL, &old) < 0)
+               panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
+       new = old;
+       new.sa_handler = handler;
+       if(sigaction(SIGIO, &new, NULL) < 0)
+               panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
+
+       got_sigio = 0;
+       (*proc)(master, slave);
+
+       close(master);
+       close(slave);
+
+       if(sigaction(SIGIO, &old, NULL) < 0)
+               panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
+}
+
+static void tty_output(int master, int slave)
+{
+       int n;
+       char buf[512];
+
+       printk("Checking that host ptys support output SIGIO...");
+
+       memset(buf, 0, sizeof(buf));
+
+       while(write(master, buf, sizeof(buf)) > 0) ;
+       if(errno != EAGAIN)
+               panic("tty_output : write failed, errno = %d\n", errno);
+       while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+
+       if(got_sigio){
+               printk("Yes\n");
+               pty_output_sigio = 1;
+       }
+       else if(n == -EAGAIN)
+               printk("No, enabling workaround\n");
+       else panic("tty_output : read failed, err = %d\n", n);
+}
+
+static void tty_close(int master, int slave)
+{
+       printk("Checking that host ptys support SIGIO on close...");
+
+       close(slave);
+       if(got_sigio){
+               printk("Yes\n");
+               pty_close_sigio = 1;
+       }
+       else printk("No, enabling workaround\n");
+}
+
+void __init check_sigio(void)
+{
+       if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+          (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
+               printk("No pseudo-terminals available - skipping pty SIGIO "
+                      "check\n");
+               return;
+       }
+       check_one_sigio(tty_output);
+       check_one_sigio(tty_close);
+}
+
+/* Here because it only does the SIGIO testing for now */
+void __init os_check_bugs(void)
+{
+       check_sigio();
+}
index 2667686..48d4934 100644 (file)
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <string.h>
 #include <sys/mman.h>
-#include "user_util.h"
 #include "user.h"
 #include "signal_kern.h"
 #include "sysdep/sigcontext.h"
index 9383e87..8e490ff 100644 (file)
@@ -6,6 +6,7 @@
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
 #include <asm/page.h>
 #include "os.h"
 #include "proc_mm.h"
 #include "ptrace_user.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "task.h"
 #include "registers.h"
 #include "uml-config.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/stub.h"
+#include "init.h"
 
 extern unsigned long batch_syscall_stub, __syscall_stub_start;
 
-extern void wait_stub_done(int pid, int sig, char * fname);
+extern void wait_stub_done(int pid);
 
 static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
                                              unsigned long *stack)
@@ -39,6 +40,19 @@ static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
        return stack;
 }
 
+static unsigned long syscall_regs[MAX_REG_NR];
+
+static int __init init_syscall_regs(void)
+{
+       get_safe_registers(syscall_regs, NULL);
+       syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+               ((unsigned long) &batch_syscall_stub -
+                (unsigned long) &__syscall_stub_start);
+       return 0;
+}
+
+__initcall(init_syscall_regs);
+
 extern int proc_mm;
 
 int single_count = 0;
@@ -47,12 +61,11 @@ int multi_op_count = 0;
 
 static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
 {
-       unsigned long regs[MAX_REG_NR];
        int n, i;
        long ret, offset;
        unsigned long * data;
        unsigned long * syscall;
-       int pid = mm_idp->u.pid;
+       int err, pid = mm_idp->u.pid;
 
        if(proc_mm)
 #warning Need to look up userspace_pid by cpu
@@ -60,21 +73,21 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
 
        multi_count++;
 
-       get_safe_registers(regs, NULL);
-       regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
-               ((unsigned long) &batch_syscall_stub -
-                (unsigned long) &__syscall_stub_start);
-
-       n = ptrace_setregs(pid, regs);
+       n = ptrace_setregs(pid, syscall_regs);
        if(n < 0){
                printk("Registers - \n");
                for(i = 0; i < MAX_REG_NR; i++)
-                       printk("\t%d\t0x%lx\n", i, regs[i]);
+                       printk("\t%d\t0x%lx\n", i, syscall_regs[i]);
                panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
                      -n);
        }
 
-       wait_stub_done(pid, 0, "do_syscall_stub");
+       err = ptrace(PTRACE_CONT, pid, 0, 0);
+       if(err)
+               panic("Failed to continue stub, pid = %d, errno = %d\n", pid,
+                     errno);
+
+       wait_stub_done(pid);
 
        /* When the stub stops, we find the following values on the
         * beginning of the stack:
@@ -176,14 +189,10 @@ long syscall_stub_data(struct mm_id * mm_idp,
        return 0;
 }
 
-int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
-       int r, int w, int x, int phys_fd, unsigned long long offset,
-       int done, void **data)
+int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
+       int phys_fd, unsigned long long offset, int done, void **data)
 {
-       int prot, ret;
-
-       prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-               (x ? PROT_EXEC : 0);
+       int ret;
 
        if(proc_mm){
                struct proc_mm_op map;
@@ -200,9 +209,11 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
                                           .fd  = phys_fd,
                                           .offset= offset
                                         } } } );
-               ret = os_write_file(fd, &map, sizeof(map));
-               if(ret != sizeof(map))
+               CATCH_EINTR(ret = write(fd, &map, sizeof(map)));
+               if(ret != sizeof(map)){
+                       ret = -errno;
                        printk("map : /proc/mm map failed, err = %d\n", -ret);
+               }
                else ret = 0;
        }
        else {
@@ -217,8 +228,8 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
        return ret;
 }
 
-int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
-         void **data)
+int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
+         int done, void **data)
 {
        int ret;
 
@@ -232,9 +243,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
                                           { .addr      =
                                             (unsigned long) addr,
                                             .len               = len } } } );
-               ret = os_write_file(fd, &unmap, sizeof(unmap));
-               if(ret != sizeof(unmap))
+               CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap)));
+               if(ret != sizeof(unmap)){
+                       ret = -errno;
                        printk("unmap - proc_mm write returned %d\n", ret);
+               }
                else ret = 0;
        }
        else {
@@ -249,13 +262,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
 }
 
 int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
-           int r, int w, int x, int done, void **data)
+           unsigned int prot, int done, void **data)
 {
        struct proc_mm_op protect;
-       int prot, ret;
+       int ret;
 
-       prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-               (x ? PROT_EXEC : 0);
        if(proc_mm){
                int fd = mm_idp->u.mm_fd;
 
@@ -267,9 +278,11 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
                                               .len     = len,
                                               .prot    = prot } } } );
 
-               ret = os_write_file(fd, &protect, sizeof(protect));
-               if(ret != sizeof(protect))
+               CATCH_EINTR(ret = write(fd, &protect, sizeof(protect)));
+               if(ret != sizeof(protect)){
+                       ret = -errno;
                        printk("protect failed, err = %d", -ret);
+               }
                else ret = 0;
        }
        else {
index 0564422..5c088a5 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/types.h>
 #include "user.h"
 #include "sysdep/ptrace.h"
-#include "user_util.h"
 #include "kern_util.h"
 #include "skas.h"
 #include "stub-data.h"
@@ -34,6 +33,8 @@
 #include "uml-config.h"
 #include "process.h"
 #include "longjmp.h"
+#include "kern_constants.h"
+#include "as-layout.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
@@ -44,45 +45,58 @@ int is_skas_winch(int pid, int fd, void *data)
        return(1);
 }
 
-void wait_stub_done(int pid, int sig, char * fname)
+static int ptrace_dump_regs(int pid)
 {
-       int n, status, err;
+        unsigned long regs[MAX_REG_NR];
+        int i;
+
+        if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+                return -errno;
+        else {
+                printk("Stub registers -\n");
+                for(i = 0; i < ARRAY_SIZE(regs); i++)
+                        printk("\t%d - %lx\n", i, regs[i]);
+        }
+
+        return 0;
+}
 
-       do {
-               if ( sig != -1 ) {
-                       err = ptrace(PTRACE_CONT, pid, 0, sig);
-                       if(err)
-                               panic("%s : continue failed, errno = %d\n",
-                                     fname, errno);
-               }
-               sig = 0;
+/*
+ * Signals that are OK to receive in the stub - we'll just continue it.
+ * SIGWINCH will happen when UML is inside a detached screen.
+ */
+#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
+
+/* Signals that the stub will finish with - anything else is an error */
+#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
+
+void wait_stub_done(int pid)
+{
+       int n, status, err;
 
+       while(1){
                CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
-       } while((n >= 0) && WIFSTOPPED(status) &&
-               ((WSTOPSIG(status) == SIGVTALRM) ||
-                /* running UML inside a detached screen can cause
-                 * SIGWINCHes
-                 */
-                (WSTOPSIG(status) == SIGWINCH)));
-
-       if((n < 0) || !WIFSTOPPED(status) ||
-          (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
-               unsigned long regs[MAX_REG_NR];
-
-               if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
-                       printk("Failed to get registers from stub, "
-                              "errno = %d\n", errno);
-               else {
-                       int i;
-
-                       printk("Stub registers -\n");
-                       for(i = 0; i < ARRAY_SIZE(regs); i++)
-                               printk("\t%d - %lx\n", i, regs[i]);
-               }
-               panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
-                     "pid = %d, n = %d, errno = %d, status = 0x%x\n",
-                     fname, pid, n, errno, status);
+               if((n < 0) || !WIFSTOPPED(status))
+                       goto bad_wait;
+
+               if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
+                       break;
+
+               err = ptrace(PTRACE_CONT, pid, 0, 0);
+               if(err)
+                       panic("wait_stub_done : continue failed, errno = %d\n",
+                             errno);
        }
+
+       if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
+               return;
+
+bad_wait:
+       err = ptrace_dump_regs(pid);
+       if(err)
+               printk("Failed to get registers from stub, errno = %d\n", -err);
+       panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
+             "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
 }
 
 extern unsigned long current_stub_stack(void);
@@ -104,7 +118,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
                               sizeof(struct ptrace_faultinfo));
        }
        else {
-               wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
+               err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
+               if(err)
+                       panic("Failed to continue stub, pid = %d, errno = %d\n",
+                             pid, errno);
+               wait_stub_done(pid);
 
                /* faultinfo is prepared by the stub-segv-handler at start of
                 * the stub stack page. We just have to copy it.
@@ -142,9 +160,14 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
 
                CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
                if((err < 0) || !WIFSTOPPED(status) ||
-                  (WSTOPSIG(status) != SIGTRAP + 0x80))
+                  (WSTOPSIG(status) != SIGTRAP + 0x80)){
+                        err = ptrace_dump_regs(pid);
+                        if(err)
+                                printk("Failed to get registers from process, "
+                                       "errno = %d\n", -err);
                        panic("handle_trap - failed to wait at end of syscall, "
                              "errno = %d, status = %d\n", errno, status);
+                }
        }
 
        handle_syscall(regs);
@@ -172,7 +195,7 @@ static int userspace_tramp(void *stack)
                int fd;
                __u64 offset;
                fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
-               addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
+               addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE,
                              PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
                if(addr == MAP_FAILED){
                        printk("mapping mmap stub failed, errno = %d\n",
@@ -182,8 +205,8 @@ static int userspace_tramp(void *stack)
 
                if(stack != NULL){
                        fd = phys_mapping(to_phys(stack), &offset);
-                       addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
-                                   PROT_READ | PROT_WRITE,
+                       addr = mmap((void *) UML_CONFIG_STUB_DATA,
+                                   UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
                                    MAP_FIXED | MAP_SHARED, fd, offset);
                        if(addr == MAP_FAILED){
                                printk("mapping segfault stack failed, "
@@ -199,7 +222,7 @@ static int userspace_tramp(void *stack)
                                  (unsigned long) stub_segv_handler -
                                  (unsigned long) &__syscall_stub_start;
 
-               set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
+               set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE);
                sigemptyset(&sa.sa_mask);
                sigaddset(&sa.sa_mask, SIGIO);
                sigaddset(&sa.sa_mask, SIGWINCH);
@@ -291,10 +314,13 @@ void userspace(union uml_pt_regs *regs)
                UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
 
                if(WIFSTOPPED(status)){
-                       switch(WSTOPSIG(status)){
+                       int sig = WSTOPSIG(status);
+                       switch(sig){
                        case SIGSEGV:
-                               if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
-                                       user_signal(SIGSEGV, regs, pid);
+                               if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
+                                       get_skas_faultinfo(pid, &regs->skas.faultinfo);
+                                       (*sig_info[SIGSEGV])(SIGSEGV, regs);
+                               }
                                else handle_segv(pid, regs);
                                break;
                        case SIGTRAP + 0x80:
@@ -309,11 +335,13 @@ void userspace(union uml_pt_regs *regs)
                        case SIGBUS:
                        case SIGFPE:
                        case SIGWINCH:
-                               user_signal(WSTOPSIG(status), regs, pid);
+                               block_signals();
+                               (*sig_info[sig])(sig, regs);
+                               unblock_signals();
                                break;
                        default:
                                printk("userspace - child stopped with signal "
-                                      "%d\n", WSTOPSIG(status));
+                                      "%d\n", sig);
                        }
                        pid = userspace_pid[0];
                        interrupt_end();
@@ -325,11 +353,29 @@ void userspace(union uml_pt_regs *regs)
        }
 }
 
+static unsigned long thread_regs[MAX_REG_NR];
+static unsigned long thread_fp_regs[HOST_FP_SIZE];
+
+static int __init init_thread_regs(void)
+{
+       get_safe_registers(thread_regs, thread_fp_regs);
+       /* Set parent's instruction pointer to start of clone-stub */
+       thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+                               (unsigned long) stub_clone_handler -
+                               (unsigned long) &__syscall_stub_start;
+       thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
+               sizeof(void *);
+#ifdef __SIGNAL_FRAMESIZE
+       thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
+#endif
+       return 0;
+}
+
+__initcall(init_thread_regs);
+
 int copy_context_skas0(unsigned long new_stack, int pid)
 {
        int err;
-       unsigned long regs[MAX_REG_NR];
-       unsigned long fp_regs[HOST_FP_SIZE];
        unsigned long current_stack = current_stub_stack();
        struct stub_data *data = (struct stub_data *) current_stack;
        struct stub_data *child_data = (struct stub_data *) new_stack;
@@ -344,23 +390,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
                                      .timer    = ((struct itimerval)
                                                    { { 0, 1000000 / hz() },
                                                      { 0, 1000000 / hz() }})});
-       get_safe_registers(regs, fp_regs);
-
-       /* Set parent's instruction pointer to start of clone-stub */
-       regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
-                               (unsigned long) stub_clone_handler -
-                               (unsigned long) &__syscall_stub_start;
-       regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
-               sizeof(void *);
-#ifdef __SIGNAL_FRAMESIZE
-       regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
-#endif
-       err = ptrace_setregs(pid, regs);
+       err = ptrace_setregs(pid, thread_regs);
        if(err < 0)
                panic("copy_context_skas0 : PTRACE_SETREGS failed, "
                      "pid = %d, errno = %d\n", pid, -err);
 
-       err = ptrace_setfpregs(pid, fp_regs);
+       err = ptrace_setfpregs(pid, thread_fp_regs);
        if(err < 0)
                panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
                      "pid = %d, errno = %d\n", pid, -err);
@@ -371,7 +406,11 @@ int copy_context_skas0(unsigned long new_stack, int pid)
        /* Wait, until parent has finished its work: read child's pid from
         * parent's stack, and check, if bad result.
         */
-       wait_stub_done(pid, 0, "copy_context_skas0");
+       err = ptrace(PTRACE_CONT, pid, 0, 0);
+       if(err)
+               panic("Failed to continue new process, pid = %d, "
+                     "errno = %d\n", pid, errno);
+       wait_stub_done(pid);
 
        pid = data->err;
        if(pid < 0)
@@ -381,7 +420,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
        /* Wait, until child has finished too: read child's result from
         * child's stack and check it.
         */
-       wait_stub_done(pid, -1, "copy_context_skas0");
+       wait_stub_done(pid);
        if (child_data->err != UML_CONFIG_STUB_DATA)
                panic("copy_context_skas0 - stub-child reports error %ld\n",
                      child_data->err);
@@ -396,7 +435,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
 
 /*
  * This is used only, if stub pages are needed, while proc_mm is
- * availabl. Opening /proc/mm creates a new mm_context, which lacks
+ * available. Opening /proc/mm creates a new mm_context, which lacks
  * the stub-pages. Thus, we map them using /proc/mm-fd
  */
 void map_stub_pages(int fd, unsigned long code,
@@ -418,12 +457,13 @@ void map_stub_pages(int fd, unsigned long code,
                                          .fd      = code_fd,
                                          .offset  = code_offset
        } } });
-       n = os_write_file(fd, &mmop, sizeof(mmop));
+       CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
        if(n != sizeof(mmop)){
+               n = errno;
                printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
                       code, code_fd, (unsigned long long) code_offset);
                panic("map_stub_pages : /proc/mm map for code failed, "
-                     "err = %d\n", -n);
+                     "err = %d\n", n);
        }
 
        if ( stack ) {
@@ -440,10 +480,10 @@ void map_stub_pages(int fd, unsigned long code,
                                      .fd      = map_fd,
                                      .offset  = map_offset
                } } });
-               n = os_write_file(fd, &mmop, sizeof(mmop));
+               CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
                if(n != sizeof(mmop))
                        panic("map_stub_pages : /proc/mm map for data failed, "
-                             "err = %d\n", -n);
+                             "err = %d\n", errno);
        }
 }
 
@@ -480,7 +520,15 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
                    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
                    SIGVTALRM, -1);
 
-       n = UML_SETJMP(&initial_jmpbuf);
+       /*
+        * Can't use UML_SETJMP or UML_LONGJMP here because they save
+        * and restore signals, with the possible side-effect of
+        * trying to handle any signals which came when they were
+        * blocked, which can't be done on this stack.
+        * Signals must be blocked when jumping back here and restored
+        * after returning to the jumper.
+        */
+       n = setjmp(initial_jmpbuf);
        switch(n){
        case INIT_JMP_NEW_THREAD:
                (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
@@ -490,7 +538,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
                break;
        case INIT_JMP_CALLBACK:
                (*cb_proc)(cb_arg);
-               UML_LONGJMP(cb_back, 1);
+               longjmp(*cb_back, 1);
                break;
        case INIT_JMP_HALT:
                kmalloc_ok = 0;
@@ -501,7 +549,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
        default:
                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
        }
-       UML_LONGJMP(switch_buf, 1);
+       longjmp(*switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
index 9ad5fbe..3b600c2 100644 (file)
@@ -5,8 +5,8 @@
 
 #include <signal.h>
 #include <errno.h>
-#include "user_util.h"
 #include "kern_util.h"
+#include "as-layout.h"
 #include "task.h"
 #include "sigcontext.h"
 #include "skas.h"
 #include "sysdep/ptrace_user.h"
 #include "os.h"
 
+static union uml_pt_regs ksig_regs[UM_NR_CPUS];
+
 void sig_handler_common_skas(int sig, void *sc_ptr)
 {
        struct sigcontext *sc = sc_ptr;
-       struct skas_regs *r;
+       union uml_pt_regs *r;
        void (*handler)(int, union uml_pt_regs *);
-       int save_errno = errno;
-       int save_user;
+       int save_user, save_errno = errno;
 
        /* This is done because to allow SIGSEGV to be delivered inside a SEGV
         * handler.  This can happen in copy_user, and if SEGV is disabled,
         * the process will die.
         * XXX Figure out why this is better than SA_NODEFER
         */
-       if(sig == SIGSEGV)
+       if(sig == SIGSEGV) {
                change_sig(SIGSEGV, 1);
+               /* For segfaults, we want the data from the
+                * sigcontext.  In this case, we don't want to mangle
+                * the process registers, so use a static set of
+                * registers.  For other signals, the process
+                * registers are OK.
+                */
+               r = &ksig_regs[cpu()];
+               copy_sc(r, sc_ptr);
+       }
+       else r = TASK_REGS(get_current());
 
-       r = &TASK_REGS(get_current())->skas;
-       save_user = r->is_user;
-       r->is_user = 0;
+       save_user = r->skas.is_user;
+       r->skas.is_user = 0;
        if ( sig == SIGFPE || sig == SIGSEGV ||
             sig == SIGBUS || sig == SIGILL ||
             sig == SIGTRAP ) {
-               GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
+               GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc);
        }
 
        change_sig(SIGUSR1, 1);
@@ -49,25 +59,8 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
            sig != SIGVTALRM && sig != SIGALRM)
                unblock_signals();
 
-       handler(sig, (union uml_pt_regs *) r);
+       handler(sig, r);
 
        errno = save_errno;
-       r->is_user = save_user;
-}
-
-extern int ptrace_faultinfo;
-
-void user_signal(int sig, union uml_pt_regs *regs, int pid)
-{
-       void (*handler)(int, union uml_pt_regs *);
-       int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
-                   (sig == SIGILL) || (sig == SIGTRAP));
-
-       if (segv)
-               get_skas_faultinfo(pid, &regs->skas.faultinfo);
-
-       handler = sig_info[sig];
-       handler(sig, (union uml_pt_regs *) regs);
-
-       unblock_signals();
+       r->skas.is_user = save_user;
 }
index 5178eba..79471f8 100644 (file)
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/mman.h>
+#include <sys/resource.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
 #include <sys/types.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "signal_kern.h"
@@ -329,8 +329,32 @@ static void __init check_ptrace(void)
 
 extern void check_tmpexec(void);
 
-void os_early_checks(void)
+static void __init check_coredump_limit(void)
 {
+       struct rlimit lim;
+       int err = getrlimit(RLIMIT_CORE, &lim);
+
+       if(err){
+               perror("Getting core dump limit");
+               return;
+       }
+
+       printf("Core dump limits :\n\tsoft - ");
+       if(lim.rlim_cur == RLIM_INFINITY)
+               printf("NONE\n");
+       else printf("%lu\n", lim.rlim_cur);
+
+       printf("\thard - ");
+       if(lim.rlim_max == RLIM_INFINITY)
+               printf("NONE\n");
+       else printf("%lu\n", lim.rlim_max);
+}
+
+void __init os_early_checks(void)
+{
+       /* Print out the core dump limits early */
+       check_coredump_limit();
+
        check_ptrace();
 
        /* Need to check this early because mmapping happens before the
@@ -528,148 +552,3 @@ int __init parse_iomem(char *str, int *add)
  out:
        return 1;
 }
-
-
-/* Changed during early boot */
-int pty_output_sigio = 0;
-int pty_close_sigio = 0;
-
-/* Used as a flag during SIGIO testing early in boot */
-static volatile int got_sigio = 0;
-
-static void __init handler(int sig)
-{
-       got_sigio = 1;
-}
-
-struct openpty_arg {
-       int master;
-       int slave;
-       int err;
-};
-
-static void openpty_cb(void *arg)
-{
-       struct openpty_arg *info = arg;
-
-       info->err = 0;
-       if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
-               info->err = -errno;
-}
-
-static int async_pty(int master, int slave)
-{
-       int flags;
-
-       flags = fcntl(master, F_GETFL);
-       if(flags < 0)
-               return -errno;
-
-       if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-          (fcntl(master, F_SETOWN, os_getpid()) < 0))
-               return -errno;
-
-       if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
-               return -errno;
-
-       return(0);
-}
-
-static void __init check_one_sigio(void (*proc)(int, int))
-{
-       struct sigaction old, new;
-       struct openpty_arg pty = { .master = -1, .slave = -1 };
-       int master, slave, err;
-
-       initial_thread_cb(openpty_cb, &pty);
-       if(pty.err){
-               printk("openpty failed, errno = %d\n", -pty.err);
-               return;
-       }
-
-       master = pty.master;
-       slave = pty.slave;
-
-       if((master == -1) || (slave == -1)){
-               printk("openpty failed to allocate a pty\n");
-               return;
-       }
-
-       /* Not now, but complain so we now where we failed. */
-       err = raw(master);
-       if (err < 0)
-               panic("check_sigio : __raw failed, errno = %d\n", -err);
-
-       err = async_pty(master, slave);
-       if(err < 0)
-               panic("tty_fds : sigio_async failed, err = %d\n", -err);
-
-       if(sigaction(SIGIO, NULL, &old) < 0)
-               panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
-       new = old;
-       new.sa_handler = handler;
-       if(sigaction(SIGIO, &new, NULL) < 0)
-               panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
-
-       got_sigio = 0;
-       (*proc)(master, slave);
-
-       close(master);
-       close(slave);
-
-       if(sigaction(SIGIO, &old, NULL) < 0)
-               panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
-}
-
-static void tty_output(int master, int slave)
-{
-       int n;
-       char buf[512];
-
-       printk("Checking that host ptys support output SIGIO...");
-
-       memset(buf, 0, sizeof(buf));
-
-       while(os_write_file(master, buf, sizeof(buf)) > 0) ;
-       if(errno != EAGAIN)
-               panic("check_sigio : write failed, errno = %d\n", errno);
-       while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
-
-       if(got_sigio){
-               printk("Yes\n");
-               pty_output_sigio = 1;
-       }
-       else if(n == -EAGAIN) printk("No, enabling workaround\n");
-       else panic("check_sigio : read failed, err = %d\n", n);
-}
-
-static void tty_close(int master, int slave)
-{
-       printk("Checking that host ptys support SIGIO on close...");
-
-       close(slave);
-       if(got_sigio){
-               printk("Yes\n");
-               pty_close_sigio = 1;
-       }
-       else printk("No, enabling workaround\n");
-}
-
-void __init check_sigio(void)
-{
-       if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
-          (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
-               printk("No pseudo-terminals available - skipping pty SIGIO "
-                      "check\n");
-               return;
-       }
-       check_one_sigio(tty_output);
-       check_one_sigio(tty_close);
-}
-
-void os_check_bugs(void)
-{
-       check_ptrace();
-       check_sigio();
-}
-
index 2565320..32ed41e 100644 (file)
@@ -5,7 +5,7 @@
 #include <unistd.h>
 
 #include "sysdep/tls.h"
-#include "user_util.h"
+#include "user.h"
 
 /* Checks whether host supports TLS, and sets *tls_min according to the value
  * valid on the host.
index 2115b8b..5de169b 100644 (file)
@@ -10,7 +10,6 @@
 #include <sys/time.h>
 #include <signal.h>
 #include <errno.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
index d221214..295da65 100644 (file)
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <signal.h>
 #include "kern_util.h"
-#include "user_util.h"
 #include "os.h"
 #include "mode.h"
 #include "longjmp.h"
index 3dc3a02..bcf9359 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/ptrace.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "signal_kern.h"
@@ -32,6 +31,7 @@
 #include "choose-mode.h"
 #include "mode.h"
 #include "tempfile.h"
+#include "kern_constants.h"
 
 int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
                   int must_succeed)
@@ -143,7 +143,7 @@ int outer_tramp(void *arg)
        int sig = sigkill;
 
        t = arg;
-       t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2,
+       t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2,
                       t->flags, t->tramp_data);
        if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL);
        kill(os_getpid(), sig);
index c6ba56c..d11a55b 100644 (file)
@@ -53,9 +53,9 @@ int open_tty_log(void *tty, void *current_tty)
                                               .direction = 0,
                                               .sec = tv.tv_sec,
                                               .usec = tv.tv_usec } );
-               os_write_file(tty_log_fd, &data, sizeof(data));
-               os_write_file(tty_log_fd, &current_tty, data.len);
-               return(tty_log_fd);
+               write(tty_log_fd, &data, sizeof(data));
+               write(tty_log_fd, &current_tty, data.len);
+               return tty_log_fd;
        }
 
        sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
@@ -67,7 +67,7 @@ int open_tty_log(void *tty, void *current_tty)
                printk("open_tty_log : couldn't open '%s', errno = %d\n",
                       buf, -fd);
        }
-       return(fd);
+       return fd;
 }
 
 void close_tty_log(int fd, void *tty)
@@ -83,7 +83,7 @@ void close_tty_log(int fd, void *tty)
                                               .direction = 0,
                                               .sec = tv.tv_sec,
                                               .usec = tv.tv_usec } );
-               os_write_file(tty_log_fd, &data, sizeof(data));
+               write(tty_log_fd, &data, sizeof(data));
                return;
        }
        os_close_file(fd);
@@ -98,21 +98,21 @@ static int log_chunk(int fd, const char *buf, int len)
                try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
                missed = copy_from_user_proc(chunk, (char *) buf, try);
                try -= missed;
-               n = os_write_file(fd, chunk, try);
+               n = write(fd, chunk, try);
                if(n != try) {
                        if(n < 0)
-                               return(n);
-                       return(-EIO);
+                               return -errno;
+                       return -EIO;
                }
                if(missed != 0)
-                       return(-EFAULT);
+                       return -EFAULT;
 
                len -= try;
                total += try;
                buf += try;
        }
 
-       return(total);
+       return total;
 }
 
 int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
@@ -130,10 +130,10 @@ int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
                                               .direction = direction,
                                               .sec = tv.tv_sec,
                                               .usec = tv.tv_usec } );
-               os_write_file(tty_log_fd, &data, sizeof(data));
+               write(tty_log_fd, &data, sizeof(data));
        }
 
-       return(log_chunk(fd, buf, len));
+       return log_chunk(fd, buf, len);
 }
 
 void log_exec(char **argv, void *tty)
@@ -161,7 +161,7 @@ void log_exec(char **argv, void *tty)
                                       .direction = 0,
                                       .sec = tv.tv_sec,
                                       .usec = tv.tv_usec } );
-       os_write_file(tty_log_fd, &data, sizeof(data));
+       write(tty_log_fd, &data, sizeof(data));
 
        for(ptr = argv; ; ptr++){
                if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
@@ -179,7 +179,7 @@ extern void register_tty_logger(int (*opener)(void *, void *),
 static int register_logger(void)
 {
        register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
-       return(0);
+       return 0;
 }
 
 __uml_initcall(register_logger);
index 56b8a50..c307a89 100644 (file)
@@ -21,7 +21,6 @@
 #include <sched.h>
 #include <termios.h>
 #include <string.h>
-#include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "mem_user.h"
 #include "uml-config.h"
 #include "os.h"
 #include "longjmp.h"
+#include "kern_constants.h"
 
 void stack_protections(unsigned long address)
 {
        int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
 
-       if(mprotect((void *) address, page_size(), prot) < 0)
+       if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0)
                panic("protecting stack failed, errno = %d", errno);
 }
 
 void task_protections(unsigned long address)
 {
-       unsigned long guard = address + page_size();
-       unsigned long stack = guard + page_size();
+       unsigned long guard = address + UM_KERN_PAGE_SIZE;
+       unsigned long stack = guard + UM_KERN_PAGE_SIZE;
        int prot = 0, pages;
 
 #ifdef notdef
-       if(mprotect((void *) stack, page_size(), prot) < 0)
+       if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0)
                panic("protecting guard page failed, errno = %d", errno);
 #endif
        pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
        prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-       if(mprotect((void *) stack, pages * page_size(), prot) < 0)
+       if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0)
                panic("protecting stack failed, errno = %d", errno);
 }
 
@@ -96,15 +96,13 @@ void setup_machinename(char *machine_out)
        strcpy(machine_out, host.machine);
 }
 
-char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1];
-
-void setup_hostinfo(void)
+void setup_hostinfo(char *buf, int len)
 {
        struct utsname host;
 
        uname(&host);
-       sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename,
-               host.release, host.version, host.machine);
+       snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
+                host.release, host.version, host.machine);
 }
 
 int setjmp_wrapper(void (*proc)(void *, void *), ...)
@@ -121,3 +119,9 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
        va_end(args);
        return n;
 }
+
+void os_dump_core(void)
+{
+       signal(SIGSEGV, SIG_DFL);
+       abort();
+}
index f1bcd39..0393e44 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -13,7 +13,6 @@
 #include "sysdep/ptrace.h"
 #include "task.h"
 #include "os.h"
-#include "user_util.h"
 
 #define MAXTOKEN 64
 
@@ -32,21 +31,21 @@ static char token(int fd, char *buf, int len, char stop)
                n = os_read_file(fd, ptr, sizeof(*ptr));
                c = *ptr++;
                if(n != sizeof(*ptr)){
-                       if(n == 0) return(0);
+                       if(n == 0)
+                               return 0;
                        printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
                        if(n < 0)
-                               return(n);
-                       else
-                               return(-EIO);
+                               return n;
+                       else return -EIO;
                }
        } while((c != '\n') && (c != stop) && (ptr < end));
 
        if(ptr == end){
                printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
-               return(-1);
+               return -1;
        }
        *(ptr - 1) = '\0';
-       return(c);
+       return c;
 }
 
 static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
@@ -58,48 +57,25 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
        while(1){
                c = token(fd, scratch, len - 1, ':');
                if(c <= 0)
-                       return(0);
+                       return 0;
                else if(c != ':'){
                        printk("Failed to find ':' in /proc/cpuinfo\n");
-                       return(0);
+                       return 0;
                }
 
                if(!strncmp(scratch, key, strlen(key)))
-                       return(1);
+                       return 1;
 
                do {
                        n = os_read_file(fd, &c, sizeof(c));
                        if(n != sizeof(c)){
                                printk("Failed to find newline in "
                                       "/proc/cpuinfo, err = %d\n", -n);
-                               return(0);
+                               return 0;
                        }
                } while(c != '\n');
        }
-       return(0);
-}
-
-int cpu_feature(char *what, char *buf, int len)
-{
-       int fd, ret = 0;
-
-       fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
-       if(fd < 0){
-               printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
-               return(0);
-       }
-
-       if(!find_cpuinfo_line(fd, what, buf, len)){
-               printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
-               goto out_close;
-       }
-
-       token(fd, buf, len, '\n');
-       ret = 1;
-
- out_close:
-       os_close_file(fd);
-       return(ret);
+       return 0;
 }
 
 static int check_cpu_flag(char *feature, int *have_it)
@@ -119,7 +95,8 @@ static int check_cpu_flag(char *feature, int *have_it)
                goto out;
 
        c = token(fd, buf, len - 1, ' ');
-       if(c < 0) goto out;
+       if(c < 0)
+               goto out;
        else if(c != ' '){
                printk("Failed to find ' ' in /proc/cpuinfo\n");
                goto out;
@@ -127,7 +104,8 @@ static int check_cpu_flag(char *feature, int *have_it)
 
        while(1){
                c = token(fd, buf, len - 1, ' ');
-               if(c < 0) goto out;
+               if(c < 0)
+                       goto out;
                else if(c == '\n') break;
 
                if(!strcmp(buf, feature)){
@@ -136,8 +114,10 @@ static int check_cpu_flag(char *feature, int *have_it)
                }
        }
  out:
-       if(*have_it == 0) printk("No\n");
-       else if(*have_it == 1) printk("Yes\n");
+       if(*have_it == 0)
+               printk("No\n");
+       else if(*have_it == 1)
+               printk("Yes\n");
        os_close_file(fd);
        return 1;
 }
@@ -189,12 +169,13 @@ int arch_handle_signal(int sig, union uml_pt_regs *regs)
        /* This is testing for a cmov (0x0f 0x4x) instruction causing a
         * SIGILL in init.
         */
-       if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0);
+       if((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+               return 0;
 
        if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
                panic("SIGILL in init, could not read instructions!\n");
        if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
-               return(0);
+               return 0;
 
        if(host_has_cmov == 0)
                panic("SIGILL caused by cmov, which this processor doesn't "
@@ -208,16 +189,5 @@ int arch_handle_signal(int sig, union uml_pt_regs *regs)
                      "implements it, boot a filesystem compiled for older "
                      "processors");
        else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
-       return(0);
+       return 0;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index d0bbcdf..745b4fd 100644 (file)
@@ -3,9 +3,7 @@
  * Licensed under the GPL
  */
 
-#include <signal.h>
 #include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
 
 /* These two are from asm-um/uaccess.h and linux/module.h, check them. */
 struct exception_table_entry
@@ -17,26 +15,14 @@ struct exception_table_entry
 const struct exception_table_entry *search_exception_tables(unsigned long add);
 
 /* Compare this to arch/i386/mm/extable.c:fixup_exception() */
-int arch_fixup(unsigned long address, void *sc_ptr)
+int arch_fixup(unsigned long address, union uml_pt_regs *regs)
 {
-       struct sigcontext *sc = sc_ptr;
        const struct exception_table_entry *fixup;
 
        fixup = search_exception_tables(address);
        if(fixup != 0){
-               sc->eip = fixup->fixup;
+               UPT_IP(regs) = fixup->fixup;
                return(1);
        }
        return(0);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 01212c8..40ff0c8 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -15,7 +15,6 @@
 #include "user.h"
 #include "os.h"
 #include "uml-config.h"
-#include "user_util.h"
 
 int ptrace_getregs(long pid, unsigned long *regs_out)
 {
@@ -45,7 +44,8 @@ int ptrace_setfpregs(long pid, unsigned long *regs)
        return 0;
 }
 
-/* All the below stuff is of interest for TT mode only */
+#ifdef UML_CONFIG_MODE_TT
+
 static void write_debugregs(int pid, unsigned long *regs)
 {
        struct user *dummy;
@@ -128,13 +128,4 @@ void update_debugregs(int seq)
 }
 #endif
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
index 3f6acd6..1cbf95f 100644 (file)
 
 #include "skas.h"
 
+void copy_sc(union uml_pt_regs *regs, void *from)
+{
+       struct sigcontext *sc = from;
+
+       REGS_GS(regs->skas.regs) = sc->gs;
+       REGS_FS(regs->skas.regs) = sc->fs;
+       REGS_ES(regs->skas.regs) = sc->es;
+       REGS_DS(regs->skas.regs) = sc->ds;
+       REGS_EDI(regs->skas.regs) = sc->edi;
+       REGS_ESI(regs->skas.regs) = sc->esi;
+       REGS_EBP(regs->skas.regs) = sc->ebp;
+       REGS_SP(regs->skas.regs) = sc->esp;
+       REGS_EBX(regs->skas.regs) = sc->ebx;
+       REGS_EDX(regs->skas.regs) = sc->edx;
+       REGS_ECX(regs->skas.regs) = sc->ecx;
+       REGS_EAX(regs->skas.regs) = sc->eax;
+       REGS_IP(regs->skas.regs) = sc->eip;
+       REGS_CS(regs->skas.regs) = sc->cs;
+       REGS_EFLAGS(regs->skas.regs) = sc->eflags;
+       REGS_SS(regs->skas.regs) = sc->ss;
+}
+
 static int copy_sc_from_user_skas(struct pt_regs *regs,
                                  struct sigcontext __user *from)
 {
@@ -28,33 +50,18 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
        err = copy_from_user(&sc, from, sizeof(sc));
        err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
        if(err)
-               return(err);
-
-       REGS_GS(regs->regs.skas.regs) = sc.gs;
-       REGS_FS(regs->regs.skas.regs) = sc.fs;
-       REGS_ES(regs->regs.skas.regs) = sc.es;
-       REGS_DS(regs->regs.skas.regs) = sc.ds;
-       REGS_EDI(regs->regs.skas.regs) = sc.edi;
-       REGS_ESI(regs->regs.skas.regs) = sc.esi;
-       REGS_EBP(regs->regs.skas.regs) = sc.ebp;
-       REGS_SP(regs->regs.skas.regs) = sc.esp;
-       REGS_EBX(regs->regs.skas.regs) = sc.ebx;
-       REGS_EDX(regs->regs.skas.regs) = sc.edx;
-       REGS_ECX(regs->regs.skas.regs) = sc.ecx;
-       REGS_EAX(regs->regs.skas.regs) = sc.eax;
-       REGS_IP(regs->regs.skas.regs) = sc.eip;
-       REGS_CS(regs->regs.skas.regs) = sc.cs;
-       REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
-       REGS_SS(regs->regs.skas.regs) = sc.ss;
+               return err;
+
+       copy_sc(&regs->regs, &sc);
 
        err = restore_fp_registers(userspace_pid[0], fpregs);
-       if(err < 0){
+       if(err < 0) {
                printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
-                      "errno = %d\n", err);
-               return(1);
+                      "errno = %d\n", -err);
+               return err;
        }
 
-       return(0);
+       return 0;
 }
 
 int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
@@ -90,16 +97,16 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *t
        if(err < 0){
                printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
                       "errno = %d\n", err);
-               return(1);
+               return 1;
        }
        to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
        sc.fpstate = to_fp;
 
        if(err)
-               return(err);
+               return err;
 
-       return(copy_to_user(to, &sc, sizeof(sc)) ||
-              copy_to_user(to_fp, fpregs, sizeof(fpregs)));
+       return copy_to_user(to, &sc, sizeof(sc)) ||
+              copy_to_user(to_fp, fpregs, sizeof(fpregs));
 }
 #endif
 
@@ -129,7 +136,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
        to->fpstate = to_fp;
        if(to_fp != NULL)
                err |= copy_from_user(to_fp, from_fp, fpsize);
-       return(err);
+       return err;
 }
 
 int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
@@ -164,15 +171,15 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
        ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from,
                                               sizeof(struct _fpstate)),
                          copy_sc_from_user_skas(to, from));
-       return(ret);
+       return ret;
 }
 
 static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
                           struct pt_regs *from, unsigned long sp)
 {
-       return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
+       return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
                                              sizeof(*fp), sp),
-                           copy_sc_to_user_skas(to, fp, from, sp)));
+                           copy_sc_to_user_skas(to, fp, from, sp));
 }
 
 static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
@@ -185,7 +192,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __u
        err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
        err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
        err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
-       return(err);
+       return err;
 }
 
 struct sigframe
@@ -359,7 +366,7 @@ long sys_sigreturn(struct pt_regs regs)
 
        /* Avoid ERESTART handling */
        PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-       return(PT_REGS_SYSCALL_RET(&current->thread.regs));
+       return PT_REGS_SYSCALL_RET(&current->thread.regs);
 
  segfault:
        force_sig(SIGSEGV, current);
@@ -389,20 +396,9 @@ long sys_rt_sigreturn(struct pt_regs regs)
 
        /* Avoid ERESTART handling */
        PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-       return(PT_REGS_SYSCALL_RET(&current->thread.regs));
+       return PT_REGS_SYSCALL_RET(&current->thread.regs);
 
  segfault:
        force_sig(SIGSEGV, current);
        return 0;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 643dab5..fea8e5e 100644 (file)
 #include "skas.h"
 #endif
 
-/* If needed we can detect when it's uninitialized. */
+/*
+ * If needed we can detect when it's uninitialized.
+ *
+ * These are initialized in an initcall and unchanged thereafter.
+ */
 static int host_supports_tls = -1;
-int host_gdt_entry_tls_min = -1;
+int host_gdt_entry_tls_min;
 
 #ifdef CONFIG_MODE_SKAS
 int do_set_thread_area_skas(struct user_desc *info)
@@ -361,7 +365,8 @@ out:
 
 /* XXX: This part is probably common to i386 and x86-64. Don't create a common
  * file for now, do that when implementing x86-64 support.*/
-static int __init __setup_host_supports_tls(void) {
+static int __init __setup_host_supports_tls(void)
+{
        check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
        if (host_supports_tls) {
                printk(KERN_INFO "Host TLS support detected\n");
index 447306b..29118cf 100644 (file)
@@ -1,9 +1,10 @@
 #include <stdio.h>
+#include <stddef.h>
 #include <signal.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
-#include <stddef.h>
-#include <sys/poll.h>
 
 #define DEFINE(sym, val) \
        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -47,7 +48,6 @@ void foo(void)
        OFFSET(HOST_SC_FP_ST, _fpstate, _st);
        OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env);
 
-       DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
        DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct));
        DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct));
 
@@ -73,4 +73,8 @@ void foo(void)
        DEFINE(UM_POLLIN, POLLIN);
        DEFINE(UM_POLLPRI, POLLPRI);
        DEFINE(UM_POLLOUT, POLLOUT);
+
+       DEFINE(UM_PROT_READ, PROT_READ);
+       DEFINE(UM_PROT_WRITE, PROT_WRITE);
+       DEFINE(UM_PROT_EXEC, PROT_EXEC);
 }
index 5d430fc..4bdc15c 100644 (file)
@@ -1,7 +1,6 @@
 #include "asm/ptrace.h"
 #include "asm/sigcontext.h"
 #include "sysdep/ptrace.h"
-#include "user_util.h"
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index fdce7ea..0954788 100644 (file)
@@ -4,12 +4,7 @@
  * Licensed under the GPL
  */
 
-#include "linux/sched.h"
-#include "linux/errno.h"
-#include "asm/system.h"
-#include "asm/pda.h"
 #include "sysdep/ptrace.h"
-#include "os.h"
 
 void arch_init_thread(void)
 {
@@ -21,102 +16,5 @@ void arch_check_bugs(void)
 
 int arch_handle_signal(int sig, union uml_pt_regs *regs)
 {
-       return(0);
+       return 0;
 }
-
-#define MAXTOKEN 64
-
-/* Set during early boot */
-int host_has_cmov = 1;
-int host_has_xmm = 0;
-
-static char token(int fd, char *buf, int len, char stop)
-{
-       int n;
-       char *ptr, *end, c;
-
-       ptr = buf;
-       end = &buf[len];
-       do {
-               n = os_read_file(fd, ptr, sizeof(*ptr));
-               c = *ptr++;
-               if(n != sizeof(*ptr)){
-                       if(n == 0) return(0);
-                       printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
-                       if(n < 0)
-                               return(n);
-                       else
-                               return(-EIO);
-               }
-       } while((c != '\n') && (c != stop) && (ptr < end));
-
-       if(ptr == end){
-               printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
-               return(-1);
-       }
-       *(ptr - 1) = '\0';
-       return(c);
-}
-
-static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
-{
-       int n;
-       char c;
-
-       scratch[len - 1] = '\0';
-       while(1){
-               c = token(fd, scratch, len - 1, ':');
-               if(c <= 0)
-                       return(0);
-               else if(c != ':'){
-                       printk("Failed to find ':' in /proc/cpuinfo\n");
-                       return(0);
-               }
-
-               if(!strncmp(scratch, key, strlen(key)))
-                       return(1);
-
-               do {
-                       n = os_read_file(fd, &c, sizeof(c));
-                       if(n != sizeof(c)){
-                               printk("Failed to find newline in "
-                                      "/proc/cpuinfo, err = %d\n", -n);
-                               return(0);
-                       }
-               } while(c != '\n');
-       }
-       return(0);
-}
-
-int cpu_feature(char *what, char *buf, int len)
-{
-       int fd, ret = 0;
-
-       fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
-       if(fd < 0){
-               printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
-               return(0);
-       }
-
-       if(!find_cpuinfo_line(fd, what, buf, len)){
-               printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
-               goto out_close;
-       }
-
-       token(fd, buf, len, '\n');
-       ret = 1;
-
- out_close:
-       os_close_file(fd);
-       return(ret);
-}
-
-/* Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index cee1513..4636b14 100644 (file)
@@ -4,20 +4,24 @@
  * Licensed under the GPL
  */
 
-#include "user.h"
+#include "sysdep/ptrace.h"
 
-int arch_fixup(unsigned long address, void *sc_ptr)
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
 {
-       /* XXX search_exception_tables() */
+       unsigned long insn;
+       unsigned long fixup;
+};
+
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+int arch_fixup(unsigned long address, union uml_pt_regs *regs)
+{
+       const struct exception_table_entry *fixup;
+
+       fixup = search_exception_tables(address);
+       if(fixup != 0){
+               UPT_IP(regs) = fixup->fixup;
+               return(1);
+       }
        return(0);
 }
-
-/* Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index af2f017..fe8ec04 100644 (file)
 
 #include "skas.h"
 
+void copy_sc(union uml_pt_regs *regs, void *from)
+{
+       struct sigcontext *sc = from;
+
+#define GETREG(regs, regno, sc, regname) \
+       (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname
+
+       GETREG(regs, R8, sc, r8);
+       GETREG(regs, R9, sc, r9);
+       GETREG(regs, R10, sc, r10);
+       GETREG(regs, R11, sc, r11);
+       GETREG(regs, R12, sc, r12);
+       GETREG(regs, R13, sc, r13);
+       GETREG(regs, R14, sc, r14);
+       GETREG(regs, R15, sc, r15);
+       GETREG(regs, RDI, sc, rdi);
+       GETREG(regs, RSI, sc, rsi);
+       GETREG(regs, RBP, sc, rbp);
+       GETREG(regs, RBX, sc, rbx);
+       GETREG(regs, RDX, sc, rdx);
+       GETREG(regs, RAX, sc, rax);
+       GETREG(regs, RCX, sc, rcx);
+       GETREG(regs, RSP, sc, rsp);
+       GETREG(regs, RIP, sc, rip);
+       GETREG(regs, EFLAGS, sc, eflags);
+       GETREG(regs, CS, sc, cs);
+
+#undef GETREG
+}
+
 static int copy_sc_from_user_skas(struct pt_regs *regs,
                                  struct sigcontext __user *from)
 {
@@ -51,7 +81,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
 
 #undef GETREG
 
-       return(err);
+       return err;
 }
 
 int copy_sc_to_user_skas(struct sigcontext __user *to,
index 899cebb..0d5fd76 100644 (file)
@@ -2,6 +2,7 @@
 #include <stddef.h>
 #include <signal.h>
 #include <sys/poll.h>
+#include <sys/mman.h>
 #define __FRAME_OFFSETS
 #include <asm/ptrace.h>
 #include <asm/types.h>
@@ -57,7 +58,6 @@ void foo(void)
        OFFSET(HOST_SC_SS, sigcontext, ss);
 #endif
 
-       DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE);
        DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
        DEFINE(HOST_XFP_SIZE, 0);
        DEFINE_LONGS(HOST_RBX, RBX);
@@ -94,4 +94,8 @@ void foo(void)
        DEFINE(UM_POLLIN, POLLIN);
        DEFINE(UM_POLLPRI, POLLPRI);
        DEFINE(UM_POLLOUT, POLLOUT);
+
+       DEFINE(UM_PROT_READ, PROT_READ);
+       DEFINE(UM_PROT_WRITE, PROT_WRITE);
+       DEFINE(UM_PROT_EXEC, PROT_EXEC);
 }
index 50ccc7f..5f54c12 100644 (file)
@@ -37,6 +37,10 @@ config GENERIC_IRQ_PROBE
        bool
        default y
 
+config GENERIC_TIME
+       bool
+       default y
+
 config TIME_LOW_RES
        bool
        default y
index 486e3a4..f0905b0 100644 (file)
@@ -90,81 +90,6 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-/*
- * This version of gettimeofday has near microsecond resolution.
- */
-void do_gettimeofday (struct timeval *tv)
-{
-#if 0 /* DAVIDM later if possible */
-       extern volatile unsigned long lost_ticks;
-       unsigned long lost;
-#endif
-       unsigned long flags;
-       unsigned long usec, sec;
-       unsigned long seq;
-
-       do {
-               seq = read_seqbegin_irqsave(&xtime_lock, flags);
-
-#if 0
-               usec = mach_gettimeoffset ? mach_gettimeoffset () : 0;
-#else
-               usec = 0;
-#endif
-#if 0 /* DAVIDM later if possible */
-               lost = lost_ticks;
-               if (lost)
-                       usec += lost * (1000000/HZ);
-#endif
-               sec = xtime.tv_sec;
-               usec += xtime.tv_nsec / 1000;
-       } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-       while (usec >= 1000000) {
-               usec -= 1000000;
-               sec++;
-       }
-
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_seqlock_irq (&xtime_lock);
-
-       /* This is revolting. We need to set the xtime.tv_nsec
-        * correctly. However, the value in this location is
-        * is value at the last tick.
-        * Discover what correction gettimeofday
-        * would have done, and then undo it!
-        */
-#if 0
-       tv->tv_nsec -= mach_gettimeoffset() * 1000;
-#endif
-
-       while (tv->tv_nsec < 0) {
-               tv->tv_nsec += NSEC_PER_SEC;
-               tv->tv_sec--;
-       }
-
-       xtime.tv_sec = tv->tv_sec;
-       xtime.tv_nsec = tv->tv_nsec;
-
-       ntp_clear();
-
-       write_sequnlock_irq (&xtime_lock);
-       clock_was_set();
-       return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
 static int timer_dev_id;
 static struct irqaction timer_irqaction = {
        timer_interrupt,
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..13c6c37 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/kexec.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/suspend.h>
+#include <linux/pfn.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -25,7 +27,7 @@
 #include <asm/bootsetup.h>
 #include <asm/sections.h>
 
-struct e820map e820 __initdata;
+struct e820map e820;
 
 /* 
  * PFN of last memory page.
@@ -98,7 +100,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 +114,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.
@@ -255,22 +258,6 @@ void __init e820_reserve_resources(void)
        }
 }
 
-/* Mark pages corresponding to given address range as nosave */
-static void __init
-e820_mark_nosave_range(unsigned long start, unsigned long end)
-{
-       unsigned long pfn, max_pfn;
-
-       if (start >= end)
-               return;
-
-       printk("Nosave address range: %016lx - %016lx\n", start, end);
-       max_pfn = end >> PAGE_SHIFT;
-       for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++)
-               if (pfn_valid(pfn))
-                       SetPageNosave(pfn_to_page(pfn));
-}
-
 /*
  * Find the ranges of physical addresses that do not correspond to
  * e820 RAM areas and mark the corresponding pages as nosave for software
@@ -289,13 +276,13 @@ void __init e820_mark_nosave_regions(void)
                struct e820entry *ei = &e820.map[i];
 
                if (paddr < ei->addr)
-                       e820_mark_nosave_range(paddr,
-                                       round_up(ei->addr, PAGE_SIZE));
+                       register_nosave_region(PFN_DOWN(paddr),
+                                               PFN_UP(ei->addr));
 
                paddr = round_down(ei->addr + ei->size, PAGE_SIZE);
                if (ei->type != E820_RAM)
-                       e820_mark_nosave_range(round_up(ei->addr, PAGE_SIZE),
-                                       paddr);
+                       register_nosave_region(PFN_UP(ei->addr),
+                                               PFN_DOWN(paddr));
 
                if (paddr >= (end_pfn << PAGE_SHIFT))
                        break;
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..c3a5547 100644 (file)
@@ -189,21 +189,21 @@ NORET_TYPE void machine_kexec(struct kimage *image)
        control_page = page_address(image->control_code_page) + PAGE_SIZE;
        memcpy(control_page, relocate_kernel, PAGE_SIZE);
 
-       page_list[PA_CONTROL_PAGE] = __pa(control_page);
+       page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page);
        page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
-       page_list[PA_PGD] = __pa(kexec_pgd);
+       page_list[PA_PGD] = virt_to_phys(&kexec_pgd);
        page_list[VA_PGD] = (unsigned long)kexec_pgd;
-       page_list[PA_PUD_0] = __pa(kexec_pud0);
+       page_list[PA_PUD_0] = virt_to_phys(&kexec_pud0);
        page_list[VA_PUD_0] = (unsigned long)kexec_pud0;
-       page_list[PA_PMD_0] = __pa(kexec_pmd0);
+       page_list[PA_PMD_0] = virt_to_phys(&kexec_pmd0);
        page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
-       page_list[PA_PTE_0] = __pa(kexec_pte0);
+       page_list[PA_PTE_0] = virt_to_phys(&kexec_pte0);
        page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
-       page_list[PA_PUD_1] = __pa(kexec_pud1);
+       page_list[PA_PUD_1] = virt_to_phys(&kexec_pud1);
        page_list[VA_PUD_1] = (unsigned long)kexec_pud1;
-       page_list[PA_PMD_1] = __pa(kexec_pmd1);
+       page_list[PA_PMD_1] = virt_to_phys(&kexec_pmd1);
        page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
-       page_list[PA_PTE_1] = __pa(kexec_pte1);
+       page_list[PA_PTE_1] = virt_to_phys(&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..db51577 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)
@@ -274,8 +276,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 +329,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 +605,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 +984,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..bd1d123 100644 (file)
@@ -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 76bf7c2..f891931 100644 (file)
@@ -93,6 +93,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        unsigned long start_addr;
        unsigned long begin, end;
        
+       if (flags & MAP_FIXED)
+               return addr;
+
        find_start_end(flags, &begin, &end); 
 
        if (len > end)
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..c082268 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,21 +570,23 @@ 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);
+               if (addr >= __START_KERNEL_map)
+                       change_page_attr_addr(addr, 1, __pgprot(0));
                free_page(addr);
                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));
@@ -621,13 +596,23 @@ void free_initmem(void)
 
 void mark_rodata_ro(void)
 {
-       unsigned long addr = (unsigned long)__start_rodata;
+       unsigned long start = (unsigned long)_stext, end;
+
+#ifdef CONFIG_HOTPLUG_CPU
+       /* It must still be possible to apply SMP alternatives. */
+       if (num_possible_cpus() > 1)
+               start = (unsigned long)_etext;
+#endif
+       end = (unsigned long)__end_rodata;
+       start = (start + PAGE_SIZE - 1) & PAGE_MASK;
+       end &= PAGE_MASK;
+       if (end <= start)
+               return;
 
-       for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
-               change_page_attr_addr(addr, 1, PAGE_KERNEL_RO);
+       change_page_attr_addr(start, (end - start) >> 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",
+              (end - start) >> 10);
 
        /*
         * change_page_attr_addr() requires a global_flush_tlb() call after it.
index c6e5e8d..6cac90a 100644 (file)
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/io.h>
+
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 #include <asm/proto.h>
 
+unsigned long __phys_addr(unsigned long x)
+{
+       if (x >= __START_KERNEL_map)
+               return x - __START_KERNEL_map + phys_base;
+       return x - PAGE_OFFSET;
+}
+EXPORT_SYMBOL(__phys_addr);
+
 #define ISA_START_ADDRESS      0xa0000
 #define ISA_END_ADDRESS                0x100000
 
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..d653d0b 100644 (file)
@@ -180,16 +180,24 @@ __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
+       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) {
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 ab05bff..4bfe333 100644 (file)
@@ -251,7 +251,7 @@ static int tuntap_open(struct iss_net_private *lp)
 
        memset(&ifr, 0, sizeof ifr);
        ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
-       strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name - 1);
+       strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name);
 
        if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) {
                printk("Failed to set interface, returned %d "
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 64df3fa..baef5fc 100644 (file)
@@ -2090,13 +2090,11 @@ static void cfq_slab_kill(void)
 
 static int __init cfq_slab_setup(void)
 {
-       cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0,
-                                       NULL, NULL);
+       cfq_pool = KMEM_CACHE(cfq_queue, 0);
        if (!cfq_pool)
                goto fail;
 
-       cfq_ioc_pool = kmem_cache_create("cfq_ioc_pool",
-                       sizeof(struct cfq_io_context), 0, 0, NULL, NULL);
+       cfq_ioc_pool = KMEM_CACHE(cfq_io_context, 0);
        if (!cfq_ioc_pool)
                goto fail;
 
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 e06dbe9..f7e3e8a 100644 (file)
@@ -80,7 +80,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        }
                        /* all seems OK */
                        fsync_bdev(bdevp);
-                       invalidate_bdev(bdevp, 0);
+                       invalidate_bdev(bdevp);
 
                        mutex_lock_nested(&bdev->bd_mutex, 1);
                        delete_partition(disk, part);
@@ -236,7 +236,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
 
                lock_kernel();
                fsync_bdev(bdev);
-               invalidate_bdev(bdev, 0);
+               invalidate_bdev(bdev);
                unlock_kernel();
                return 0;
 
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 2d912b7..dcde9dd 100644 (file)
@@ -60,7 +60,7 @@ acpi_system_write_sleep(struct file *file,
        state = simple_strtoul(str, NULL, 0);
 #ifdef CONFIG_SOFTWARE_SUSPEND
        if (state == 4) {
-               error = software_suspend();
+               error = pm_suspend(PM_SUSPEND_DISK);
                goto Done;
        }
 #endif
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 e9eb738..b39ea3f 100644 (file)
@@ -2,10 +2,10 @@
 
 obj-y                  := core.o sys.o bus.o dd.o \
                           driver.o class.o platform.o \
-                          cpu.o firmware.o init.o map.o dmapool.o \
-                          dma-mapping.o devres.o \
+                          cpu.o firmware.o init.o map.o devres.o \
                           attribute_container.o transport_class.o
 obj-y                  += power/
+obj-$(CONFIG_HAS_DMA)  += dma-mapping.o dmapool.o
 obj-$(CONFIG_ISA)      += isa.o
 obj-$(CONFIG_FW_LOADER)        += firmware_class.o
 obj-$(CONFIG_NUMA)     += node.o
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 5d65621..27a1390 100644 (file)
@@ -1480,7 +1480,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
                break;
        case FDFMTEND:
                floppy_off(drive);
-               invalidate_bdev(inode->i_bdev, 0);
+               invalidate_bdev(inode->i_bdev);
                break;
        case FDGETPRM:
                memset((void *)&getprm, 0, sizeof (getprm));
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 6b5b642..0d4ccd4 100644 (file)
@@ -833,7 +833,7 @@ out_clr:
        lo->lo_backing_file = NULL;
        lo->lo_flags = 0;
        set_capacity(disks[lo->lo_number], 0);
-       invalidate_bdev(bdev, 0);
+       invalidate_bdev(bdev);
        bd_set_size(bdev, 0);
        mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
        lo->lo_state = Lo_unbound;
@@ -917,7 +917,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
        memset(lo->lo_file_name, 0, LO_NAME_SIZE);
-       invalidate_bdev(bdev, 0);
+       invalidate_bdev(bdev);
        set_capacity(disks[lo->lo_number], 0);
        bd_set_size(bdev, 0);
        mapping_set_gfp_mask(filp->f_mapping, gfp);
index 485aa87..43d4ebc 100644 (file)
@@ -403,7 +403,7 @@ static void __exit rd_cleanup(void)
                struct block_device *bdev = rd_bdev[i];
                rd_bdev[i] = NULL;
                if (bdev) {
-                       invalidate_bdev(bdev, 1);
+                       invalidate_bdev(bdev);
                        blkdev_put(bdev);
                }
                del_gendisk(rd_disks[i]);
index 406af57..b0238b4 100644 (file)
@@ -114,10 +114,16 @@ static struct usb_device_id blacklist_ids[] = {
        { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 },
 
+       /* Broadcom BCM2045 */
+       { USB_DEVICE(0x0a5c, 0x2101), .driver_info = HCI_WRONG_SCO_MTU },
+
        /* IBM/Lenovo ThinkPad with Broadcom chip */
        { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_WRONG_SCO_MTU },
 
+       /* Targus ACB10US */
+       { USB_DEVICE(0x0a5c, 0x2100), .driver_info = HCI_RESET },
+
        /* ANYCOM Bluetooth USB-200 and USB-250 */
        { USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
 
index b36f44d..3625a05 100644 (file)
@@ -2384,7 +2384,7 @@ static int cdrom_ioctl_reset(struct cdrom_device_info *cdi,
                return -EACCES;
        if (!CDROM_CAN(CDC_RESET))
                return -ENOSYS;
-       invalidate_bdev(bdev, 0);
+       invalidate_bdev(bdev);
        return cdi->ops->reset(cdi);
 }
 
index d0c978f..a26d917 100644 (file)
@@ -905,8 +905,8 @@ config SONYPI
          To compile this driver as a module, choose M here: the
          module will be called sonypi.
 
-config TANBAC_TB0219
-       tristate "TANBAC TB0219 base board support"
+config GPIO_TB0219
+       tristate "TANBAC TB0219 GPIO support"
        depends on TANBAC_TB022X
        select GPIO_VR41XX
 
index ae8567c..2f56ecc 100644 (file)
@@ -91,7 +91,7 @@ obj-$(CONFIG_PC8736x_GPIO)    += pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)         += nsc_gpio.o
 obj-$(CONFIG_CS5535_GPIO)      += cs5535_gpio.o
 obj-$(CONFIG_GPIO_VR41XX)      += vr41xx_giu.o
-obj-$(CONFIG_TANBAC_TB0219)    += tb0219.o
+obj-$(CONFIG_GPIO_TB0219)      += tb0219.o
 obj-$(CONFIG_TELCLOCK)         += tlclk.o
 
 obj-$(CONFIG_WATCHDOG)         += watchdog/
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 6441e01..af74cd7 100644 (file)
@@ -1,6 +1,6 @@
 ************************************************************
 * For the very latest on DRI development, please see:      *
-*     http://dri.sourceforge.net/                          *
+*     http://dri.freedesktop.org/                          *
 ************************************************************
 
 The Direct Rendering Manager (drm) is a device-independent kernel-level
@@ -26,21 +26,19 @@ ways:
 
 
 Documentation on the DRI is available from:
-    http://precisioninsight.com/piinsights.html
+    http://dri.freedesktop.org/wiki/Documentation
+    http://sourceforge.net/project/showfiles.php?group_id=387
+    http://dri.sourceforge.net/doc/
 
 For specific information about kernel-level support, see:
 
     The Direct Rendering Manager, Kernel Support for the Direct Rendering
     Infrastructure
-    http://precisioninsight.com/dr/drm.html
+    http://dri.sourceforge.net/doc/drm_low_level.html
 
     Hardware Locking for the Direct Rendering Infrastructure
-    http://precisioninsight.com/dr/locking.html
+    http://dri.sourceforge.net/doc/hardware_locking_low_level.html
 
     A Security Analysis of the Direct Rendering Infrastructure
-    http://precisioninsight.com/dr/security.html
+    http://dri.sourceforge.net/doc/security_low_level.html
 
-************************************************************
-* For the very latest on DRI development, please see:      *
-*     http://dri.sourceforge.net/                          *
-************************************************************
index 8db9041..0891984 100644 (file)
@@ -654,11 +654,13 @@ typedef struct drm_set_version {
 
 /**
  * Device specific ioctls should only be in their respective headers
- * The device specific ioctl range is from 0x40 to 0x79.
+ * The device specific ioctl range is from 0x40 to 0x99.
+ * Generic IOCTLS restart at 0xA0.
  *
  * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
  * drmCommandReadWrite().
  */
 #define DRM_COMMAND_BASE                0x40
+#define DRM_COMMAND_END                        0xA0
 
 #endif
index 85d99e2..80041d5 100644 (file)
@@ -414,6 +414,10 @@ typedef struct drm_lock_data {
        struct file *filp;              /**< File descr of lock holder (0=kernel) */
        wait_queue_head_t lock_queue;   /**< Queue of blocked processes */
        unsigned long lock_time;        /**< Time of last lock in jiffies */
+       spinlock_t spinlock;
+       uint32_t kernel_waiters;
+       uint32_t user_waiters;
+       int idle_has_lock;
 } drm_lock_data_t;
 
 /**
@@ -590,6 +594,8 @@ struct drm_driver {
        void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
        void (*reclaim_buffers_locked) (struct drm_device *dev,
                                        struct file *filp);
+       void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
+                                       struct file * filp);
        unsigned long (*get_map_ofs) (drm_map_t * map);
        unsigned long (*get_reg_ofs) (struct drm_device * dev);
        void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
@@ -764,7 +770,7 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,
 }
 
 #ifdef __alpha__
-#define drm_get_pci_domain(dev) dev->hose->bus->number
+#define drm_get_pci_domain(dev) dev->hose->index
 #else
 #define drm_get_pci_domain(dev) 0
 #endif
@@ -915,9 +921,18 @@ extern int drm_lock(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long arg);
 extern int drm_unlock(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg);
-extern int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context);
-extern int drm_lock_free(drm_device_t * dev,
-                        __volatile__ unsigned int *lock, unsigned int context);
+extern int drm_lock_take(drm_lock_data_t *lock_data, unsigned int context);
+extern int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context);
+extern void drm_idlelock_take(drm_lock_data_t *lock_data);
+extern void drm_idlelock_release(drm_lock_data_t *lock_data);
+
+/*
+ * These are exported to drivers so that they can implement fencing using
+ * DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
+ */
+
+extern int drm_i_have_hw_lock(struct file *filp);
+extern int drm_kernel_take_hw_lock(struct file *filp);
 
                                /* Buffer management support (drm_bufs.h) */
 extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
index a6828cc..c113458 100644 (file)
@@ -57,7 +57,8 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
        list_for_each(list, &dev->maplist->head) {
                drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
                if (entry->map && map->type == entry->map->type &&
-                   entry->map->offset == map->offset) {
+                   ((entry->map->offset == map->offset) ||
+                    (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
                        return entry;
                }
        }
@@ -180,8 +181,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
                if (map->type == _DRM_REGISTERS)
                        map->handle = ioremap(map->offset, map->size);
                break;
-
        case _DRM_SHM:
+               list = drm_find_matching_map(dev, map);
+               if (list != NULL) {
+                       if(list->map->size != map->size) {
+                               DRM_DEBUG("Matching maps of type %d with "
+                                         "mismatched sizes, (%ld vs %ld)\n",
+                                         map->type, map->size, list->map->size);
+                               list->map->size = map->size;
+                       }
+
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       *maplist = list;
+                       return 0;
+               }
                map->handle = vmalloc_user(map->size);
                DRM_DEBUG("%lu %d %p\n",
                          map->size, drm_order(map->size), map->handle);
@@ -200,15 +213,45 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
                        dev->sigdata.lock = dev->lock.hw_lock = map->handle;    /* Pointer to lock */
                }
                break;
-       case _DRM_AGP:
-               if (drm_core_has_AGP(dev)) {
+       case _DRM_AGP: {
+               drm_agp_mem_t *entry;
+               int valid = 0;
+
+               if (!drm_core_has_AGP(dev)) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EINVAL;
+               }
 #ifdef __alpha__
-                       map->offset += dev->hose->mem_space->start;
+               map->offset += dev->hose->mem_space->start;
 #endif
-                       map->offset += dev->agp->base;
-                       map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+               /* Note: dev->agp->base may actually be 0 when the DRM
+                * is not in control of AGP space. But if user space is
+                * it should already have added the AGP base itself.
+                */
+               map->offset += dev->agp->base;
+               map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+
+               /* This assumes the DRM is in total control of AGP space.
+                * It's not always the case as AGP can be in the control
+                * of user space (i.e. i810 driver). So this loop will get
+                * skipped and we double check that dev->agp->memory is
+                * actually set as well as being invalid before EPERM'ing
+                */
+               for (entry = dev->agp->memory; entry; entry = entry->next) {
+                       if ((map->offset >= entry->bound) &&
+                           (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
+                               valid = 1;
+                               break;
+                       }
                }
+               if (dev->agp->memory && !valid) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EPERM;
+               }
+               DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size);
+
                break;
+       }
        case _DRM_SCATTER_GATHER:
                if (!dev->sg) {
                        drm_free(map, sizeof(*map), DRM_MEM_MAPS);
@@ -267,7 +310,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
 
        *maplist = list;
        return 0;
-}
+       }
 
 int drm_addmap(drm_device_t * dev, unsigned int offset,
               unsigned int size, drm_map_type_t type,
@@ -519,6 +562,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
 {
        drm_device_dma_t *dma = dev->dma;
        drm_buf_entry_t *entry;
+       drm_agp_mem_t *agp_entry;
        drm_buf_t *buf;
        unsigned long offset;
        unsigned long agp_offset;
@@ -529,7 +573,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
        int page_order;
        int total;
        int byte_count;
-       int i;
+       int i, valid;
        drm_buf_t **temp_buflist;
 
        if (!dma)
@@ -560,6 +604,19 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
        if (dev->queue_count)
                return -EBUSY;  /* Not while in use */
 
+       /* Make sure buffers are located in AGP memory that we own */
+       valid = 0;
+       for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) {
+               if ((agp_offset >= agp_entry->bound) &&
+                   (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
+                       valid = 1;
+                       break;
+               }
+       }
+       if (dev->agp->memory && !valid) {
+               DRM_DEBUG("zone invalid\n");
+               return -EINVAL;
+       }
        spin_lock(&dev->count_lock);
        if (dev->buf_use) {
                spin_unlock(&dev->count_lock);
index f5b9b24..26bec30 100644 (file)
@@ -496,11 +496,14 @@ int drm_ioctl(struct inode *inode, struct file *filp,
                  (long)old_encode_dev(priv->head->device),
                  priv->authenticated);
 
-       if (nr < DRIVER_IOCTL_COUNT)
-               ioctl = &drm_ioctls[nr];
-       else if ((nr >= DRM_COMMAND_BASE)
+       if ((nr >= DRIVER_IOCTL_COUNT) &&
+           ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+               goto err_i1;
+       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
                 && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
                ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+       else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
+               ioctl = &drm_ioctls[nr];
        else
                goto err_i1;
 
index 898f47d..3b159ca 100644 (file)
@@ -46,6 +46,7 @@ static int drm_setup(drm_device_t * dev)
        drm_local_map_t *map;
        int i;
        int ret;
+       u32 sareapage;
 
        if (dev->driver->firstopen) {
                ret = dev->driver->firstopen(dev);
@@ -56,7 +57,8 @@ static int drm_setup(drm_device_t * dev)
        dev->magicfree.next = NULL;
 
        /* prebuild the SAREA */
-       i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
+       sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE);
+       i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
        if (i != 0)
                return i;
 
@@ -84,7 +86,7 @@ static int drm_setup(drm_device_t * dev)
        INIT_LIST_HEAD(&dev->ctxlist->head);
 
        dev->vmalist = NULL;
-       dev->sigdata.lock = dev->lock.hw_lock = NULL;
+       dev->sigdata.lock = NULL;
        init_waitqueue_head(&dev->lock.lock_queue);
        dev->queue_count = 0;
        dev->queue_reserved = 0;
@@ -354,58 +356,56 @@ int drm_release(struct inode *inode, struct file *filp)
                  current->pid, (long)old_encode_dev(priv->head->device),
                  dev->open_count);
 
-       if (priv->lock_count && dev->lock.hw_lock &&
-           _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
-           dev->lock.filp == filp) {
-               DRM_DEBUG("File %p released, freeing lock for context %d\n",
-                         filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-
-               if (dev->driver->reclaim_buffers_locked)
+       if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+               if (drm_i_have_hw_lock(filp)) {
                        dev->driver->reclaim_buffers_locked(dev, filp);
-
-               drm_lock_free(dev, &dev->lock.hw_lock->lock,
-                             _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-
-               /* FIXME: may require heavy-handed reset of
-                  hardware at this point, possibly
-                  processed via a callback to the X
-                  server. */
-       } else if (dev->driver->reclaim_buffers_locked && priv->lock_count
-                  && dev->lock.hw_lock) {
-               /* The lock is required to reclaim buffers */
-               DECLARE_WAITQUEUE(entry, current);
-
-               add_wait_queue(&dev->lock.lock_queue, &entry);
-               for (;;) {
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       if (!dev->lock.hw_lock) {
-                               /* Device has been unregistered */
-                               retcode = -EINTR;
-                               break;
+               } else {
+                       unsigned long _end=jiffies + 3*DRM_HZ;
+                       int locked = 0;
+
+                       drm_idlelock_take(&dev->lock);
+
+                       /*
+                        * Wait for a while.
+                        */
+
+                       do{
+                               spin_lock(&dev->lock.spinlock);
+                               locked = dev->lock.idle_has_lock;
+                               spin_unlock(&dev->lock.spinlock);
+                               if (locked)
+                                       break;
+                               schedule();
+                       } while (!time_after_eq(jiffies, _end));
+
+                       if (!locked) {
+                               DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
+                                         "\tdriver to use reclaim_buffers_idlelocked() instead.\n"
+                                         "\tI will go on reclaiming the buffers anyway.\n");
                        }
-                       if (drm_lock_take(&dev->lock.hw_lock->lock,
-                                         DRM_KERNEL_CONTEXT)) {
-                               dev->lock.filp = filp;
-                               dev->lock.lock_time = jiffies;
-                               atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
-                               break;  /* Got lock */
-                       }
-                       /* Contention */
-                       schedule();
-                       if (signal_pending(current)) {
-                               retcode = -ERESTARTSYS;
-                               break;
-                       }
-               }
-               __set_current_state(TASK_RUNNING);
-               remove_wait_queue(&dev->lock.lock_queue, &entry);
-               if (!retcode) {
+
                        dev->driver->reclaim_buffers_locked(dev, filp);
-                       drm_lock_free(dev, &dev->lock.hw_lock->lock,
-                                     DRM_KERNEL_CONTEXT);
+                       drm_idlelock_release(&dev->lock);
                }
        }
 
+       if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
+
+               drm_idlelock_take(&dev->lock);
+               dev->driver->reclaim_buffers_idlelocked(dev, filp);
+               drm_idlelock_release(&dev->lock);
+
+       }
+
+       if (drm_i_have_hw_lock(filp)) {
+               DRM_DEBUG("File %p released, freeing lock for context %d\n",
+                         filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+               drm_lock_free(&dev->lock,
+                             _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+       }
+
+
        if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
            !dev->driver->reclaim_buffers_locked) {
                dev->driver->reclaim_buffers(dev, filp);
index a0b2d68..31acb62 100644 (file)
@@ -43,7 +43,16 @@ int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
        ht->size = 1 << order;
        ht->order = order;
        ht->fill = 0;
-       ht->table = vmalloc(ht->size*sizeof(*ht->table));
+       ht->table = NULL;
+       ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
+       if (!ht->use_vmalloc) {
+               ht->table = drm_calloc(ht->size, sizeof(*ht->table),
+                                      DRM_MEM_HASHTAB);
+       }
+       if (!ht->table) {
+               ht->use_vmalloc = 1;
+               ht->table = vmalloc(ht->size*sizeof(*ht->table));
+       }
        if (!ht->table) {
                DRM_ERROR("Out of memory for hash table\n");
                return -ENOMEM;
@@ -183,7 +192,11 @@ int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
 void drm_ht_remove(drm_open_hash_t *ht)
 {
        if (ht->table) {
-               vfree(ht->table);
+               if (ht->use_vmalloc)
+                       vfree(ht->table);
+               else
+                       drm_free(ht->table, ht->size * sizeof(*ht->table),
+                                DRM_MEM_HASHTAB);
                ht->table = NULL;
        }
 }
index 40afec0..613091c 100644 (file)
@@ -47,6 +47,7 @@ typedef struct drm_open_hash{
        unsigned int order;
        unsigned int fill;
        struct hlist_head *table;
+       int use_vmalloc;
 } drm_open_hash_t;
 
 
index 9d00c51..2e75331 100644 (file)
@@ -424,7 +424,7 @@ static void drm_locked_tasklet_func(unsigned long data)
        spin_lock_irqsave(&dev->tasklet_lock, irqflags);
 
        if (!dev->locked_tasklet_func ||
-           !drm_lock_take(&dev->lock.hw_lock->lock,
+           !drm_lock_take(&dev->lock,
                           DRM_KERNEL_CONTEXT)) {
                spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
                return;
@@ -435,7 +435,7 @@ static void drm_locked_tasklet_func(unsigned long data)
 
        dev->locked_tasklet_func(dev);
 
-       drm_lock_free(dev, &dev->lock.hw_lock->lock,
+       drm_lock_free(&dev->lock,
                      DRM_KERNEL_CONTEXT);
 
        dev->locked_tasklet_func = NULL;
index e9993ba..befd1af 100644 (file)
@@ -35,9 +35,6 @@
 
 #include "drmP.h"
 
-static int drm_lock_transfer(drm_device_t * dev,
-                            __volatile__ unsigned int *lock,
-                            unsigned int context);
 static int drm_notifier(void *priv);
 
 /**
@@ -80,6 +77,9 @@ int drm_lock(struct inode *inode, struct file *filp,
                        return -EINVAL;
 
        add_wait_queue(&dev->lock.lock_queue, &entry);
+       spin_lock(&dev->lock.spinlock);
+       dev->lock.user_waiters++;
+       spin_unlock(&dev->lock.spinlock);
        for (;;) {
                __set_current_state(TASK_INTERRUPTIBLE);
                if (!dev->lock.hw_lock) {
@@ -87,7 +87,7 @@ int drm_lock(struct inode *inode, struct file *filp,
                        ret = -EINTR;
                        break;
                }
-               if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
+               if (drm_lock_take(&dev->lock, lock.context)) {
                        dev->lock.filp = filp;
                        dev->lock.lock_time = jiffies;
                        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
@@ -101,12 +101,14 @@ int drm_lock(struct inode *inode, struct file *filp,
                        break;
                }
        }
+       spin_lock(&dev->lock.spinlock);
+       dev->lock.user_waiters--;
+       spin_unlock(&dev->lock.spinlock);
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(&dev->lock.lock_queue, &entry);
 
-       DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-       if (ret)
-               return ret;
+       DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
+       if (ret) return ret;
 
        sigemptyset(&dev->sigmask);
        sigaddset(&dev->sigmask, SIGSTOP);
@@ -127,14 +129,12 @@ int drm_lock(struct inode *inode, struct file *filp,
                }
        }
 
-       /* dev->driver->kernel_context_switch isn't used by any of the x86
-        *  drivers but is used by the Sparc driver.
-        */
        if (dev->driver->kernel_context_switch &&
            dev->last_context != lock.context) {
                dev->driver->kernel_context_switch(dev, dev->last_context,
                                                   lock.context);
        }
+
        return 0;
 }
 
@@ -184,12 +184,8 @@ int drm_unlock(struct inode *inode, struct file *filp,
        if (dev->driver->kernel_context_switch_unlock)
                dev->driver->kernel_context_switch_unlock(dev);
        else {
-               drm_lock_transfer(dev, &dev->lock.hw_lock->lock,
-                                 DRM_KERNEL_CONTEXT);
-
-               if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-                                 DRM_KERNEL_CONTEXT)) {
-                       DRM_ERROR("\n");
+               if (drm_lock_free(&dev->lock,lock.context)) {
+                       /* FIXME: Should really bail out here. */
                }
        }
 
@@ -206,18 +202,26 @@ int drm_unlock(struct inode *inode, struct file *filp,
  *
  * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
  */
-int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
+int drm_lock_take(drm_lock_data_t *lock_data,
+                 unsigned int context)
 {
        unsigned int old, new, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
 
+       spin_lock(&lock_data->spinlock);
        do {
                old = *lock;
                if (old & _DRM_LOCK_HELD)
                        new = old | _DRM_LOCK_CONT;
-               else
-                       new = context | _DRM_LOCK_HELD;
+               else {
+                       new = context | _DRM_LOCK_HELD |
+                               ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ?
+                                _DRM_LOCK_CONT : 0);
+               }
                prev = cmpxchg(lock, old, new);
        } while (prev != old);
+       spin_unlock(&lock_data->spinlock);
+
        if (_DRM_LOCKING_CONTEXT(old) == context) {
                if (old & _DRM_LOCK_HELD) {
                        if (context != DRM_KERNEL_CONTEXT) {
@@ -227,7 +231,8 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
                        return 0;
                }
        }
-       if (new == (context | _DRM_LOCK_HELD)) {
+
+       if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) {
                /* Have lock */
                return 1;
        }
@@ -246,13 +251,13 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
  * Resets the lock file pointer.
  * Marks the lock as held by the given context, via the \p cmpxchg instruction.
  */
-static int drm_lock_transfer(drm_device_t * dev,
-                            __volatile__ unsigned int *lock,
+static int drm_lock_transfer(drm_lock_data_t *lock_data,
                             unsigned int context)
 {
        unsigned int old, new, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
 
-       dev->lock.filp = NULL;
+       lock_data->filp = NULL;
        do {
                old = *lock;
                new = context | _DRM_LOCK_HELD;
@@ -272,23 +277,32 @@ static int drm_lock_transfer(drm_device_t * dev,
  * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
  * waiting on the lock queue.
  */
-int drm_lock_free(drm_device_t * dev,
-                 __volatile__ unsigned int *lock, unsigned int context)
+int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
 {
        unsigned int old, new, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+       spin_lock(&lock_data->spinlock);
+       if (lock_data->kernel_waiters != 0) {
+               drm_lock_transfer(lock_data, 0);
+               lock_data->idle_has_lock = 1;
+               spin_unlock(&lock_data->spinlock);
+               return 1;
+       }
+       spin_unlock(&lock_data->spinlock);
 
-       dev->lock.filp = NULL;
        do {
                old = *lock;
-               new = 0;
+               new = _DRM_LOCKING_CONTEXT(old);
                prev = cmpxchg(lock, old, new);
        } while (prev != old);
+
        if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
                DRM_ERROR("%d freed heavyweight lock held by %d\n",
                          context, _DRM_LOCKING_CONTEXT(old));
                return 1;
        }
-       wake_up_interruptible(&dev->lock.lock_queue);
+       wake_up_interruptible(&lock_data->lock_queue);
        return 0;
 }
 
@@ -322,3 +336,67 @@ static int drm_notifier(void *priv)
        } while (prev != old);
        return 0;
 }
+
+/**
+ * This function returns immediately and takes the hw lock
+ * with the kernel context if it is free, otherwise it gets the highest priority when and if
+ * it is eventually released.
+ *
+ * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held
+ * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause
+ * a deadlock, which is why the "idlelock" was invented).
+ *
+ * This should be sufficient to wait for GPU idle without
+ * having to worry about starvation.
+ */
+
+void drm_idlelock_take(drm_lock_data_t *lock_data)
+{
+       int ret = 0;
+
+       spin_lock(&lock_data->spinlock);
+       lock_data->kernel_waiters++;
+       if (!lock_data->idle_has_lock) {
+
+               spin_unlock(&lock_data->spinlock);
+               ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
+               spin_lock(&lock_data->spinlock);
+
+               if (ret == 1)
+                       lock_data->idle_has_lock = 1;
+       }
+       spin_unlock(&lock_data->spinlock);
+}
+EXPORT_SYMBOL(drm_idlelock_take);
+
+void drm_idlelock_release(drm_lock_data_t *lock_data)
+{
+       unsigned int old, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+       spin_lock(&lock_data->spinlock);
+       if (--lock_data->kernel_waiters == 0) {
+               if (lock_data->idle_has_lock) {
+                       do {
+                               old = *lock;
+                               prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT);
+                       } while (prev != old);
+                       wake_up_interruptible(&lock_data->lock_queue);
+                       lock_data->idle_has_lock = 0;
+               }
+       }
+       spin_unlock(&lock_data->spinlock);
+}
+EXPORT_SYMBOL(drm_idlelock_release);
+
+
+int drm_i_have_hw_lock(struct file *filp)
+{
+       DRM_DEVICE;
+
+       return (priv->lock_count && dev->lock.hw_lock &&
+               _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
+               dev->lock.filp == filp);
+}
+
+EXPORT_SYMBOL(drm_i_have_hw_lock);
index 9b46b85..2ec1d9f 100644 (file)
@@ -274,7 +274,6 @@ int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
        return drm_mm_create_tail_node(mm, start, size);
 }
 
-EXPORT_SYMBOL(drm_mm_init);
 
 void drm_mm_takedown(drm_mm_t * mm)
 {
@@ -295,4 +294,3 @@ void drm_mm_takedown(drm_mm_t * mm)
        drm_free(entry, sizeof(*entry), DRM_MEM_MM);
 }
 
-EXPORT_SYMBOL(drm_mm_takedown);
index ad54b84..01cf482 100644 (file)
        {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \
+       {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
        {0, 0, 0}
 
 #define i810_PCI_IDS \
        {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
index 7fd0da7..b204498 100644 (file)
@@ -72,7 +72,7 @@ static struct drm_proc_list {
 #endif
 };
 
-#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
+#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
 
 /**
  * Initialize the DRI proc filesystem for a device.
index 120d102..19408ad 100644 (file)
@@ -62,6 +62,7 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
        spin_lock_init(&dev->count_lock);
        spin_lock_init(&dev->drw_lock);
        spin_lock_init(&dev->tasklet_lock);
+       spin_lock_init(&dev->lock.spinlock);
        init_timer(&dev->timer);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
index 54a6328..35540cf 100644 (file)
 static void drm_vm_open(struct vm_area_struct *vma);
 static void drm_vm_close(struct vm_area_struct *vma);
 
+static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
+{
+       pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
+
+#if defined(__i386__) || defined(__x86_64__)
+       if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
+               pgprot_val(tmp) |= _PAGE_PCD;
+               pgprot_val(tmp) &= ~_PAGE_PWT;
+       }
+#elif defined(__powerpc__)
+       pgprot_val(tmp) |= _PAGE_NO_CACHE;
+       if (map_type == _DRM_REGISTERS)
+               pgprot_val(tmp) |= _PAGE_GUARDED;
+#endif
+#if defined(__ia64__)
+       if (efi_range_is_wc(vma->vm_start, vma->vm_end -
+                                   vma->vm_start))
+               tmp = pgprot_writecombine(tmp);
+       else
+               tmp = pgprot_noncached(tmp);
+#endif
+       return tmp;
+}
+
 /**
  * \c nopage method for AGP virtual memory.
  *
@@ -151,8 +175,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
 
        offset = address - vma->vm_start;
        i = (unsigned long)map->handle + offset;
-       page = (map->type == _DRM_CONSISTENT) ?
-               virt_to_page((void *)i) : vmalloc_to_page((void *)i);
+       page = vmalloc_to_page((void *)i);
        if (!page)
                return NOPAGE_SIGBUS;
        get_page(page);
@@ -389,7 +412,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
  * Create a new drm_vma_entry structure as the \p vma private data entry and
  * add it to drm_device::vmalist.
  */
-static void drm_vm_open(struct vm_area_struct *vma)
+static void drm_vm_open_locked(struct vm_area_struct *vma)
 {
        drm_file_t *priv = vma->vm_file->private_data;
        drm_device_t *dev = priv->head->dev;
@@ -401,15 +424,23 @@ static void drm_vm_open(struct vm_area_struct *vma)
 
        vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
        if (vma_entry) {
-               mutex_lock(&dev->struct_mutex);
                vma_entry->vma = vma;
                vma_entry->next = dev->vmalist;
                vma_entry->pid = current->pid;
                dev->vmalist = vma_entry;
-               mutex_unlock(&dev->struct_mutex);
        }
 }
 
+static void drm_vm_open(struct vm_area_struct *vma)
+{
+       drm_file_t *priv = vma->vm_file->private_data;
+       drm_device_t *dev = priv->head->dev;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_vm_open_locked(vma);
+       mutex_unlock(&dev->struct_mutex);
+}
+
 /**
  * \c close method for all virtual memory types.
  *
@@ -460,7 +491,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        drm_device_dma_t *dma;
        unsigned long length = vma->vm_end - vma->vm_start;
 
-       lock_kernel();
        dev = priv->head->dev;
        dma = dev->dma;
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
@@ -468,10 +498,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 
        /* Length must match exact page count */
        if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
-               unlock_kernel();
                return -EINVAL;
        }
-       unlock_kernel();
 
        if (!capable(CAP_SYS_ADMIN) &&
            (dma->flags & _DRM_DMA_USE_PCI_RO)) {
@@ -494,7 +522,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        vma->vm_flags |= VM_RESERVED;   /* Don't swap */
 
        vma->vm_file = filp;    /* Needed for drm_vm_open() */
-       drm_vm_open(vma);
+       drm_vm_open_locked(vma);
        return 0;
 }
 
@@ -529,7 +557,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
  * according to the mapping type and remaps the pages. Finally sets the file
  * pointer and calls vm_open().
  */
-int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->head->dev;
@@ -565,7 +593,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                return -EPERM;
 
        /* Check for valid size. */
-       if (map->size != vma->vm_end - vma->vm_start)
+       if (map->size < vma->vm_end - vma->vm_start)
                return -EINVAL;
 
        if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
@@ -600,37 +628,16 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                /* fall through to _DRM_FRAME_BUFFER... */
        case _DRM_FRAME_BUFFER:
        case _DRM_REGISTERS:
-#if defined(__i386__) || defined(__x86_64__)
-               if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
-                       pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-                       pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
-               }
-#elif defined(__powerpc__)
-               pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-               if (map->type == _DRM_REGISTERS)
-                       pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED;
-#endif
-               vma->vm_flags |= VM_IO; /* not in core dump */
-#if defined(__ia64__)
-               if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
-                       vma->vm_page_prot =
-                           pgprot_writecombine(vma->vm_page_prot);
-               else
-                       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#endif
                offset = dev->driver->get_reg_ofs(dev);
+               vma->vm_flags |= VM_IO; /* not in core dump */
+               vma->vm_page_prot = drm_io_prot(map->type, vma);
 #ifdef __sparc__
                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
                if (io_remap_pfn_range(vma, vma->vm_start,
                                       (map->offset + offset) >> PAGE_SHIFT,
                                       vma->vm_end - vma->vm_start,
                                       vma->vm_page_prot))
-#else
-               if (io_remap_pfn_range(vma, vma->vm_start,
-                                      (map->offset + offset) >> PAGE_SHIFT,
-                                      vma->vm_end - vma->vm_start,
-                                      vma->vm_page_prot))
-#endif
                        return -EAGAIN;
                DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
                          " offset = 0x%lx\n",
@@ -638,10 +645,15 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                          vma->vm_start, vma->vm_end, map->offset + offset);
                vma->vm_ops = &drm_vm_ops;
                break;
-       case _DRM_SHM:
        case _DRM_CONSISTENT:
-               /* Consistent memory is really like shared memory. It's only
-                * allocate in a different way */
+               /* Consistent memory is really like shared memory. But
+                * it's allocated in a different way, so avoid nopage */
+               if (remap_pfn_range(vma, vma->vm_start,
+                   page_to_pfn(virt_to_page(map->handle)),
+                   vma->vm_end - vma->vm_start, vma->vm_page_prot))
+                       return -EAGAIN;
+       /* fall through to _DRM_SHM */
+       case _DRM_SHM:
                vma->vm_ops = &drm_vm_shm_ops;
                vma->vm_private_data = (void *)map;
                /* Don't let this area swap.  Change when
@@ -659,8 +671,20 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
        vma->vm_flags |= VM_RESERVED;   /* Don't swap */
 
        vma->vm_file = filp;    /* Needed for drm_vm_open() */
-       drm_vm_open(vma);
+       drm_vm_open_locked(vma);
        return 0;
 }
 
+int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_mmap_locked(filp, vma);
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
 EXPORT_SYMBOL(drm_mmap);
index 9354ce3..1ba15d9 100644 (file)
@@ -34,7 +34,8 @@
 #define IS_I965G(dev) (dev->pci_device == 0x2972 || \
                       dev->pci_device == 0x2982 || \
                       dev->pci_device == 0x2992 || \
-                      dev->pci_device == 0x29A2)
+                      dev->pci_device == 0x29A2 || \
+                      dev->pci_device == 0x2A02)
 
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
index 5ed9656..c1850ec 100644 (file)
@@ -1560,8 +1560,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                if (dev_priv->flags & RADEON_IS_AGP) {
                        base = dev->agp->base;
                        /* Check if valid */
-                       if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
-                           base < (dev_priv->fb_location + dev_priv->fb_size)) {
+                       if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
+                           base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
                                DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
                                         dev->agp->base);
                                base = 0;
@@ -1571,8 +1571,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
                if (base == 0) {
                        base = dev_priv->fb_location + dev_priv->fb_size;
-                       if (((base + dev_priv->gart_size) & 0xfffffffful)
-                           < base)
+                       if (base < dev_priv->fb_location ||
+                           ((base + dev_priv->gart_size) & 0xfffffffful) < base)
                                base = dev_priv->fb_location
                                        - dev_priv->gart_size;
                }               
index 3d5b321..690e0af 100644 (file)
@@ -71,7 +71,7 @@ static struct drm_driver driver = {
        .context_dtor = NULL,
        .dma_quiescent = sis_idle,
        .reclaim_buffers = NULL,
-       .reclaim_buffers_locked = sis_reclaim_buffers_locked,
+       .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked,
        .lastclose = sis_lastclose,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
index bb9dde8..2d4957a 100644 (file)
@@ -52,7 +52,8 @@ static struct drm_driver driver = {
        .dma_quiescent = via_driver_dma_quiescent,
        .dri_library_name = dri_library_name,
        .reclaim_buffers = drm_core_reclaim_buffers,
-       .reclaim_buffers_locked = via_reclaim_buffers_locked,
+       .reclaim_buffers_locked = NULL,
+       .reclaim_buffers_idlelocked = via_reclaim_buffers_locked,
        .lastclose = via_lastclose,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
diff --git a/drivers/char/drm/via_mm.h b/drivers/char/drm/via_mm.h
deleted file mode 100644 (file)
index d57efda..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef _via_drm_mm_h_
-#define _via_drm_mm_h_
-
-typedef struct {
-       unsigned int context;
-       unsigned int size;
-       unsigned long offset;
-       unsigned long free;
-} drm_via_mm_t;
-
-typedef struct {
-       unsigned int size;
-       unsigned long handle;
-       void *virtual;
-} drm_via_dma_t;
-
-#endif
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 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 7a32df5..389da36 100644 (file)
@@ -3720,11 +3720,10 @@ int tty_register_driver(struct tty_driver *driver)
        if (driver->flags & TTY_DRIVER_INSTALLED)
                return 0;
 
-       if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
-               p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+       if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
+               p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
                if (!p)
                        return -ENOMEM;
-               memset(p, 0, driver->num * 3 * sizeof(void *));
        }
 
        if (!driver->major) {
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.
index 214fbb1..7ed92dc 100644 (file)
@@ -351,8 +351,10 @@ static void tps65010_interrupt(struct tps65010 *tps)
 #if 0
                        /* REVISIT:  this might need its own workqueue
                         * plus tweaks including deadlock avoidance ...
+                        * also needs to get error handling and probably
+                        * an #ifdef CONFIG_SOFTWARE_SUSPEND
                         */
-                       software_suspend();
+                       pm_suspend(PM_SUSPEND_DISK);
 #endif
                        poll = 1;
                }
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 1d796e7..a06bcc6 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "core_priv.h"
 
+#define PFX "fmr_pool: "
+
 enum {
        IB_FMR_MAX_REMAPS = 32,
 
@@ -150,7 +152,7 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
 
 #ifdef DEBUG
                if (fmr->ref_count !=0) {
-                       printk(KERN_WARNING "Unmapping FMR 0x%08x with ref count %d",
+                       printk(KERN_WARNING PFX "Unmapping FMR 0x%08x with ref count %d",
                               fmr, fmr->ref_count);
                }
 #endif
@@ -168,7 +170,7 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
 
        ret = ib_unmap_fmr(&fmr_list);
        if (ret)
-               printk(KERN_WARNING "ib_unmap_fmr returned %d", ret);
+               printk(KERN_WARNING PFX "ib_unmap_fmr returned %d", ret);
 
        spin_lock_irq(&pool->pool_lock);
        list_splice(&unmap_list, &pool->free_list);
@@ -226,20 +228,20 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
        device = pd->device;
        if (!device->alloc_fmr    || !device->dealloc_fmr  ||
            !device->map_phys_fmr || !device->unmap_fmr) {
-               printk(KERN_WARNING "Device %s does not support fast memory regions",
+               printk(KERN_INFO PFX "Device %s does not support FMRs\n",
                       device->name);
                return ERR_PTR(-ENOSYS);
        }
 
        attr = kmalloc(sizeof *attr, GFP_KERNEL);
        if (!attr) {
-               printk(KERN_WARNING "couldn't allocate device attr struct");
+               printk(KERN_WARNING PFX "couldn't allocate device attr struct");
                return ERR_PTR(-ENOMEM);
        }
 
        ret = ib_query_device(device, attr);
        if (ret) {
-               printk(KERN_WARNING "couldn't query device");
+               printk(KERN_WARNING PFX "couldn't query device: %d", ret);
                kfree(attr);
                return ERR_PTR(ret);
        }
@@ -253,7 +255,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
 
        pool = kmalloc(sizeof *pool, GFP_KERNEL);
        if (!pool) {
-               printk(KERN_WARNING "couldn't allocate pool struct");
+               printk(KERN_WARNING PFX "couldn't allocate pool struct");
                return ERR_PTR(-ENOMEM);
        }
 
@@ -270,7 +272,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
                        kmalloc(IB_FMR_HASH_SIZE * sizeof *pool->cache_bucket,
                                GFP_KERNEL);
                if (!pool->cache_bucket) {
-                       printk(KERN_WARNING "Failed to allocate cache in pool");
+                       printk(KERN_WARNING PFX "Failed to allocate cache in pool");
                        ret = -ENOMEM;
                        goto out_free_pool;
                }
@@ -294,7 +296,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
                                      "ib_fmr(%s)",
                                      device->name);
        if (IS_ERR(pool->thread)) {
-               printk(KERN_WARNING "couldn't start cleanup thread");
+               printk(KERN_WARNING PFX "couldn't start cleanup thread");
                ret = PTR_ERR(pool->thread);
                goto out_free_pool;
        }
@@ -311,8 +313,8 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
                        fmr = kmalloc(sizeof *fmr + params->max_pages_per_fmr * sizeof (u64),
                                      GFP_KERNEL);
                        if (!fmr) {
-                               printk(KERN_WARNING "failed to allocate fmr struct "
-                                      "for FMR %d", i);
+                               printk(KERN_WARNING PFX "failed to allocate fmr "
+                                      "struct for FMR %d", i);
                                goto out_fail;
                        }
 
@@ -323,7 +325,8 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
 
                        fmr->fmr = ib_alloc_fmr(pd, params->access, &fmr_attr);
                        if (IS_ERR(fmr->fmr)) {
-                               printk(KERN_WARNING "fmr_create failed for FMR %d", i);
+                               printk(KERN_WARNING PFX "fmr_create failed "
+                                      "for FMR %d", i);
                                kfree(fmr);
                                goto out_fail;
                        }
@@ -378,7 +381,7 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
        }
 
        if (i < pool->pool_size)
-               printk(KERN_WARNING "pool still has %d regions registered",
+               printk(KERN_WARNING PFX "pool still has %d regions registered",
                       pool->pool_size - i);
 
        kfree(pool->cache_bucket);
@@ -463,8 +466,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle,
                list_add(&fmr->list, &pool->free_list);
                spin_unlock_irqrestore(&pool->pool_lock, flags);
 
-               printk(KERN_WARNING "fmr_map returns %d\n",
-                      result);
+               printk(KERN_WARNING PFX "fmr_map returns %d\n", result);
 
                return ERR_PTR(result);
        }
@@ -516,7 +518,7 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr)
 
 #ifdef DEBUG
        if (fmr->ref_count < 0)
-               printk(KERN_WARNING "FMR %p has ref count %d < 0",
+               printk(KERN_WARNING PFX "FMR %p has ref count %d < 0",
                       fmr, fmr->ref_count);
 #endif
 
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 6edfecf..85ccf13 100644 (file)
@@ -2771,7 +2771,7 @@ static int ib_mad_port_open(struct ib_device *device,
        cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
        port_priv->cq = ib_create_cq(port_priv->device,
                                     ib_mad_thread_completion_handler,
-                                    NULL, port_priv, cq_size);
+                                    NULL, port_priv, cq_size, 0);
        if (IS_ERR(port_priv->cq)) {
                printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
                ret = PTR_ERR(port_priv->cq);
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 4fd75af..bab6676 100644 (file)
@@ -802,6 +802,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        INIT_LIST_HEAD(&obj->async_list);
 
        cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
+                                            cmd.comp_vector,
                                             file->ucontext, &udata);
        if (IS_ERR(cq)) {
                ret = PTR_ERR(cq);
index f8bc822..d44e547 100644 (file)
@@ -752,7 +752,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
        spin_unlock(&map_lock);
 
        uverbs_dev->ib_dev           = device;
-       uverbs_dev->num_comp_vectors = 1;
+       uverbs_dev->num_comp_vectors = device->num_comp_vectors;
 
        uverbs_dev->dev = cdev_alloc();
        if (!uverbs_dev->dev)
index ccdf93d..86ed8af 100644 (file)
@@ -609,11 +609,11 @@ EXPORT_SYMBOL(ib_destroy_qp);
 struct ib_cq *ib_create_cq(struct ib_device *device,
                           ib_comp_handler comp_handler,
                           void (*event_handler)(struct ib_event *, void *),
-                          void *cq_context, int cqe)
+                          void *cq_context, int cqe, int comp_vector)
 {
        struct ib_cq *cq;
 
-       cq = device->create_cq(device, cqe, NULL, NULL);
+       cq = device->create_cq(device, cqe, comp_vector, NULL, NULL);
 
        if (!IS_ERR(cq)) {
                cq->device        = device;
index 04a9db5..fa58200 100644 (file)
@@ -519,7 +519,7 @@ extern void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq);
 extern void c2_cq_event(struct c2_dev *c2dev, u32 mq_index);
 extern void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index);
 extern int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
-extern int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify);
+extern int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
 
 /* CM */
 extern int c2_llp_connect(struct iw_cm_id *cm_id,
index 5175c99..d2b3366 100644 (file)
@@ -217,17 +217,19 @@ int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
        return npolled;
 }
 
-int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags)
 {
        struct c2_mq_shared __iomem *shared;
        struct c2_cq *cq;
+       unsigned long flags;
+       int ret = 0;
 
        cq = to_c2cq(ibcq);
        shared = cq->mq.peer;
 
-       if (notify == IB_CQ_NEXT_COMP)
+       if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_NEXT_COMP)
                writeb(C2_CQ_NOTIFICATION_TYPE_NEXT, &shared->notification_type);
-       else if (notify == IB_CQ_SOLICITED)
+       else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
                writeb(C2_CQ_NOTIFICATION_TYPE_NEXT_SE, &shared->notification_type);
        else
                return -EINVAL;
@@ -241,7 +243,13 @@ int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
         */
        readb(&shared->armed);
 
-       return 0;
+       if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
+               spin_lock_irqsave(&cq->lock, flags);
+               ret = !c2_mq_empty(&cq->mq);
+               spin_unlock_irqrestore(&cq->lock, flags);
+       }
+
+       return ret;
 }
 
 static void c2_free_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq)
index 607c09b..1091662 100644 (file)
@@ -290,7 +290,7 @@ static int c2_destroy_qp(struct ib_qp *ib_qp)
        return 0;
 }
 
-static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries,
+static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int vector,
                                  struct ib_ucontext *context,
                                  struct ib_udata *udata)
 {
@@ -795,6 +795,7 @@ int c2_register_device(struct c2_dev *dev)
        memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
        memcpy(&dev->ibdev.node_guid, dev->pseudo_netdev->dev_addr, 6);
        dev->ibdev.phys_port_cnt = 1;
+       dev->ibdev.num_comp_vectors = 1;
        dev->ibdev.dma_device = &dev->pcidev->dev;
        dev->ibdev.query_device = c2_query_device;
        dev->ibdev.query_port = c2_query_port;
index f5e9aee..76049af 100644 (file)
@@ -114,7 +114,10 @@ int cxio_hal_cq_op(struct cxio_rdev *rdev_p, struct t3_cq *cq,
                                return -EIO;
                        }
                }
+
+               return 1;
        }
+
        return 0;
 }
 
index 90d7b89..ff7290e 100644 (file)
@@ -38,6 +38,7 @@
 #include "firmware_exports.h"
 
 #define T3_MAX_SGE      4
+#define T3_MAX_INLINE  64
 
 #define Q_EMPTY(rptr,wptr) ((rptr)==(wptr))
 #define Q_FULL(rptr,wptr,size_log2)  ( (((wptr)-(rptr))>>(size_log2)) && \
index 3b4b0ac..b2faff5 100644 (file)
@@ -1109,6 +1109,15 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 
        PDBG("%s ep %p\n", __FUNCTION__, ep);
 
+       /*
+        * We get 2 abort replies from the HW.  The first one must
+        * be ignored except for scribbling that we need one more.
+        */
+       if (!(ep->flags & ABORT_REQ_IN_PROGRESS)) {
+               ep->flags |= ABORT_REQ_IN_PROGRESS;
+               return CPL_RET_BUF_DONE;
+       }
+
        close_complete_upcall(ep);
        state_set(&ep->com, DEAD);
        release_ep_resources(ep);
@@ -1189,6 +1198,7 @@ static int listen_stop(struct iwch_listen_ep *ep)
        }
        req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+       req->cpu_idx = 0;
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, ep->stid));
        skb->priority = 1;
        ep->com.tdev->send(ep->com.tdev, skb);
@@ -1475,6 +1485,15 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        int ret;
        int state;
 
+       /*
+        * We get 2 peer aborts from the HW.  The first one must
+        * be ignored except for scribbling that we need one more.
+        */
+       if (!(ep->flags & PEER_ABORT_IN_PROGRESS)) {
+               ep->flags |= PEER_ABORT_IN_PROGRESS;
+               return CPL_RET_BUF_DONE;
+       }
+
        if (is_neg_adv_abort(req->status)) {
                PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
                     ep->hwtid);
index 0c6f281..21a388c 100644 (file)
@@ -143,6 +143,11 @@ enum iwch_ep_state {
        DEAD,
 };
 
+enum iwch_ep_flags {
+       PEER_ABORT_IN_PROGRESS  = (1 << 0),
+       ABORT_REQ_IN_PROGRESS   = (1 << 1),
+};
+
 struct iwch_ep_common {
        struct iw_cm_id *cm_id;
        struct iwch_qp *qp;
@@ -181,6 +186,7 @@ struct iwch_ep {
        u16 plen;
        u32 ird;
        u32 ord;
+       u32 flags;
 };
 
 static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id)
index af28a31..a891493 100644 (file)
@@ -139,7 +139,7 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq)
        return 0;
 }
 
-static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries,
+static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int vector,
                             struct ib_ucontext *ib_context,
                             struct ib_udata *udata)
 {
@@ -292,7 +292,7 @@ static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
 #endif
 }
 
-static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
 {
        struct iwch_dev *rhp;
        struct iwch_cq *chp;
@@ -303,7 +303,7 @@ static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
 
        chp = to_iwch_cq(ibcq);
        rhp = chp->rhp;
-       if (notify == IB_CQ_SOLICITED)
+       if ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
                cq_op = CQ_ARM_SE;
        else
                cq_op = CQ_ARM_AN;
@@ -317,9 +317,11 @@ static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
        PDBG("%s rptr 0x%x\n", __FUNCTION__, chp->cq.rptr);
        err = cxio_hal_cq_op(&rhp->rdev, &chp->cq, cq_op, 0);
        spin_unlock_irqrestore(&chp->lock, flag);
-       if (err)
+       if (err < 0)
                printk(KERN_ERR MOD "Error %d rearming CQID 0x%x\n", err,
                       chp->cq.cqid);
+       if (err > 0 && !(flags & IB_CQ_REPORT_MISSED_EVENTS))
+               err = 0;
        return err;
 }
 
@@ -780,6 +782,9 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
        if (rqsize > T3_MAX_RQ_SIZE)
                return ERR_PTR(-EINVAL);
 
+       if (attrs->cap.max_inline_data > T3_MAX_INLINE)
+               return ERR_PTR(-EINVAL);
+
        /*
         * NOTE: The SQ and total WQ sizes don't need to be
         * a power of two.  However, all the code assumes
@@ -1107,6 +1112,7 @@ int iwch_register_device(struct iwch_dev *dev)
        dev->ibdev.node_type = RDMA_NODE_RNIC;
        memcpy(dev->ibdev.node_desc, IWCH_NODE_DESC, sizeof(IWCH_NODE_DESC));
        dev->ibdev.phys_port_cnt = dev->rdev.port_info.nports;
+       dev->ibdev.num_comp_vectors = 1;
        dev->ibdev.dma_device = &(dev->rdev.rnic_info.pdev->dev);
        dev->ibdev.query_device = iwch_query_device;
        dev->ibdev.query_port = iwch_query_port;
index 0a472c9..714dddb 100644 (file)
@@ -471,43 +471,62 @@ int iwch_bind_mw(struct ib_qp *qp,
        return err;
 }
 
-static void build_term_codes(int t3err, u8 *layer_type, u8 *ecode, int tagged)
+static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
+                                   u8 *layer_type, u8 *ecode)
 {
-       switch (t3err) {
+       int status = TPT_ERR_INTERNAL_ERR;
+       int tagged = 0;
+       int opcode = -1;
+       int rqtype = 0;
+       int send_inv = 0;
+
+       if (rsp_msg) {
+               status = CQE_STATUS(rsp_msg->cqe);
+               opcode = CQE_OPCODE(rsp_msg->cqe);
+               rqtype = RQ_TYPE(rsp_msg->cqe);
+               send_inv = (opcode == T3_SEND_WITH_INV) ||
+                          (opcode == T3_SEND_WITH_SE_INV);
+               tagged = (opcode == T3_RDMA_WRITE) ||
+                        (rqtype && (opcode == T3_READ_RESP));
+       }
+
+       switch (status) {
        case TPT_ERR_STAG:
-               if (tagged == 1) {
-                       *layer_type = LAYER_DDP|DDP_TAGGED_ERR;
-                       *ecode = DDPT_INV_STAG;
-               } else if (tagged == 2) {
+               if (send_inv) {
+                       *layer_type = LAYER_RDMAP|RDMAP_REMOTE_OP;
+                       *ecode = RDMAP_CANT_INV_STAG;
+               } else {
                        *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
                        *ecode = RDMAP_INV_STAG;
                }
                break;
        case TPT_ERR_PDID:
+               *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+               if ((opcode == T3_SEND_WITH_INV) ||
+                   (opcode == T3_SEND_WITH_SE_INV))
+                       *ecode = RDMAP_CANT_INV_STAG;
+               else
+                       *ecode = RDMAP_STAG_NOT_ASSOC;
+               break;
        case TPT_ERR_QPID:
+               *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+               *ecode = RDMAP_STAG_NOT_ASSOC;
+               break;
        case TPT_ERR_ACCESS:
-               if (tagged == 1) {
-                       *layer_type = LAYER_DDP|DDP_TAGGED_ERR;
-                       *ecode = DDPT_STAG_NOT_ASSOC;
-               } else if (tagged == 2) {
-                       *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
-                       *ecode = RDMAP_STAG_NOT_ASSOC;
-               }
+               *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+               *ecode = RDMAP_ACC_VIOL;
                break;
        case TPT_ERR_WRAP:
                *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
                *ecode = RDMAP_TO_WRAP;
                break;
        case TPT_ERR_BOUND:
-               if (tagged == 1) {
+               if (tagged) {
                        *layer_type = LAYER_DDP|DDP_TAGGED_ERR;
                        *ecode = DDPT_BASE_BOUNDS;
-               } else if (tagged == 2) {
+               } else {
                        *layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
                        *ecode = RDMAP_BASE_BOUNDS;
-               } else {
-                       *layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
-                       *ecode = DDPU_MSG_TOOBIG;
                }
                break;
        case TPT_ERR_INVALIDATE_SHARED_MR:
@@ -591,8 +610,6 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
 {
        union t3_wr *wqe;
        struct terminate_message *term;
-       int status;
-       int tagged = 0;
        struct sk_buff *skb;
 
        PDBG("%s %d\n", __FUNCTION__, __LINE__);
@@ -610,17 +627,7 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
 
        /* immediate data starts here. */
        term = (struct terminate_message *)wqe->send.sgl;
-       if (rsp_msg) {
-               status = CQE_STATUS(rsp_msg->cqe);
-               if (CQE_OPCODE(rsp_msg->cqe) == T3_RDMA_WRITE)
-                       tagged = 1;
-               if ((CQE_OPCODE(rsp_msg->cqe) == T3_READ_REQ) ||
-                   (CQE_OPCODE(rsp_msg->cqe) == T3_READ_RESP))
-                       tagged = 2;
-       } else {
-               status = TPT_ERR_INTERNAL_ERR;
-       }
-       build_term_codes(status, &term->layer_etype, &term->ecode, tagged);
+       build_term_codes(rsp_msg, &term->layer_etype, &term->ecode);
        build_fw_riwrh((void *)wqe, T3_WR_SEND,
                       T3_COMPLETION_FLAG | T3_NOTIFY_FLAG, 1,
                       qhp->ep->hwtid, 5);
index e2cdc1a..67f0670 100644 (file)
@@ -113,7 +113,7 @@ struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
        return ret;
 }
 
-struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
+struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
                             struct ib_ucontext *context,
                             struct ib_udata *udata)
 {
index 95fd59f..e14b029 100644 (file)
@@ -123,7 +123,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
 void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
 
 
-struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
+struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
                             struct ib_ucontext *context,
                             struct ib_udata *udata);
 
@@ -135,7 +135,7 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc);
 
 int ehca_peek_cq(struct ib_cq *cq, int wc_cnt);
 
-int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify);
+int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags);
 
 struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                             struct ib_qp_init_attr *init_attr,
index 4700085..2d37054 100644 (file)
@@ -313,6 +313,7 @@ int ehca_init_device(struct ehca_shca *shca)
 
        shca->ib_device.node_type           = RDMA_NODE_IB_CA;
        shca->ib_device.phys_port_cnt       = shca->num_ports;
+       shca->ib_device.num_comp_vectors    = 1;
        shca->ib_device.dma_device          = &shca->ibmebus_dev->ofdev.dev;
        shca->ib_device.query_device        = ehca_query_device;
        shca->ib_device.query_port          = ehca_query_port;
@@ -375,7 +376,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
                return -EPERM;
        }
 
-       ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10);
+       ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10, 0);
        if (IS_ERR(ibcq)) {
                ehca_err(&shca->ib_device, "Cannot create AQP1 CQ.");
                return PTR_ERR(ibcq);
index 08d3f89..caec9de 100644 (file)
@@ -634,11 +634,13 @@ poll_cq_exit0:
        return ret;
 }
 
-int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify)
+int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
 {
        struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+       unsigned long spl_flags;
+       int ret = 0;
 
-       switch (cq_notify) {
+       switch (notify_flags & IB_CQ_SOLICITED_MASK) {
        case IB_CQ_SOLICITED:
                hipz_set_cqx_n0(my_cq, 1);
                break;
@@ -649,5 +651,11 @@ int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify)
                return -EINVAL;
        }
 
-       return 0;
+       if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
+               spin_lock_irqsave(&my_cq->spinlock, spl_flags);
+               ret = ipz_qeit_is_valid(&my_cq->ipz_queue);
+               spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
+       }
+
+       return ret;
 }
index 8199c45..57f141a 100644 (file)
@@ -140,6 +140,14 @@ static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
        return cqe;
 }
 
+static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
+{
+       struct ehca_cqe *cqe = ipz_qeit_get(queue);
+       u32 cqe_flags = cqe->cqe_flags;
+
+       return cqe_flags >> 7 == (queue->toggle_state & 1);
+}
+
 /*
  * returns and resets Queue Entry iterator
  * returns address (kv) of first Queue Entry
index ea78e6d..3e9241b 100644 (file)
@@ -204,7 +204,7 @@ static void send_complete(unsigned long data)
  *
  * Called by ib_create_cq() in the generic verbs code.
  */
-struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector,
                              struct ib_ucontext *context,
                              struct ib_udata *udata)
 {
@@ -243,33 +243,21 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
         * See ipath_mmap() for details.
         */
        if (udata && udata->outlen >= sizeof(__u64)) {
-               struct ipath_mmap_info *ip;
-               __u64 offset = (__u64) wc;
                int err;
+               u32 s = sizeof *wc + sizeof(struct ib_wc) * entries;
 
-               err = ib_copy_to_udata(udata, &offset, sizeof(offset));
-               if (err) {
-                       ret = ERR_PTR(err);
+               cq->ip = ipath_create_mmap_info(dev, s, context, wc);
+               if (!cq->ip) {
+                       ret = ERR_PTR(-ENOMEM);
                        goto bail_wc;
                }
 
-               /* Allocate info for ipath_mmap(). */
-               ip = kmalloc(sizeof(*ip), GFP_KERNEL);
-               if (!ip) {
-                       ret = ERR_PTR(-ENOMEM);
-                       goto bail_wc;
+               err = ib_copy_to_udata(udata, &cq->ip->offset,
+                                      sizeof(cq->ip->offset));
+               if (err) {
+                       ret = ERR_PTR(err);
+                       goto bail_ip;
                }
-               cq->ip = ip;
-               ip->context = context;
-               ip->obj = wc;
-               kref_init(&ip->ref);
-               ip->mmap_cnt = 0;
-               ip->size = PAGE_ALIGN(sizeof(*wc) +
-                                     sizeof(struct ib_wc) * entries);
-               spin_lock_irq(&dev->pending_lock);
-               ip->next = dev->pending_mmaps;
-               dev->pending_mmaps = ip;
-               spin_unlock_irq(&dev->pending_lock);
        } else
                cq->ip = NULL;
 
@@ -277,12 +265,18 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
        if (dev->n_cqs_allocated == ib_ipath_max_cqs) {
                spin_unlock(&dev->n_cqs_lock);
                ret = ERR_PTR(-ENOMEM);
-               goto bail_wc;
+               goto bail_ip;
        }
 
        dev->n_cqs_allocated++;
        spin_unlock(&dev->n_cqs_lock);
 
+       if (cq->ip) {
+               spin_lock_irq(&dev->pending_lock);
+               list_add(&cq->ip->pending_mmaps, &dev->pending_mmaps);
+               spin_unlock_irq(&dev->pending_lock);
+       }
+
        /*
         * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe.
         * The number of entries should be >= the number requested or return
@@ -301,12 +295,12 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
 
        goto done;
 
+bail_ip:
+       kfree(cq->ip);
 bail_wc:
        vfree(wc);
-
 bail_cq:
        kfree(cq);
-
 done:
        return ret;
 }
@@ -340,17 +334,18 @@ int ipath_destroy_cq(struct ib_cq *ibcq)
 /**
  * ipath_req_notify_cq - change the notification type for a completion queue
  * @ibcq: the completion queue
- * @notify: the type of notification to request
+ * @notify_flags: the type of notification to request
  *
  * Returns 0 for success.
  *
  * This may be called from interrupt context.  Also called by
  * ib_req_notify_cq() in the generic verbs code.
  */
-int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags)
 {
        struct ipath_cq *cq = to_icq(ibcq);
        unsigned long flags;
+       int ret = 0;
 
        spin_lock_irqsave(&cq->lock, flags);
        /*
@@ -358,9 +353,15 @@ int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
         * any other transitions (see C11-31 and C11-32 in ch. 11.4.2.2).
         */
        if (cq->notify != IB_CQ_NEXT_COMP)
-               cq->notify = notify;
+               cq->notify = notify_flags & IB_CQ_SOLICITED_MASK;
+
+       if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) &&
+           cq->queue->head != cq->queue->tail)
+               ret = 1;
+
        spin_unlock_irqrestore(&cq->lock, flags);
-       return 0;
+
+       return ret;
 }
 
 /**
@@ -443,13 +444,12 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
        if (cq->ip) {
                struct ipath_ibdev *dev = to_idev(ibcq->device);
                struct ipath_mmap_info *ip = cq->ip;
+               u32 s = sizeof *wc + sizeof(struct ib_wc) * cqe;
 
-               ip->obj = wc;
-               ip->size = PAGE_ALIGN(sizeof(*wc) +
-                                     sizeof(struct ib_wc) * cqe);
+               ipath_update_mmap_info(dev, ip, s, wc);
                spin_lock_irq(&dev->pending_lock);
-               ip->next = dev->pending_mmaps;
-               dev->pending_mmaps = ip;
+               if (list_empty(&ip->pending_mmaps))
+                       list_add(&ip->pending_mmaps, &dev->pending_mmaps);
                spin_unlock_irq(&dev->pending_lock);
        }
 
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 a82157d..937bc33 100644 (file)
@@ -46,6 +46,11 @@ void ipath_release_mmap_info(struct kref *ref)
 {
        struct ipath_mmap_info *ip =
                container_of(ref, struct ipath_mmap_info, ref);
+       struct ipath_ibdev *dev = to_idev(ip->context->device);
+
+       spin_lock_irq(&dev->pending_lock);
+       list_del(&ip->pending_mmaps);
+       spin_unlock_irq(&dev->pending_lock);
 
        vfree(ip->obj);
        kfree(ip);
@@ -60,14 +65,12 @@ static void ipath_vma_open(struct vm_area_struct *vma)
        struct ipath_mmap_info *ip = vma->vm_private_data;
 
        kref_get(&ip->ref);
-       ip->mmap_cnt++;
 }
 
 static void ipath_vma_close(struct vm_area_struct *vma)
 {
        struct ipath_mmap_info *ip = vma->vm_private_data;
 
-       ip->mmap_cnt--;
        kref_put(&ip->ref, ipath_release_mmap_info);
 }
 
@@ -87,7 +90,7 @@ int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
        struct ipath_ibdev *dev = to_idev(context->device);
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        unsigned long size = vma->vm_end - vma->vm_start;
-       struct ipath_mmap_info *ip, **pp;
+       struct ipath_mmap_info *ip, *pp;
        int ret = -EINVAL;
 
        /*
@@ -96,15 +99,16 @@ int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
         * CQ, QP, or SRQ is soon followed by a call to mmap().
         */
        spin_lock_irq(&dev->pending_lock);
-       for (pp = &dev->pending_mmaps; (ip = *pp); pp = &ip->next) {
+       list_for_each_entry_safe(ip, pp, &dev->pending_mmaps,
+                                pending_mmaps) {
                /* Only the creator is allowed to mmap the object */
-               if (context != ip->context || (void *) offset != ip->obj)
+               if (context != ip->context || (__u64) offset != ip->offset)
                        continue;
                /* Don't allow a mmap larger than the object. */
                if (size > ip->size)
                        break;
 
-               *pp = ip->next;
+               list_del_init(&ip->pending_mmaps);
                spin_unlock_irq(&dev->pending_lock);
 
                ret = remap_vmalloc_range(vma, ip->obj, 0);
@@ -119,3 +123,51 @@ int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 done:
        return ret;
 }
+
+/*
+ * Allocate information for ipath_mmap
+ */
+struct ipath_mmap_info *ipath_create_mmap_info(struct ipath_ibdev *dev,
+                                              u32 size,
+                                              struct ib_ucontext *context,
+                                              void *obj) {
+       struct ipath_mmap_info *ip;
+
+       ip = kmalloc(sizeof *ip, GFP_KERNEL);
+       if (!ip)
+               goto bail;
+
+       size = PAGE_ALIGN(size);
+
+       spin_lock_irq(&dev->mmap_offset_lock);
+       if (dev->mmap_offset == 0)
+               dev->mmap_offset = PAGE_SIZE;
+       ip->offset = dev->mmap_offset;
+       dev->mmap_offset += size;
+       spin_unlock_irq(&dev->mmap_offset_lock);
+
+       INIT_LIST_HEAD(&ip->pending_mmaps);
+       ip->size = size;
+       ip->context = context;
+       ip->obj = obj;
+       kref_init(&ip->ref);
+
+bail:
+       return ip;
+}
+
+void ipath_update_mmap_info(struct ipath_ibdev *dev,
+                           struct ipath_mmap_info *ip,
+                           u32 size, void *obj) {
+       size = PAGE_ALIGN(size);
+
+       spin_lock_irq(&dev->mmap_offset_lock);
+       if (dev->mmap_offset == 0)
+               dev->mmap_offset = PAGE_SIZE;
+       ip->offset = dev->mmap_offset;
+       dev->mmap_offset += size;
+       spin_unlock_irq(&dev->mmap_offset_lock);
+
+       ip->size = size;
+       ip->obj = obj;
+}
index 16db9ac..bfef08e 100644 (file)
@@ -844,34 +844,36 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
         * See ipath_mmap() for details.
         */
        if (udata && udata->outlen >= sizeof(__u64)) {
-               struct ipath_mmap_info *ip;
-               __u64 offset = (__u64) qp->r_rq.wq;
                int err;
 
-               err = ib_copy_to_udata(udata, &offset, sizeof(offset));
-               if (err) {
-                       ret = ERR_PTR(err);
-                       goto bail_rwq;
-               }
+               if (!qp->r_rq.wq) {
+                       __u64 offset = 0;
 
-               if (qp->r_rq.wq) {
-                       /* Allocate info for ipath_mmap(). */
-                       ip = kmalloc(sizeof(*ip), GFP_KERNEL);
-                       if (!ip) {
+                       err = ib_copy_to_udata(udata, &offset,
+                                              sizeof(offset));
+                       if (err) {
+                               ret = ERR_PTR(err);
+                               goto bail_rwq;
+                       }
+               } else {
+                       u32 s = sizeof(struct ipath_rwq) +
+                               qp->r_rq.size * sz;
+
+                       qp->ip =
+                           ipath_create_mmap_info(dev, s,
+                                                  ibpd->uobject->context,
+                                                  qp->r_rq.wq);
+                       if (!qp->ip) {
                                ret = ERR_PTR(-ENOMEM);
                                goto bail_rwq;
                        }
-                       qp->ip = ip;
-                       ip->context = ibpd->uobject->context;
-                       ip->obj = qp->r_rq.wq;
-                       kref_init(&ip->ref);
-                       ip->mmap_cnt = 0;
-                       ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) +
-                                             qp->r_rq.size * sz);
-                       spin_lock_irq(&dev->pending_lock);
-                       ip->next = dev->pending_mmaps;
-                       dev->pending_mmaps = ip;
-                       spin_unlock_irq(&dev->pending_lock);
+
+                       err = ib_copy_to_udata(udata, &(qp->ip->offset),
+                                              sizeof(qp->ip->offset));
+                       if (err) {
+                               ret = ERR_PTR(err);
+                               goto bail_ip;
+                       }
                }
        }
 
@@ -885,6 +887,12 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
        dev->n_qps_allocated++;
        spin_unlock(&dev->n_qps_lock);
 
+       if (qp->ip) {
+               spin_lock_irq(&dev->pending_lock);
+               list_add(&qp->ip->pending_mmaps, &dev->pending_mmaps);
+               spin_unlock_irq(&dev->pending_lock);
+       }
+
        ret = &qp->ibqp;
        goto bail;
 
index b4b88d0..1915771 100644 (file)
@@ -98,13 +98,21 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
        case OP(RDMA_READ_RESPONSE_LAST):
        case OP(RDMA_READ_RESPONSE_ONLY):
        case OP(ATOMIC_ACKNOWLEDGE):
-               qp->s_ack_state = OP(ACKNOWLEDGE);
+               /*
+                * We can increment the tail pointer now that the last
+                * response has been sent instead of only being
+                * constructed.
+                */
+               if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC)
+                       qp->s_tail_ack_queue = 0;
                /* FALLTHROUGH */
+       case OP(SEND_ONLY):
        case OP(ACKNOWLEDGE):
                /* Check for no next entry in the queue. */
                if (qp->r_head_ack_queue == qp->s_tail_ack_queue) {
                        if (qp->s_flags & IPATH_S_ACK_PENDING)
                                goto normal;
+                       qp->s_ack_state = OP(ACKNOWLEDGE);
                        goto bail;
                }
 
@@ -117,12 +125,8 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                        if (len > pmtu) {
                                len = pmtu;
                                qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
-                       } else {
+                       } else
                                qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
-                               if (++qp->s_tail_ack_queue >
-                                   IPATH_MAX_RDMA_ATOMIC)
-                                       qp->s_tail_ack_queue = 0;
-                       }
                        ohdr->u.aeth = ipath_compute_aeth(qp);
                        hwords++;
                        qp->s_ack_rdma_psn = e->psn;
@@ -139,8 +143,6 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                                cpu_to_be32(e->atomic_data);
                        hwords += sizeof(ohdr->u.at) / sizeof(u32);
                        bth2 = e->psn;
-                       if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC)
-                               qp->s_tail_ack_queue = 0;
                }
                bth0 = qp->s_ack_state << 24;
                break;
@@ -156,8 +158,6 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                        ohdr->u.aeth = ipath_compute_aeth(qp);
                        hwords++;
                        qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
-                       if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC)
-                               qp->s_tail_ack_queue = 0;
                }
                bth0 = qp->s_ack_state << 24;
                bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK;
@@ -171,7 +171,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
                 * the ACK before setting s_ack_state to ACKNOWLEDGE
                 * (see above).
                 */
-               qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE);
+               qp->s_ack_state = OP(SEND_ONLY);
                qp->s_flags &= ~IPATH_S_ACK_PENDING;
                qp->s_cur_sge = NULL;
                if (qp->s_nak_state)
@@ -223,23 +223,18 @@ int ipath_make_rc_req(struct ipath_qp *qp,
        /* Sending responses has higher priority over sending requests. */
        if ((qp->r_head_ack_queue != qp->s_tail_ack_queue ||
             (qp->s_flags & IPATH_S_ACK_PENDING) ||
-            qp->s_ack_state != IB_OPCODE_RC_ACKNOWLEDGE) &&
+            qp->s_ack_state != OP(ACKNOWLEDGE)) &&
            ipath_make_rc_ack(qp, ohdr, pmtu, bth0p, bth2p))
                goto done;
 
        if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) ||
-           qp->s_rnr_timeout)
+           qp->s_rnr_timeout || qp->s_wait_credit)
                goto bail;
 
        /* Limit the number of packets sent without an ACK. */
        if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT) > 0) {
                qp->s_wait_credit = 1;
                dev->n_rc_stalls++;
-               spin_lock(&dev->pending_lock);
-               if (list_empty(&qp->timerwait))
-                       list_add_tail(&qp->timerwait,
-                                     &dev->pending[dev->pending_index]);
-               spin_unlock(&dev->pending_lock);
                goto bail;
        }
 
@@ -587,9 +582,12 @@ static void send_rc_ack(struct ipath_qp *qp)
        u32 hwords;
        struct ipath_ib_header hdr;
        struct ipath_other_headers *ohdr;
+       unsigned long flags;
 
        /* Don't send ACK or NAK if a RDMA read or atomic is pending. */
-       if (qp->r_head_ack_queue != qp->s_tail_ack_queue)
+       if (qp->r_head_ack_queue != qp->s_tail_ack_queue ||
+           (qp->s_flags & IPATH_S_ACK_PENDING) ||
+           qp->s_ack_state != OP(ACKNOWLEDGE))
                goto queue_ack;
 
        /* Construct the header. */
@@ -640,11 +638,11 @@ static void send_rc_ack(struct ipath_qp *qp)
        dev->n_rc_qacks++;
 
 queue_ack:
-       spin_lock_irq(&qp->s_lock);
+       spin_lock_irqsave(&qp->s_lock, flags);
        qp->s_flags |= IPATH_S_ACK_PENDING;
        qp->s_nak_state = qp->r_nak_state;
        qp->s_ack_psn = qp->r_ack_psn;
-       spin_unlock_irq(&qp->s_lock);
+       spin_unlock_irqrestore(&qp->s_lock, flags);
 
        /* Call ipath_do_rc_send() in another thread. */
        tasklet_hi_schedule(&qp->s_task);
@@ -1261,6 +1259,7 @@ ack_err:
        wc.dlid_path_bits = 0;
        wc.port_num = 0;
        ipath_sqerror_qp(qp, &wc);
+       spin_unlock_irqrestore(&qp->s_lock, flags);
 bail:
        return;
 }
@@ -1294,6 +1293,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
        struct ipath_ack_entry *e;
        u8 i, prev;
        int old_req;
+       unsigned long flags;
 
        if (diff > 0) {
                /*
@@ -1327,7 +1327,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
        psn &= IPATH_PSN_MASK;
        e = NULL;
        old_req = 1;
-       spin_lock_irq(&qp->s_lock);
+       spin_lock_irqsave(&qp->s_lock, flags);
        for (i = qp->r_head_ack_queue; ; i = prev) {
                if (i == qp->s_tail_ack_queue)
                        old_req = 0;
@@ -1425,7 +1425,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
                 * after all the previous RDMA reads and atomics.
                 */
                if (i == qp->r_head_ack_queue) {
-                       spin_unlock_irq(&qp->s_lock);
+                       spin_unlock_irqrestore(&qp->s_lock, flags);
                        qp->r_nak_state = 0;
                        qp->r_ack_psn = qp->r_psn - 1;
                        goto send_ack;
@@ -1439,11 +1439,10 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
                break;
        }
        qp->r_nak_state = 0;
-       spin_unlock_irq(&qp->s_lock);
        tasklet_hi_schedule(&qp->s_task);
 
 unlock_done:
-       spin_unlock_irq(&qp->s_lock);
+       spin_unlock_irqrestore(&qp->s_lock, flags);
 done:
        return 1;
 
@@ -1453,10 +1452,12 @@ send_ack:
 
 static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err)
 {
-       spin_lock_irq(&qp->s_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->s_lock, flags);
        qp->state = IB_QPS_ERR;
        ipath_error_qp(qp, err);
-       spin_unlock_irq(&qp->s_lock);
+       spin_unlock_irqrestore(&qp->s_lock, flags);
 }
 
 /**
index 9403350..03acae6 100644 (file)
@@ -139,33 +139,24 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
         * See ipath_mmap() for details.
         */
        if (udata && udata->outlen >= sizeof(__u64)) {
-               struct ipath_mmap_info *ip;
-               __u64 offset = (__u64) srq->rq.wq;
                int err;
+               u32 s = sizeof(struct ipath_rwq) + srq->rq.size * sz;
 
-               err = ib_copy_to_udata(udata, &offset, sizeof(offset));
-               if (err) {
-                       ret = ERR_PTR(err);
+               srq->ip =
+                   ipath_create_mmap_info(dev, s,
+                                          ibpd->uobject->context,
+                                          srq->rq.wq);
+               if (!srq->ip) {
+                       ret = ERR_PTR(-ENOMEM);
                        goto bail_wq;
                }
 
-               /* Allocate info for ipath_mmap(). */
-               ip = kmalloc(sizeof(*ip), GFP_KERNEL);
-               if (!ip) {
-                       ret = ERR_PTR(-ENOMEM);
-                       goto bail_wq;
+               err = ib_copy_to_udata(udata, &srq->ip->offset,
+                                      sizeof(srq->ip->offset));
+               if (err) {
+                       ret = ERR_PTR(err);
+                       goto bail_ip;
                }
-               srq->ip = ip;
-               ip->context = ibpd->uobject->context;
-               ip->obj = srq->rq.wq;
-               kref_init(&ip->ref);
-               ip->mmap_cnt = 0;
-               ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) +
-                                     srq->rq.size * sz);
-               spin_lock_irq(&dev->pending_lock);
-               ip->next = dev->pending_mmaps;
-               dev->pending_mmaps = ip;
-               spin_unlock_irq(&dev->pending_lock);
        } else
                srq->ip = NULL;
 
@@ -181,21 +172,27 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
        if (dev->n_srqs_allocated == ib_ipath_max_srqs) {
                spin_unlock(&dev->n_srqs_lock);
                ret = ERR_PTR(-ENOMEM);
-               goto bail_wq;
+               goto bail_ip;
        }
 
        dev->n_srqs_allocated++;
        spin_unlock(&dev->n_srqs_lock);
 
+       if (srq->ip) {
+               spin_lock_irq(&dev->pending_lock);
+               list_add(&srq->ip->pending_mmaps, &dev->pending_mmaps);
+               spin_unlock_irq(&dev->pending_lock);
+       }
+
        ret = &srq->ibsrq;
        goto done;
 
+bail_ip:
+       kfree(srq->ip);
 bail_wq:
        vfree(srq->rq.wq);
-
 bail_srq:
        kfree(srq);
-
 done:
        return ret;
 }
@@ -312,13 +309,13 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                if (srq->ip) {
                        struct ipath_mmap_info *ip = srq->ip;
                        struct ipath_ibdev *dev = to_idev(srq->ibsrq.device);
+                       u32 s = sizeof(struct ipath_rwq) + size * sz;
 
-                       ip->obj = wq;
-                       ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) +
-                                             size * sz);
+                       ipath_update_mmap_info(dev, ip, s, wq);
                        spin_lock_irq(&dev->pending_lock);
-                       ip->next = dev->pending_mmaps;
-                       dev->pending_mmaps = ip;
+                       if (list_empty(&ip->pending_mmaps))
+                               list_add(&ip->pending_mmaps,
+                                        &dev->pending_mmaps);
                        spin_unlock_irq(&dev->pending_lock);
                }
        } else if (attr_mask & IB_SRQ_LIMIT) {
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 18c6df2..12933e7 100644 (file)
@@ -1476,7 +1476,10 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
                ret = -ENOMEM;
                goto err_lk;
        }
+       INIT_LIST_HEAD(&idev->pending_mmaps);
        spin_lock_init(&idev->pending_lock);
+       idev->mmap_offset = PAGE_SIZE;
+       spin_lock_init(&idev->mmap_offset_lock);
        INIT_LIST_HEAD(&idev->pending[0]);
        INIT_LIST_HEAD(&idev->pending[1]);
        INIT_LIST_HEAD(&idev->pending[2]);
@@ -1558,6 +1561,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
                (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
        dev->node_type = RDMA_NODE_IB_CA;
        dev->phys_port_cnt = 1;
+       dev->num_comp_vectors = 1;
        dev->dma_device = &dd->pcidev->dev;
        dev->query_device = ipath_query_device;
        dev->modify_device = ipath_modify_device;
index 7c4929f..7064fc2 100644 (file)
@@ -173,12 +173,12 @@ struct ipath_ah {
  * this as its vm_private_data.
  */
 struct ipath_mmap_info {
-       struct ipath_mmap_info *next;
+       struct list_head pending_mmaps;
        struct ib_ucontext *context;
        void *obj;
+       __u64 offset;
        struct kref ref;
        unsigned size;
-       unsigned mmap_cnt;
 };
 
 /*
@@ -422,7 +422,7 @@ struct ipath_qp {
 #define IPATH_S_RDMAR_PENDING  0x04
 #define IPATH_S_ACK_PENDING    0x08
 
-#define IPATH_PSN_CREDIT       2048
+#define IPATH_PSN_CREDIT       512
 
 /*
  * Since struct ipath_swqe is not a fixed size, we can't simply index into
@@ -485,9 +485,10 @@ struct ipath_opcode_stats {
 
 struct ipath_ibdev {
        struct ib_device ibdev;
-       struct list_head dev_list;
        struct ipath_devdata *dd;
-       struct ipath_mmap_info *pending_mmaps;
+       struct list_head pending_mmaps;
+       spinlock_t mmap_offset_lock;
+       u32 mmap_offset;
        int ib_unit;            /* This is the device number */
        u16 sm_lid;             /* in host order */
        u8 sm_sl;
@@ -734,13 +735,13 @@ int ipath_destroy_srq(struct ib_srq *ibsrq);
 
 int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
 
-struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector,
                              struct ib_ucontext *context,
                              struct ib_udata *udata);
 
 int ipath_destroy_cq(struct ib_cq *ibcq);
 
-int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify);
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags);
 
 int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata);
 
@@ -768,6 +769,15 @@ int ipath_dealloc_fmr(struct ib_fmr *ibfmr);
 
 void ipath_release_mmap_info(struct kref *ref);
 
+struct ipath_mmap_info *ipath_create_mmap_info(struct ipath_ibdev *dev,
+                                              u32 size,
+                                              struct ib_ucontext *context,
+                                              void *obj);
+
+void ipath_update_mmap_info(struct ipath_ibdev *dev,
+                           struct ipath_mmap_info *ip,
+                           u32 size, void *obj);
+
 int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
 
 void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev);
index efd79ef..cf0868f 100644 (file)
@@ -726,11 +726,12 @@ repoll:
        return err == 0 || err == -EAGAIN ? npolled : err;
 }
 
-int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
+int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags)
 {
        __be32 doorbell[2];
 
-       doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
+       doorbell[0] = cpu_to_be32(((flags & IB_CQ_SOLICITED_MASK) ==
+                                  IB_CQ_SOLICITED ?
                                   MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
                                   MTHCA_TAVOR_CQ_DB_REQ_NOT)      |
                                  to_mcq(cq)->cqn);
@@ -743,7 +744,7 @@ int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
        return 0;
 }
 
-int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
 {
        struct mthca_cq *cq = to_mcq(ibcq);
        __be32 doorbell[2];
@@ -755,7 +756,8 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
 
        doorbell[0] = ci;
        doorbell[1] = cpu_to_be32((cq->cqn << 8) | (2 << 5) | (sn << 3) |
-                                 (notify == IB_CQ_SOLICITED ? 1 : 2));
+                                 ((flags & IB_CQ_SOLICITED_MASK) ==
+                                  IB_CQ_SOLICITED ? 1 : 2));
 
        mthca_write_db_rec(doorbell, cq->arm_db);
 
@@ -766,7 +768,7 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
        wmb();
 
        doorbell[0] = cpu_to_be32((sn << 28)                       |
-                                 (notify == IB_CQ_SOLICITED ?
+                                 ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
                                   MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL :
                                   MTHCA_ARBEL_CQ_DB_REQ_NOT)      |
                                  cq->cqn);
index b7e42ef..9bae3cc 100644 (file)
@@ -495,8 +495,8 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev);
 
 int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
                  struct ib_wc *entry);
-int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
-int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
+int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags);
+int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags);
 int mthca_init_cq(struct mthca_dev *dev, int nent,
                  struct mthca_ucontext *ctx, u32 pdn,
                  struct mthca_cq *cq);
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 47e6fd4..1c05486 100644 (file)
@@ -663,6 +663,7 @@ static int mthca_destroy_qp(struct ib_qp *qp)
 }
 
 static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
+                                    int comp_vector,
                                     struct ib_ucontext *context,
                                     struct ib_udata *udata)
 {
@@ -1292,6 +1293,7 @@ int mthca_register_device(struct mthca_dev *dev)
                (1ull << IB_USER_VERBS_CMD_DETACH_MCAST);
        dev->ib_dev.node_type            = RDMA_NODE_IB_CA;
        dev->ib_dev.phys_port_cnt        = dev->limits.num_ports;
+       dev->ib_dev.num_comp_vectors     = 1;
        dev->ib_dev.dma_device           = &dev->pdev->dev;
        dev->ib_dev.query_device         = mthca_query_device;
        dev->ib_dev.query_port           = mthca_query_port;
index 8fe6fee..fee60c8 100644 (file)
@@ -701,6 +701,19 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
                qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
        }
 
+       if (ibqp->qp_type == IB_QPT_RC &&
+           cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
+               u8 sched_queue = ibqp->uobject ? 0x2 : 0x1;
+
+               if (mthca_is_memfree(dev))
+                       qp_context->rlkey_arbel_sched_queue |= sched_queue;
+               else
+                       qp_context->tavor_sched_queue |= cpu_to_be32(sched_queue);
+
+               qp_param->opt_param_mask |=
+                       cpu_to_be32(MTHCA_QP_OPTPAR_SCHED_QUEUE);
+       }
+
        if (attr_mask & IB_QP_TIMEOUT) {
                qp_context->pri_path.ackto = attr->timeout << 3;
                qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT);
index fd55826..87310ee 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>
@@ -311,6 +310,7 @@ extern struct workqueue_struct *ipoib_workqueue;
 
 /* functions */
 
+int ipoib_poll(struct net_device *dev, int *budget);
 void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
 
 struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
index 0c4e59b..785bc85 100644 (file)
@@ -370,7 +370,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
 
        if (!likely(wr_id & IPOIB_CM_RX_UPDATE_MASK)) {
                p = wc->qp->qp_context;
-               if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
+               if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
                        spin_lock_irqsave(&priv->lock, flags);
                        p->jiffies = jiffies;
                        /* Move this entry to list head, but do
@@ -416,7 +416,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        skb->dev = dev;
        /* XXX get correct PACKET_ type here */
        skb->pkt_type = PACKET_HOST;
-       netif_rx_ni(skb);
+       netif_receive_skb(skb);
 
 repost:
        if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
@@ -592,7 +592,9 @@ int ipoib_cm_dev_open(struct net_device *dev)
        priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev);
        if (IS_ERR(priv->cm.id)) {
                printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
-               return IS_ERR(priv->cm.id);
+               ret = PTR_ERR(priv->cm.id);
+               priv->cm.id = NULL;
+               return ret;
        }
 
        ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num),
@@ -601,6 +603,7 @@ int ipoib_cm_dev_open(struct net_device *dev)
                printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name,
                       IPOIB_CM_IETF_ID | priv->qp->qp_num);
                ib_destroy_cm_id(priv->cm.id);
+               priv->cm.id = NULL;
                return ret;
        }
        return 0;
@@ -611,10 +614,11 @@ void ipoib_cm_dev_stop(struct net_device *dev)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_cm_rx *p;
 
-       if (!IPOIB_CM_SUPPORTED(dev->dev_addr))
+       if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id)
                return;
 
        ib_destroy_cm_id(priv->cm.id);
+       priv->cm.id = NULL;
        spin_lock_irq(&priv->lock);
        while (!list_empty(&priv->cm.passive_ids)) {
                p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
@@ -789,7 +793,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
        }
 
        p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p,
-                            ipoib_sendq_size + 1);
+                            ipoib_sendq_size + 1, 0);
        if (IS_ERR(p->cq)) {
                ret = PTR_ERR(p->cq);
                ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret);
index 1bdb910..68d72c6 100644 (file)
@@ -226,7 +226,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                skb->dev = dev;
                /* XXX get correct PACKET_ type here */
                skb->pkt_type = PACKET_HOST;
-               netif_rx_ni(skb);
+               netif_receive_skb(skb);
        } else {
                ipoib_dbg_data(priv, "dropping loopback packet\n");
                dev_kfree_skb_any(skb);
@@ -280,28 +280,63 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
                           wc->status, wr_id, wc->vendor_err);
 }
 
-static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc)
+int ipoib_poll(struct net_device *dev, int *budget)
 {
-       if (wc->wr_id & IPOIB_CM_OP_SRQ)
-               ipoib_cm_handle_rx_wc(dev, wc);
-       else if (wc->wr_id & IPOIB_OP_RECV)
-               ipoib_ib_handle_rx_wc(dev, wc);
-       else
-               ipoib_ib_handle_tx_wc(dev, wc);
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       int max = min(*budget, dev->quota);
+       int done;
+       int t;
+       int empty;
+       int n, i;
+
+       done  = 0;
+       empty = 0;
+
+       while (max) {
+               t = min(IPOIB_NUM_WC, max);
+               n = ib_poll_cq(priv->cq, t, priv->ibwc);
+
+               for (i = 0; i < n; ++i) {
+                       struct ib_wc *wc = priv->ibwc + i;
+
+                       if (wc->wr_id & IPOIB_CM_OP_SRQ) {
+                               ++done;
+                               --max;
+                               ipoib_cm_handle_rx_wc(dev, wc);
+                       } else if (wc->wr_id & IPOIB_OP_RECV) {
+                               ++done;
+                               --max;
+                               ipoib_ib_handle_rx_wc(dev, wc);
+                       } else
+                               ipoib_ib_handle_tx_wc(dev, wc);
+               }
+
+               if (n != t) {
+                       empty = 1;
+                       break;
+               }
+       }
+
+       dev->quota -= done;
+       *budget    -= done;
+
+       if (empty) {
+               netif_rx_complete(dev);
+               if (unlikely(ib_req_notify_cq(priv->cq,
+                                             IB_CQ_NEXT_COMP |
+                                             IB_CQ_REPORT_MISSED_EVENTS)) &&
+                   netif_rx_reschedule(dev, 0))
+                       return 1;
+
+               return 0;
+       }
+
+       return 1;
 }
 
 void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
 {
-       struct net_device *dev = (struct net_device *) dev_ptr;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
-       int n, i;
-
-       ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
-       do {
-               n = ib_poll_cq(cq, IPOIB_NUM_WC, priv->ibwc);
-               for (i = 0; i < n; ++i)
-                       ipoib_ib_handle_wc(dev, priv->ibwc + i);
-       } while (n == IPOIB_NUM_WC);
+       netif_rx_schedule(dev_ptr);
 }
 
 static inline int post_send(struct ipoib_dev_priv *priv,
@@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev)
        struct ib_qp_attr qp_attr;
        unsigned long begin;
        struct ipoib_tx_buf *tx_req;
-       int i;
+       int i, n;
 
        clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+       netif_poll_disable(dev);
 
        ipoib_cm_dev_stop(dev);
 
@@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev)
                        goto timeout;
                }
 
+               do {
+                       n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
+                       for (i = 0; i < n; ++i) {
+                               if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
+                                       ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
+                               else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
+                                       ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
+                               else
+                                       ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+                       }
+               } while (n == IPOIB_NUM_WC);
+
                msleep(1);
        }
 
@@ -596,6 +644,9 @@ timeout:
                msleep(1);
        }
 
+       netif_poll_enable(dev);
+       ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
+
        return 0;
 }
 
index b4c380c..0a428f2 100644 (file)
@@ -948,6 +948,8 @@ static void ipoib_setup(struct net_device *dev)
        dev->hard_header         = ipoib_hard_header;
        dev->set_multicast_list  = ipoib_set_mcast_list;
        dev->neigh_setup         = ipoib_neigh_setup_dev;
+       dev->poll                = ipoib_poll;
+       dev->weight              = 100;
 
        dev->watchdog_timeo      = HZ;
 
index 7f3ec20..5c3c6a4 100644 (file)
@@ -187,7 +187,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
        if (!ret)
                size += ipoib_recvq_size;
 
-       priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size);
+       priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
        if (IS_ERR(priv->cq)) {
                printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
                goto out_free_mr;
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 1fc9674..89d6008 100644 (file)
@@ -76,7 +76,7 @@ static int iser_create_device_ib_res(struct iser_device *device)
                                  iser_cq_callback,
                                  iser_cq_event_callback,
                                  (void *)device,
-                                 ISER_MAX_CQ_LEN);
+                                 ISER_MAX_CQ_LEN, 0);
        if (IS_ERR(device->cq))
                goto cq_err;
 
index 5e8ac57..39bf057 100644 (file)
@@ -197,7 +197,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
                return -ENOMEM;
 
        target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion,
-                                 NULL, target, SRP_CQ_SIZE);
+                                 NULL, target, SRP_CQ_SIZE, 0);
        if (IS_ERR(target->cq)) {
                ret = PTR_ERR(target->cq);
                goto out;
@@ -1468,6 +1468,25 @@ static ssize_t show_dgid(struct class_device *cdev, char *buf)
                       be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));
 }
 
+static ssize_t show_orig_dgid(struct class_device *cdev, char *buf)
+{
+       struct srp_target_port *target = host_to_target(class_to_shost(cdev));
+
+       if (target->state == SRP_TARGET_DEAD ||
+           target->state == SRP_TARGET_REMOVED)
+               return -ENODEV;
+
+       return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+                      be16_to_cpu(target->orig_dgid[0]),
+                      be16_to_cpu(target->orig_dgid[1]),
+                      be16_to_cpu(target->orig_dgid[2]),
+                      be16_to_cpu(target->orig_dgid[3]),
+                      be16_to_cpu(target->orig_dgid[4]),
+                      be16_to_cpu(target->orig_dgid[5]),
+                      be16_to_cpu(target->orig_dgid[6]),
+                      be16_to_cpu(target->orig_dgid[7]));
+}
+
 static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
 {
        struct srp_target_port *target = host_to_target(class_to_shost(cdev));
@@ -1498,6 +1517,7 @@ static CLASS_DEVICE_ATTR(ioc_guid,          S_IRUGO, show_ioc_guid,        NULL);
 static CLASS_DEVICE_ATTR(service_id,     S_IRUGO, show_service_id,      NULL);
 static CLASS_DEVICE_ATTR(pkey,           S_IRUGO, show_pkey,            NULL);
 static CLASS_DEVICE_ATTR(dgid,           S_IRUGO, show_dgid,            NULL);
+static CLASS_DEVICE_ATTR(orig_dgid,      S_IRUGO, show_orig_dgid,       NULL);
 static CLASS_DEVICE_ATTR(zero_req_lim,   S_IRUGO, show_zero_req_lim,    NULL);
 static CLASS_DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,  NULL);
 static CLASS_DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
@@ -1508,6 +1528,7 @@ static struct class_device_attribute *srp_host_attrs[] = {
        &class_device_attr_service_id,
        &class_device_attr_pkey,
        &class_device_attr_dgid,
+       &class_device_attr_orig_dgid,
        &class_device_attr_zero_req_lim,
        &class_device_attr_local_ib_port,
        &class_device_attr_local_ib_device,
@@ -1516,7 +1537,8 @@ static struct class_device_attribute *srp_host_attrs[] = {
 
 static struct scsi_host_template srp_template = {
        .module                         = THIS_MODULE,
-       .name                           = DRV_NAME,
+       .name                           = "InfiniBand SRP initiator",
+       .proc_name                      = DRV_NAME,
        .info                           = srp_target_info,
        .queuecommand                   = srp_queuecommand,
        .eh_abort_handler               = srp_abort,
@@ -1662,6 +1684,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
                                target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16);
                        }
                        kfree(p);
+                       memcpy(target->orig_dgid, target->path.dgid.raw, 16);
                        break;
 
                case SRP_OPT_PKEY:
index 2f3319c..1d53c7b 100644 (file)
@@ -129,6 +129,7 @@ struct srp_target_port {
        unsigned int            scsi_id;
 
        struct ib_sa_path_rec   path;
+       __be16                  orig_dgid[8];
        struct ib_sa_query     *path_query;
        int                     path_query_id;
 
index 0b45d47..a4c3729 100644 (file)
@@ -664,7 +664,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
        }
 
        /* temporary symlink to keep userspace happy */
-       error = sysfs_create_link(&input_class.subsys.kset.kobj,
+       error = sysfs_create_link(&input_class.subsys.kobj,
                                  &cdev->kobj, evdev->name);
        if (error)
                goto err_cdev_destroy;
@@ -676,7 +676,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
        return 0;
 
  err_remove_link:
-       sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
  err_cdev_destroy:
        class_device_destroy(&input_class, devt);
  err_free_evdev:
@@ -692,7 +692,7 @@ static void evdev_disconnect(struct input_handle *handle)
 
        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;
index 4f37224..9bcc542 100644 (file)
@@ -560,7 +560,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
        }
 
        /* temporary symlink to keep userspace happy */
-       error = sysfs_create_link(&input_class.subsys.kset.kobj,
+       error = sysfs_create_link(&input_class.subsys.kobj,
                                  &cdev->kobj, joydev->name);
        if (error)
                goto err_cdev_destroy;
@@ -572,7 +572,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
        return 0;
 
  err_remove_link:
-       sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
  err_cdev_destroy:
        class_device_destroy(&input_class, devt);
  err_free_joydev:
@@ -589,7 +589,7 @@ static void joydev_disconnect(struct input_handle *handle)
 
        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;
 
index cbf2abb..bd707b8 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
index fc1d1f2..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
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 73b85cb..499b697 100644 (file)
@@ -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
index d0d0744..81dd8c7 100644 (file)
@@ -155,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
index 83477d5..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
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 3b8011c..7678e98 100644 (file)
@@ -724,7 +724,7 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
        }
 
        /* temporary symlink to keep userspace happy */
-       error = sysfs_create_link(&input_class.subsys.kset.kobj,
+       error = sysfs_create_link(&input_class.subsys.kobj,
                                  &cdev->kobj, mousedev->name);
        if (error)
                goto err_cdev_destroy;
@@ -742,7 +742,7 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
  err_unregister_handle:
        input_unregister_handle(&mousedev->handle);
  err_remove_link:
-       sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
  err_cdev_destroy:
        class_device_destroy(&input_class, devt);
  err_free_mousedev:
@@ -758,7 +758,7 @@ static void mousedev_disconnect(struct input_handle *handle)
 
        input_unregister_handle(handle);
 
-       sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+       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;
index 2490874..61c1502 100644 (file)
@@ -21,7 +21,7 @@
 static void do_softint(void *data);
 
 static struct input_dev *hp680_ts_dev;
-static DECLARE_WORK(work, do_softint, 0);
+static DECLARE_WORK(work, do_softint);
 
 static void do_softint(void *data)
 {
index 8e2d2c9..5e5b5c9 100644 (file)
@@ -442,7 +442,7 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
        }
 
        /* temporary symlink to keep userspace happy */
-       error = sysfs_create_link(&input_class.subsys.kset.kobj,
+       error = sysfs_create_link(&input_class.subsys.kobj,
                                  &cdev->kobj, tsdev->name);
        if (error)
                goto err_cdev_destroy;
@@ -454,7 +454,7 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
        return 0;
 
  err_remove_link:
-       sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
  err_cdev_destroy:
        class_device_destroy(&input_class, devt);
  err_free_tsdev:
@@ -470,7 +470,7 @@ static void tsdev_disconnect(struct input_handle *handle)
 
        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;
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 509171c..2b4315d 100644 (file)
@@ -3080,7 +3080,7 @@ static int do_md_run(mddev_t * mddev)
                if (test_bit(Faulty, &rdev->flags))
                        continue;
                sync_blockdev(rdev->bdev);
-               invalidate_bdev(rdev->bdev, 0);
+               invalidate_bdev(rdev->bdev);
        }
 
        md_probe(mddev->unit, NULL, NULL);
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 3956c25..2d666b5 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/delay.h>
 #include <sound/driver.h>
 #include <sound/core.h>
index b2eb32e..2ebde2f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <asm/delay.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 fbce1d5..b94ef8a 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  *
  * device driver for Conexant 2388x based TV cards
@@ -34,6 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <asm/div64.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 690c942..ff642f8 100644 (file)
@@ -49,8 +49,8 @@ config MTD_MS02NV
 
          If you want to compile this driver as a module ( = code which can be
          inserted in and removed from the running kernel whenever you want),
-         say M here and read <file:Documentation/modules.txt>.  The module will
-         be called ms02-nv.o.
+         say M here and read <file:Documentation/kbuild/modules.txt>.
+         The module will be called ms02-nv.ko.
 
 config MTD_DATAFLASH
        tristate "Support for AT45xxx DataFlash"
index ce47544..fc4cc8b 100644 (file)
@@ -40,13 +40,11 @@ struct block2mtd_dev {
 static LIST_HEAD(blkmtd_device_list);
 
 
-static struct pagepage_read(struct address_space *mapping, int index)
+static struct page *page_read(struct address_space *mapping, int index)
 {
-       filler_t *filler = (filler_t*)mapping->a_ops->readpage;
-       return read_cache_page(mapping, index, filler, NULL);
+       return read_mapping_page(mapping, index, NULL);
 }
 
-
 /* erase a specified part of the device */
 static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
 {
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 d847ee1..3dba573 100644 (file)
@@ -940,8 +940,7 @@ static void ltree_entry_ctor(void *obj, struct kmem_cache *cache,
 {
        struct ltree_entry *le = obj;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) !=
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                return;
 
        le->users = 0;
index d396f99..0877fc3 100644 (file)
@@ -565,9 +565,9 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
         ib->btx_ring [entry].length = (-len) | 0xf000;
         ib->btx_ring [entry].misc = 0;
 
-       if (skb->len < ETH_ZLEN)
-               memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
-        skb_copy_from_linear_data(skb, &ib->tx_buf[entry][0], skblen);
+       if (skb->len < ETH_ZLEN)
+               memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
+        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
 
         /* Now, give the packet to the lance */
         ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
index dcdad21..279ec62 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
@@ -822,7 +822,7 @@ config SMC91X
        tristate "SMC 91C9x/91C1xxx support"
        select CRC32
        select MII
-       depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00)
+       depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
        help
          This is a driver for SMC's 91x series of Ethernet chipsets,
          including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -833,8 +833,8 @@ config SMC91X
          This driver is also available as a module ( = code which can be
          inserted in and removed from the running kernel whenever you want).
          The module will be called smc91x.  If you want to compile it as a
-         module, say M here and read <file:Documentation/modules.txt> as well
-         as <file:Documentation/networking/net-modules.txt>.
+         module, say M here and read <file:Documentation/kbuild/modules.txt>
+         as well as <file:Documentation/networking/net-modules.txt>.
 
 config SMC9194
        tristate "SMC 9194 support"
@@ -889,7 +889,7 @@ config SMC911X
 
          This driver is also available as a module. The module will be 
          called smc911x.  If you want to compile it as a module, say M 
-         here and read <file:Documentation/modules.txt>
+         here and read <file:Documentation/kbuild/modules.txt>
 
 config NET_VENDOR_RACAL
        bool "Racal-Interlan (Micom) NI cards"
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 042e27e..b112317 100644 (file)
@@ -38,7 +38,7 @@
 #define DRV_VERSION "1.0-ko"
 
 /* Firmware version */
-#define FW_VERSION_MAJOR 3
-#define FW_VERSION_MINOR 3
+#define FW_VERSION_MAJOR 4
+#define FW_VERSION_MINOR 0
 #define FW_VERSION_MICRO 0
 #endif                         /* __CHELSIO_VERSION_H */
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 d2767e6..7053026 100644 (file)
 #define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
 
+#elif defined(CONFIG_BFIN)
+
+#define SMC_IRQ_FLAGS          IRQF_TRIGGER_HIGH
+
+# if defined (CONFIG_BFIN561_EZKIT)
+#define SMC_CAN_USE_8BIT       0
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+#define SMC_IO_SHIFT           0
+#define SMC_NOWAIT             1
+#define SMC_USE_BFIN_DMA       0
+
+
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_inl(a, r)          readl((a) + (r))
+#define SMC_outl(v, a, r)      writel(v, (a) + (r))
+#define SMC_outsl(a, r, p, l)  outsl((unsigned long *)((a) + (r)), p, l)
+#define SMC_insl(a, r, p, l)   insl ((unsigned long *)((a) + (r)), p, l)
+# else
+#define SMC_CAN_USE_8BIT       0
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      0
+#define SMC_IO_SHIFT           0
+#define SMC_NOWAIT             1
+#define SMC_USE_BFIN_DMA       0
+
+
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_outsw(a, r, p, l)  outsw((unsigned long *)((a) + (r)), p, l)
+#define SMC_insw(a, r, p, l)   insw ((unsigned long *)((a) + (r)), p, l)
+# endif
+/* check if the mac in reg is valid */
+#define SMC_GET_MAC_ADDR(addr)                                 \
+       do {                                                    \
+               unsigned int __v;                               \
+               __v = SMC_inw(ioaddr, ADDR0_REG);               \
+               addr[0] = __v; addr[1] = __v >> 8;              \
+               __v = SMC_inw(ioaddr, ADDR1_REG);               \
+               addr[2] = __v; addr[3] = __v >> 8;              \
+               __v = SMC_inw(ioaddr, ADDR2_REG);               \
+               addr[4] = __v; addr[5] = __v >> 8;              \
+               if (*(u32 *)(&addr[0]) == 0xFFFFFFFF) {         \
+                       random_ether_addr(addr);                \
+               }                                               \
+       } while (0)
 #elif defined(CONFIG_REDWOOD_5) || defined(CONFIG_REDWOOD_6)
 
 /* We can only do 16-bit reads and writes in the static memory space. */
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..e5e901e 100644 (file)
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.75"
-#define DRV_MODULE_RELDATE     "March 23, 2007"
+#define DRV_MODULE_VERSION     "3.76"
+#define DRV_MODULE_RELDATE     "May 5, 2007"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -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);
@@ -3021,6 +3019,16 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                }
        }
 
+       if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) {
+               u32 val = tr32(PCIE_PWR_MGMT_THRESH);
+               if (!netif_carrier_ok(tp->dev))
+                       val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
+                             tp->pwrmgmt_thresh;
+               else
+                       val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+               tw32(PCIE_PWR_MGMT_THRESH, val);
+       }
+
        return err;
 }
 
@@ -3582,8 +3590,12 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
         * Writing non-zero to intr-mbox-0 additional tells the
         * NIC to stop sending us irqs, engaging "in-intr-handler"
         * event coalescing.
+        *
+        * Flush the mailbox to de-assert the IRQ immediately to prevent
+        * spurious interrupts.  The flush impacts performance but
+        * excessive spurious interrupts can be worse in some cases.
         */
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
        if (tg3_irq_sync(tp))
                goto out;
        sblk->status &= ~SD_STATUS_UPDATED;
@@ -3627,8 +3639,12 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
         * writing non-zero to intr-mbox-0 additional tells the
         * NIC to stop sending us irqs, engaging "in-intr-handler"
         * event coalescing.
+        *
+        * Flush the mailbox to de-assert the IRQ immediately to prevent
+        * spurious interrupts.  The flush impacts performance but
+        * excessive spurious interrupts can be worse in some cases.
         */
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
        if (tg3_irq_sync(tp))
                goto out;
        if (netif_rx_schedule_prep(dev)) {
@@ -3895,8 +3911,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 +4068,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 +5948,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 +5960,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 +5988,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 +5999,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 +6330,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 +6361,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 +6471,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 +7051,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 +7410,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 +8045,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 +8062,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 +9300,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 +9419,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 +9452,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 +9533,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 +9546,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,14 +10014,16 @@ 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)) {
                        tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
                        tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
                }
+               if (tr32(VCPU_CFGSHDW) & VCPU_CFGSHDW_ASPM_DBNC)
+                       tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
                return;
        }
 
@@ -10120,8 +10140,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;
@@ -10130,6 +10151,14 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                /* bootcode if bit 18 is set */
                if (cfg2 & (1 << 18))
                        tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
+
+               if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+                       u32 cfg3;
+
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+                       if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)
+                               tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+               }
        }
 }
 
@@ -10399,6 +10428,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 +10585,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 +10602,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 +10711,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 +10734,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)) {
@@ -10983,6 +11026,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         */
        tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
 
+       if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND)
+               tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) &
+                                    PCIE_PWR_MGMT_L1_THRESH_MSK;
+
        return err;
 }
 
@@ -11892,10 +11939,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..4d334cf 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
 #define  VCPU_STATUS_INIT_DONE          0x04000000
 #define  VCPU_STATUS_DRV_RESET          0x08000000
 
+#define VCPU_CFGSHDW                   0x00005104
+#define  VCPU_CFGSHDW_ASPM_DBNC                 0x00001000
+
 /* Mailboxes */
 #define GRCMBOX_BASE                   0x00005600
 #define GRCMBOX_INTERRUPT_0            0x00005800 /* 64-bit */
 #define PCIE_TRANS_CFG_1SHOT_MSI        0x20000000
 #define PCIE_TRANS_CFG_LOM              0x00000020
 
+#define PCIE_PWR_MGMT_THRESH           0x00007d28
+#define PCIE_PWR_MGMT_L1_THRESH_MSK     0x0000ff00
 
 #define TG3_EEPROM_MAGIC               0x669955aa
 #define TG3_EEPROM_MAGIC_FW            0xa5000000
 #define  SHASTA_EXT_LED_MAC             0x00010000
 #define  SHASTA_EXT_LED_COMBO           0x00018000
 
+#define NIC_SRAM_DATA_CFG_3            0x00000d3c
+#define  NIC_SRAM_ASPM_DEBOUNCE                 0x00000002
+
 #define NIC_SRAM_RX_MINI_BUFFER_DESC   0x00001000
 
 #define NIC_SRAM_DMA_DESC_POOL_BASE    0x00002000
@@ -2199,7 +2208,7 @@ 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_ASPM_WORKAROUND       0x00000040
 #define TG3_FLAG_POLL_SERDES           0x00000080
 #define TG3_FLAG_MBOX_WRITE_REORDER    0x00000100
 #define TG3_FLAG_PCIX_TARGET_HWBUG     0x00000200
@@ -2215,14 +2224,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;
@@ -2288,6 +2297,7 @@ struct tg3 {
        u32                             grc_local_ctrl;
        u32                             dma_rwctrl;
        u32                             coalesce_mode;
+       u32                             pwrmgmt_thresh;
 
        /* PCI block */
        u16                             pci_chip_rev_id;
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 c4b3dc2..0184614 100644 (file)
@@ -153,8 +153,8 @@ config IPW2100
  
           If you want to compile the driver as a module ( = code which can be
           inserted in and removed from the running kernel whenever you want),
-          say M here and read <file:Documentation/modules.txt>.  The module
-          will be called ipw2100.ko.
+          say M here and read <file:Documentation/kbuild/modules.txt>.
+          The module will be called ipw2100.ko.
        
 config IPW2100_MONITOR
         bool "Enable promiscuous mode"
@@ -208,8 +208,8 @@ config IPW2200
  
           If you want to compile the driver as a module ( = code which can be
           inserted in and removed from the running kernel whenever you want),
-          say M here and read <file:Documentation/modules.txt>.  The module
-          will be called ipw2200.ko.
+          say M here and read <file:Documentation/kbuild/modules.txt>.
+          The module will be called ipw2200.ko.
 
 config IPW2200_MONITOR
         bool "Enable promiscuous mode"
@@ -517,8 +517,8 @@ config PRISM54
          
          If you want to compile the driver as a module ( = code which can be
          inserted in and removed from the running kernel whenever you want),
-         say M here and read <file:Documentation/modules.txt>.  The module
-         will be called prism54.ko.
+         say M here and read <file:Documentation/kbuild/modules.txt>.
+         The module will be called prism54.ko.
 
 config USB_ZD1201
        tristate "USB ZD1201 based Wireless device support"
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 99baabc..948efc7 100644 (file)
@@ -360,7 +360,6 @@ static struct platform_driver at91_cf_driver = {
                .name           = (char *) driver_name,
                .owner          = THIS_MODULE,
        },
-       .probe          = at91_cf_probe,
        .remove         = __exit_p(at91_cf_remove),
        .suspend        = at91_cf_suspend,
        .resume         = at91_cf_resume,
@@ -370,7 +369,7 @@ static struct platform_driver at91_cf_driver = {
 
 static int __init at91_cf_init(void)
 {
-       return platform_driver_register(&at91_cf_driver);
+       return platform_driver_probe(&at91_cf_driver, at91_cf_probe);
 }
 module_init(at91_cf_init);
 
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 18e111e..143c6ef 100644 (file)
@@ -234,6 +234,89 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
 /*======================================================================*/
 
 
+struct pcmcia_dynid {
+       struct list_head                node;
+       struct pcmcia_device_id         id;
+};
+
+/**
+ * pcmcia_store_new_id - add a new PCMCIA device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
+ *
+ * Adds a new dynamic PCMCIA device ID to this driver,
+ * and causes the driver to probe for all devices again.
+ */
+static ssize_t
+pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count)
+{
+       struct pcmcia_dynid *dynid;
+       struct pcmcia_driver *pdrv = to_pcmcia_drv(driver);
+       __u16 match_flags, manf_id, card_id;
+       __u8 func_id, function, device_no;
+       __u32 prod_id_hash[4] = {0, 0, 0, 0};
+       int fields=0;
+       int retval = 0;
+
+       fields = sscanf(buf, "%hx %hx %hx %hhx %hhx %hhx %x %x %x %x",
+                       &match_flags, &manf_id, &card_id, &func_id, &function, &device_no,
+                       &prod_id_hash[0], &prod_id_hash[1], &prod_id_hash[2], &prod_id_hash[3]);
+       if (fields < 6)
+               return -EINVAL;
+
+       dynid = kzalloc(sizeof(struct pcmcia_dynid), GFP_KERNEL);
+       if (!dynid)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&dynid->node);
+       dynid->id.match_flags = match_flags;
+       dynid->id.manf_id = manf_id;
+       dynid->id.card_id = card_id;
+       dynid->id.func_id = func_id;
+       dynid->id.function = function;
+       dynid->id.device_no = device_no;
+       memcpy(dynid->id.prod_id_hash, prod_id_hash, sizeof(__u32) * 4);
+
+       spin_lock(&pdrv->dynids.lock);
+       list_add_tail(&pdrv->dynids.list, &dynid->node);
+       spin_unlock(&pdrv->dynids.lock);
+
+       if (get_driver(&pdrv->drv)) {
+               retval = driver_attach(&pdrv->drv);
+               put_driver(&pdrv->drv);
+       }
+
+       if (retval)
+               return retval;
+       return count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, pcmcia_store_new_id);
+
+static void
+pcmcia_free_dynids(struct pcmcia_driver *drv)
+{
+       struct pcmcia_dynid *dynid, *n;
+
+       spin_lock(&drv->dynids.lock);
+       list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
+               list_del(&dynid->node);
+               kfree(dynid);
+       }
+       spin_unlock(&drv->dynids.lock);
+}
+
+static int
+pcmcia_create_newid_file(struct pcmcia_driver *drv)
+{
+       int error = 0;
+       if (drv->probe != NULL)
+               error = sysfs_create_file(&drv->drv.kobj,
+                                         &driver_attr_new_id.attr);
+       return error;
+}
+
+
 /**
  * pcmcia_register_driver - register a PCMCIA driver with the bus core
  *
@@ -241,6 +324,8 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
  */
 int pcmcia_register_driver(struct pcmcia_driver *driver)
 {
+       int error;
+
        if (!driver)
                return -EINVAL;
 
@@ -249,10 +334,20 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
        /* initialize common fields */
        driver->drv.bus = &pcmcia_bus_type;
        driver->drv.owner = driver->owner;
+       spin_lock_init(&driver->dynids.lock);
+       INIT_LIST_HEAD(&driver->dynids.list);
 
        ds_dbg(3, "registering driver %s\n", driver->drv.name);
 
-       return driver_register(&driver->drv);
+       error = driver_register(&driver->drv);
+       if (error < 0)
+               return error;
+
+       error = pcmcia_create_newid_file(driver);
+       if (error)
+               driver_unregister(&driver->drv);
+
+       return error;
 }
 EXPORT_SYMBOL(pcmcia_register_driver);
 
@@ -263,6 +358,7 @@ void pcmcia_unregister_driver(struct pcmcia_driver *driver)
 {
        ds_dbg(3, "unregistering driver %s\n", driver->drv.name);
        driver_unregister(&driver->drv);
+       pcmcia_free_dynids(driver);
 }
 EXPORT_SYMBOL(pcmcia_unregister_driver);
 
@@ -927,6 +1023,21 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
        struct pcmcia_device * p_dev = to_pcmcia_dev(dev);
        struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
        struct pcmcia_device_id *did = p_drv->id_table;
+       struct pcmcia_dynid *dynid;
+
+       /* match dynamic devices first */
+       spin_lock(&p_drv->dynids.lock);
+       list_for_each_entry(dynid, &p_drv->dynids.list, node) {
+               ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
+                      drv->name);
+               if (pcmcia_devmatch(p_dev, &dynid->id)) {
+                       ds_dbg(0, "matched %s to %s\n", dev->bus_id,
+                              drv->name);
+                       spin_unlock(&p_drv->dynids.lock);
+                       return 1;
+               }
+       }
+       spin_unlock(&p_drv->dynids.lock);
 
 #ifdef CONFIG_PCMCIA_IOCTL
        /* matching by cardmgr */
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 95826b9..ef1eae9 100644 (file)
@@ -354,4 +354,14 @@ config RTC_DRV_V3020
          This driver can also be built as a module. If so, the module
          will be called rtc-v3020.
 
+config RTC_DRV_BFIN
+       tristate "Blackfin On-Chip RTC"
+       depends on RTC_CLASS && BFIN
+       help
+         If you say yes here you will get support for the
+         Blackfin On-Chip Real Time Clock.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-bfin.
+
 endmenu
index 92bfe1b..9218cf2 100644 (file)
@@ -38,3 +38,4 @@ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
+obj-$(CONFIG_RTC_DRV_BFIN)     += rtc-bfin.o
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
new file mode 100644 (file)
index 0000000..260ead9
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Blackfin On-Chip Real Time Clock Driver
+ *  Supports BF531/BF532/BF533/BF534/BF536/BF537
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+/* The biggest issue we deal with in this driver is that register writes are
+ * synced to the RTC frequency of 1Hz.  So if you write to a register and
+ * attempt to write again before the first write has completed, the new write
+ * is simply discarded.  This can easily be troublesome if userspace disables
+ * one event (say periodic) and then right after enables an event (say alarm).
+ * Since all events are maintained in the same interrupt mask register, if
+ * we wrote to it to disable the first event and then wrote to it again to
+ * enable the second event, that second event would not be enabled as the
+ * write would be discarded and things quickly fall apart.
+ *
+ * To keep this delay from significantly degrading performance (we, in theory,
+ * would have to sleep for up to 1 second everytime we wanted to write a
+ * register), we only check the write pending status before we start to issue
+ * a new write.  We bank on the idea that it doesnt matter when the sync
+ * happens so long as we don't attempt another write before it does.  The only
+ * time userspace would take this penalty is when they try and do multiple
+ * operations right after another ... but in this case, they need to take the
+ * sync penalty, so we should be OK.
+ *
+ * Also note that the RTC_ISTAT register does not suffer this penalty; its
+ * writes to clear status registers complete immediately.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include <asm/blackfin.h>
+
+#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __FUNCTION__, __LINE__, ## args)
+#define stampit() stamp("here i am")
+
+struct bfin_rtc {
+       struct rtc_device *rtc_dev;
+       struct rtc_time rtc_alarm;
+       spinlock_t lock;
+};
+
+/* Bit values for the ISTAT / ICTL registers */
+#define RTC_ISTAT_WRITE_COMPLETE  0x8000
+#define RTC_ISTAT_WRITE_PENDING   0x4000
+#define RTC_ISTAT_ALARM_DAY       0x0040
+#define RTC_ISTAT_24HR            0x0020
+#define RTC_ISTAT_HOUR            0x0010
+#define RTC_ISTAT_MIN             0x0008
+#define RTC_ISTAT_SEC             0x0004
+#define RTC_ISTAT_ALARM           0x0002
+#define RTC_ISTAT_STOPWATCH       0x0001
+
+/* Shift values for RTC_STAT register */
+#define DAY_BITS_OFF    17
+#define HOUR_BITS_OFF   12
+#define MIN_BITS_OFF    6
+#define SEC_BITS_OFF    0
+
+/* Some helper functions to convert between the common RTC notion of time
+ * and the internal Blackfin notion that is stored in 32bits.
+ */
+static inline u32 rtc_time_to_bfin(unsigned long now)
+{
+       u32 sec  = (now % 60);
+       u32 min  = (now % (60 * 60)) / 60;
+       u32 hour = (now % (60 * 60 * 24)) / (60 * 60);
+       u32 days = (now / (60 * 60 * 24));
+       return (sec  << SEC_BITS_OFF) +
+              (min  << MIN_BITS_OFF) +
+              (hour << HOUR_BITS_OFF) +
+              (days << DAY_BITS_OFF);
+}
+static inline unsigned long rtc_bfin_to_time(u32 rtc_bfin)
+{
+       return (((rtc_bfin >> SEC_BITS_OFF)  & 0x003F)) +
+              (((rtc_bfin >> MIN_BITS_OFF)  & 0x003F) * 60) +
+              (((rtc_bfin >> HOUR_BITS_OFF) & 0x001F) * 60 * 60) +
+              (((rtc_bfin >> DAY_BITS_OFF)  & 0x7FFF) * 60 * 60 * 24);
+}
+static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm)
+{
+       rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm);
+}
+
+/* Wait for the previous write to a RTC register to complete.
+ * Unfortunately, we can't sleep here as that introduces a race condition when
+ * turning on interrupt events.  Consider this:
+ *  - process sets alarm
+ *  - process enables alarm
+ *  - process sleeps while waiting for rtc write to sync
+ *  - interrupt fires while process is sleeping
+ *  - interrupt acks the event by writing to ISTAT
+ *  - interrupt sets the WRITE PENDING bit
+ *  - interrupt handler finishes
+ *  - process wakes up, sees WRITE PENDING bit set, goes to sleep
+ *  - interrupt fires while process is sleeping
+ * If anyone can point out the obvious solution here, i'm listening :).  This
+ * shouldn't be an issue on an SMP or preempt system as this function should
+ * only be called with the rtc lock held.
+ */
+static void rtc_bfin_sync_pending(void)
+{
+       stampit();
+       while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) {
+               if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING))
+                       break;
+       }
+       bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE);
+}
+
+static void rtc_bfin_reset(struct bfin_rtc *rtc)
+{
+       /* Initialize the RTC. Enable pre-scaler to scale RTC clock
+        * to 1Hz and clear interrupt/status registers. */
+       spin_lock_irq(&rtc->lock);
+       rtc_bfin_sync_pending();
+       bfin_write_RTC_PREN(0x1);
+       bfin_write_RTC_ICTL(0);
+       bfin_write_RTC_SWCNT(0);
+       bfin_write_RTC_ALARM(0);
+       bfin_write_RTC_ISTAT(0xFFFF);
+       spin_unlock_irq(&rtc->lock);
+}
+
+static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id)
+{
+       struct platform_device *pdev = to_platform_device(dev_id);
+       struct bfin_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned long events = 0;
+       u16 rtc_istat;
+
+       stampit();
+
+       spin_lock_irq(&rtc->lock);
+
+       rtc_istat = bfin_read_RTC_ISTAT();
+
+       if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) {
+               bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY);
+               events |= RTC_AF | RTC_IRQF;
+       }
+
+       if (rtc_istat & RTC_ISTAT_STOPWATCH) {
+               bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
+               events |= RTC_PF | RTC_IRQF;
+               bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
+       }
+
+       if (rtc_istat & RTC_ISTAT_SEC) {
+               bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
+               events |= RTC_UF | RTC_IRQF;
+       }
+
+       rtc_update_irq(rtc->rtc_dev, 1, events);
+
+       spin_unlock_irq(&rtc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int bfin_rtc_open(struct device *dev)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+       int ret;
+
+       stampit();
+
+       ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_DISABLED, "rtc-bfin", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request RTC IRQ failed with %d\n", ret);
+               return ret;
+       }
+
+       rtc_bfin_reset(rtc);
+
+       return ret;
+}
+
+static void bfin_rtc_release(struct device *dev)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+       stampit();
+       rtc_bfin_reset(rtc);
+       free_irq(IRQ_RTC, dev);
+}
+
+static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+
+       stampit();
+
+       switch (cmd) {
+       case RTC_PIE_ON:
+               stampit();
+               spin_lock_irq(&rtc->lock);
+               rtc_bfin_sync_pending();
+               bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
+               bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
+               bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_STOPWATCH);
+               spin_unlock_irq(&rtc->lock);
+               return 0;
+       case RTC_PIE_OFF:
+               stampit();
+               spin_lock_irq(&rtc->lock);
+               rtc_bfin_sync_pending();
+               bfin_write_RTC_SWCNT(0);
+               bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_STOPWATCH);
+               spin_unlock_irq(&rtc->lock);
+               return 0;
+
+       case RTC_UIE_ON:
+               stampit();
+               spin_lock_irq(&rtc->lock);
+               rtc_bfin_sync_pending();
+               bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
+               bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_SEC);
+               spin_unlock_irq(&rtc->lock);
+               return 0;
+       case RTC_UIE_OFF:
+               stampit();
+               spin_lock_irq(&rtc->lock);
+               rtc_bfin_sync_pending();
+               bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_SEC);
+               spin_unlock_irq(&rtc->lock);
+               return 0;
+
+       case RTC_AIE_ON: {
+               unsigned long rtc_alarm;
+               u16 which_alarm;
+               int ret = 0;
+
+               stampit();
+
+               spin_lock_irq(&rtc->lock);
+
+               rtc_bfin_sync_pending();
+               if (rtc->rtc_alarm.tm_yday == -1) {
+                       struct rtc_time now;
+                       rtc_bfin_to_tm(bfin_read_RTC_STAT(), &now);
+                       now.tm_sec = rtc->rtc_alarm.tm_sec;
+                       now.tm_min = rtc->rtc_alarm.tm_min;
+                       now.tm_hour = rtc->rtc_alarm.tm_hour;
+                       ret = rtc_tm_to_time(&now, &rtc_alarm);
+                       which_alarm = RTC_ISTAT_ALARM;
+               } else {
+                       ret = rtc_tm_to_time(&rtc->rtc_alarm, &rtc_alarm);
+                       which_alarm = RTC_ISTAT_ALARM_DAY;
+               }
+               if (ret == 0) {
+                       bfin_write_RTC_ISTAT(which_alarm);
+                       bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm));
+                       bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | which_alarm);
+               }
+
+               spin_unlock_irq(&rtc->lock);
+
+               return ret;
+       }
+       case RTC_AIE_OFF:
+               stampit();
+               spin_lock_irq(&rtc->lock);
+               rtc_bfin_sync_pending();
+               bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+               spin_unlock_irq(&rtc->lock);
+               return 0;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+
+       stampit();
+
+       spin_lock_irq(&rtc->lock);
+       rtc_bfin_sync_pending();
+       rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm);
+       spin_unlock_irq(&rtc->lock);
+
+       return 0;
+}
+
+static int bfin_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+       int ret;
+       unsigned long now;
+
+       stampit();
+
+       spin_lock_irq(&rtc->lock);
+
+       ret = rtc_tm_to_time(tm, &now);
+       if (ret == 0) {
+               rtc_bfin_sync_pending();
+               bfin_write_RTC_STAT(rtc_time_to_bfin(now));
+       }
+
+       spin_unlock_irq(&rtc->lock);
+
+       return ret;
+}
+
+static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+       stampit();
+       memcpy(&alrm->time, &rtc->rtc_alarm, sizeof(struct rtc_time));
+       alrm->pending = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+       return 0;
+}
+
+static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+       stampit();
+       memcpy(&rtc->rtc_alarm, &alrm->time, sizeof(struct rtc_time));
+       return 0;
+}
+
+static int bfin_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+#define yesno(x) (x ? "yes" : "no")
+       u16 ictl = bfin_read_RTC_ICTL();
+       stampit();
+       seq_printf(seq, "alarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM));
+       seq_printf(seq, "wkalarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM_DAY));
+       seq_printf(seq, "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_SEC));
+       seq_printf(seq, "periodic_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_STOPWATCH));
+#ifdef DEBUG
+       seq_printf(seq, "RTC_STAT\t: 0x%08X\n", bfin_read_RTC_STAT());
+       seq_printf(seq, "RTC_ICTL\t: 0x%04X\n", bfin_read_RTC_ICTL());
+       seq_printf(seq, "RTC_ISTAT\t: 0x%04X\n", bfin_read_RTC_ISTAT());
+       seq_printf(seq, "RTC_SWCNT\t: 0x%04X\n", bfin_read_RTC_SWCNT());
+       seq_printf(seq, "RTC_ALARM\t: 0x%08X\n", bfin_read_RTC_ALARM());
+       seq_printf(seq, "RTC_PREN\t: 0x%04X\n", bfin_read_RTC_PREN());
+#endif
+       return 0;
+}
+
+static int bfin_irq_set_freq(struct device *dev, int freq)
+{
+       struct bfin_rtc *rtc = dev_get_drvdata(dev);
+       stampit();
+       rtc->rtc_dev->irq_freq = freq;
+       return 0;
+}
+
+static struct rtc_class_ops bfin_rtc_ops = {
+       .open          = bfin_rtc_open,
+       .release       = bfin_rtc_release,
+       .ioctl         = bfin_rtc_ioctl,
+       .read_time     = bfin_rtc_read_time,
+       .set_time      = bfin_rtc_set_time,
+       .read_alarm    = bfin_rtc_read_alarm,
+       .set_alarm     = bfin_rtc_set_alarm,
+       .proc          = bfin_rtc_proc,
+       .irq_set_freq  = bfin_irq_set_freq,
+};
+
+static int __devinit bfin_rtc_probe(struct platform_device *pdev)
+{
+       struct bfin_rtc *rtc;
+       int ret = 0;
+
+       stampit();
+
+       rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+       if (unlikely(!rtc))
+               return -ENOMEM;
+
+       spin_lock_init(&rtc->lock);
+
+       rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE);
+       if (unlikely(IS_ERR(rtc))) {
+               ret = PTR_ERR(rtc->rtc_dev);
+               goto err;
+       }
+       rtc->rtc_dev->irq_freq = 0;
+       rtc->rtc_dev->max_user_freq = (2 << 16); /* stopwatch is an unsigned 16 bit reg */
+
+       platform_set_drvdata(pdev, rtc);
+
+       return 0;
+
+err:
+       kfree(rtc);
+       return ret;
+}
+
+static int __devexit bfin_rtc_remove(struct platform_device *pdev)
+{
+       struct bfin_rtc *rtc = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(rtc->rtc_dev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(rtc);
+
+       return 0;
+}
+
+static struct platform_driver bfin_rtc_driver = {
+       .driver         = {
+               .name   = "rtc-bfin",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = bfin_rtc_probe,
+       .remove         = __devexit_p(bfin_rtc_remove),
+};
+
+static int __init bfin_rtc_init(void)
+{
+       stampit();
+       return platform_driver_register(&bfin_rtc_driver);
+}
+
+static void __exit bfin_rtc_exit(void)
+{
+       platform_driver_unregister(&bfin_rtc_driver);
+}
+
+module_init(bfin_rtc_init);
+module_exit(bfin_rtc_exit);
+
+MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver");
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_LICENSE("GPL");
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 fcc4cb6..e62d23f 100644 (file)
@@ -170,7 +170,7 @@ config CHR_DEV_SCH
        
          If you want to compile this as a module ( = code which can be
          inserted in and removed from the running kernel whenever you want),
-         say M here and read <file:Documentation/modules.txt> and
+         say M here and read <file:Documentation/kbuild/modules.txt> and
          <file:Documentation/scsi.txt>. The module will be called ch.o.
          If unsure, say N.
        
@@ -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,
@@ -1793,7 +1783,7 @@ config ZFCP
 
           This driver is also available as a module. This module will be
           called zfcp. If you want to compile it as a module, say M here
-          and read <file:Documentation/modules.txt>.
+          and read <file:Documentation/kbuild/modules.txt>.
 
 config SCSI_SRP
        tristate "SCSI RDMA Protocol helper library"
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 99ce033..ec71061 100644 (file)
@@ -2212,7 +2212,7 @@ static void __devinit esp_init_swstate(struct esp *esp)
 }
 
 /* This places the ESP into a known state at boot time. */
-static void __devinit esp_bootup_reset(struct esp *esp)
+static void esp_bootup_reset(struct esp *esp)
 {
        u8 val;
 
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 8c766bc..bbeb245 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
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 90621c3..c9832d9 100644 (file)
@@ -251,9 +251,16 @@ static const struct serial8250_config uart_config[] = {
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
                .flags          = UART_CAP_FIFO | UART_CAP_UUE,
        },
+       [PORT_RM9000] = {
+               .name           = "RM9000",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO,
+       },
 };
 
-#ifdef CONFIG_SERIAL_8250_AU1X00
+#if defined (CONFIG_SERIAL_8250_AU1X00)
 
 /* Au1x00 UART hardware has a weird register layout */
 static const u8 au_io_in_map[] = {
@@ -289,6 +296,44 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
        return au_io_out_map[offset];
 }
 
+#elif defined (CONFIG_SERIAL_8250_RM9K)
+
+static const u8
+       regmap_in[8] = {
+               [UART_RX]       = 0x00,
+               [UART_IER]      = 0x0c,
+               [UART_IIR]      = 0x14,
+               [UART_LCR]      = 0x1c,
+               [UART_MCR]      = 0x20,
+               [UART_LSR]      = 0x24,
+               [UART_MSR]      = 0x28,
+               [UART_SCR]      = 0x2c
+       },
+       regmap_out[8] = {
+               [UART_TX]       = 0x04,
+               [UART_IER]      = 0x0c,
+               [UART_FCR]      = 0x18,
+               [UART_LCR]      = 0x1c,
+               [UART_MCR]      = 0x20,
+               [UART_LSR]      = 0x24,
+               [UART_MSR]      = 0x28,
+               [UART_SCR]      = 0x2c
+       };
+
+static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+{
+       if (up->port.iotype != UPIO_RM9000)
+               return offset;
+       return regmap_in[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+{
+       if (up->port.iotype != UPIO_RM9000)
+               return offset;
+       return regmap_out[offset];
+}
+
 #else
 
 /* sane hardware needs no mapping */
@@ -308,8 +353,10 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset)
                return inb(up->port.iobase + 1);
 
        case UPIO_MEM:
+       case UPIO_DWAPB:
                return readb(up->port.membase + offset);
 
+       case UPIO_RM9000:
        case UPIO_MEM32:
                return readl(up->port.membase + offset);
 
@@ -333,6 +380,8 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset)
 static void
 serial_out(struct uart_8250_port *up, int offset, int value)
 {
+       /* Save the offset before it's remapped */
+       int save_offset = offset;
        offset = map_8250_out_reg(up, offset) << up->port.regshift;
 
        switch (up->port.iotype) {
@@ -345,6 +394,7 @@ serial_out(struct uart_8250_port *up, int offset, int value)
                writeb(value, up->port.membase + offset);
                break;
 
+       case UPIO_RM9000:
        case UPIO_MEM32:
                writel(value, up->port.membase + offset);
                break;
@@ -359,6 +409,18 @@ serial_out(struct uart_8250_port *up, int offset, int value)
                        writeb(value, up->port.membase + offset);
                break;
 
+       case UPIO_DWAPB:
+               /* Save the LCR value so it can be re-written when a
+                * Busy Detect interrupt occurs. */
+               if (save_offset == UART_LCR)
+                       up->lcr = value;
+               writeb(value, up->port.membase + offset);
+               /* Read the IER to ensure any interrupt is cleared before
+                * returning from ISR. */
+               if (save_offset == UART_TX || save_offset == UART_IER)
+                       value = serial_in(up, UART_IER);
+               break;
+
        default:
                outb(value, up->port.iobase + offset);
        }
@@ -373,6 +435,7 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value)
 #ifdef CONFIG_SERIAL_8250_AU1X00
        case UPIO_AU:
 #endif
+       case UPIO_DWAPB:
                serial_out(up, offset, value);
                serial_in(up, UART_LCR);        /* safe, no side-effects */
                break;
@@ -403,7 +466,7 @@ static inline void _serial_dl_write(struct uart_8250_port *up, int value)
        serial_outp(up, UART_DLM, value >> 8 & 0xff);
 }
 
-#ifdef CONFIG_SERIAL_8250_AU1X00
+#if defined (CONFIG_SERIAL_8250_AU1X00)
 /* Au1x00 haven't got a standard divisor latch */
 static int serial_dl_read(struct uart_8250_port *up)
 {
@@ -420,6 +483,24 @@ static void serial_dl_write(struct uart_8250_port *up, int value)
        else
                _serial_dl_write(up, value);
 }
+#elif defined (CONFIG_SERIAL_8250_RM9K)
+static int serial_dl_read(struct uart_8250_port *up)
+{
+       return  (up->port.iotype == UPIO_RM9000) ?
+               (((__raw_readl(up->port.membase + 0x10) << 8) |
+               (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+               _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+       if (up->port.iotype == UPIO_RM9000) {
+               __raw_writel(value, up->port.membase + 0x08);
+               __raw_writel(value >> 8, up->port.membase + 0x10);
+       } else {
+               _serial_dl_write(up, value);
+       }
+}
 #else
 #define serial_dl_read(up) _serial_dl_read(up)
 #define serial_dl_write(up, value) _serial_dl_write(up, value)
@@ -621,7 +702,7 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
  * its clones.  (We treat the broken original StarTech 16650 V1 as a
  * 16550, and why not?  Startech doesn't seem to even acknowledge its
  * existence.)
- * 
+ *
  * What evil have men's minds wrought...
  */
 static void autoconfig_has_efr(struct uart_8250_port *up)
@@ -674,7 +755,7 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
                        up->bugs |= UART_BUG_QUOT;
                return;
        }
-       
+
        /*
         * We check for a XR16C850 by setting DLL and DLM to 0, and then
         * reading back DLL and DLM.  The chip type depends on the DLM
@@ -817,7 +898,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
                        status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
                        status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
                        serial_outp(up, 0x04, status1);
-                       
+
                        serial_dl_write(up, quot);
 
                        serial_outp(up, UART_LCR, 0);
@@ -922,7 +1003,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
                /*
                 * Do a simple existence test first; if we fail this,
                 * there's no point trying anything else.
-                * 
+                *
                 * 0x80 is used as a nonsense port to prevent against
                 * false positives due to ISA bus float.  The
                 * assumption is that 0x80 is a non-existent port;
@@ -961,7 +1042,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        save_mcr = serial_in(up, UART_MCR);
        save_lcr = serial_in(up, UART_LCR);
 
-       /* 
+       /*
         * Check to see if a UART is really there.  Certain broken
         * internal modems based on the Rockwell chipset fail this
         * test, because they apparently don't implement the loopback
@@ -1068,7 +1149,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        else
                serial_outp(up, UART_IER, 0);
 
- out:  
+ out:
        spin_unlock_irqrestore(&up->port.lock, flags);
 //     restore_flags(flags);
        DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
@@ -1094,7 +1175,7 @@ static void autoconfig_irq(struct uart_8250_port *up)
        save_mcr = serial_inp(up, UART_MCR);
        save_ier = serial_inp(up, UART_IER);
        serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-       
+
        irqs = probe_irq_on();
        serial_outp(up, UART_MCR, 0);
        udelay (10);
@@ -1159,8 +1240,11 @@ static void serial8250_start_tx(struct uart_port *port)
                if (up->bugs & UART_BUG_TXEN) {
                        unsigned char lsr, iir;
                        lsr = serial_in(up, UART_LSR);
-                       iir = serial_in(up, UART_IIR);
-                       if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
+                       iir = serial_in(up, UART_IIR) & 0x0f;
+                       if ((up->port.type == PORT_RM9000) ?
+                               (lsr & UART_LSR_THRE &&
+                               (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
+                               (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
                                transmit_chars(up);
                }
        }
@@ -1388,6 +1472,19 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 
                        handled = 1;
 
+                       end = NULL;
+               } else if (up->port.iotype == UPIO_DWAPB &&
+                         (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+                       /* The DesignWare APB UART has an Busy Detect (0x07)
+                        * interrupt meaning an LCR write attempt occured while the
+                        * UART was busy. The interrupt must be cleared by reading
+                        * the UART status register (USR) and the LCR re-written. */
+                       unsigned int status;
+                       status = *(volatile u32 *)up->port.private_data;
+                       serial_out(up, UART_LCR, up->lcr);
+
+                       handled = 1;
+
                        end = NULL;
                } else if (end == NULL)
                        end = l;
@@ -1928,7 +2025,7 @@ serial8250_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, port->uartclk/16);
        quot = serial8250_get_divisor(port, baud);
 
        /*
@@ -2090,6 +2187,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
        case UPIO_TSI:
        case UPIO_MEM32:
        case UPIO_MEM:
+       case UPIO_DWAPB:
                if (!up->port.mapbase)
                        break;
 
@@ -2127,6 +2225,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
        case UPIO_TSI:
        case UPIO_MEM32:
        case UPIO_MEM:
+       case UPIO_DWAPB:
                if (!up->port.mapbase)
                        break;
 
index ad9f321..924e9bd 100644 (file)
@@ -254,6 +254,15 @@ config SERIAL_8250_AU1X00
          to this option.  The driver can handle 1 or 2 serial ports.
          If unsure, say N.
 
+config SERIAL_8250_RM9K
+       bool "Support for MIPS RM9xxx integrated serial port"
+       depends on SERIAL_8250 != n && SERIAL_RM9000
+       select SERIAL_8250_SHARE_IRQ
+       help
+         Selecting this option will add support for the integrated serial
+         port hardware found on MIPS RM9122 and similar processors.
+         If unsure, say N.
+
 comment "Non-8250 serial port support"
 
 config SERIAL_AMBA_PL010
@@ -499,6 +508,100 @@ config SERIAL_SA1100_CONSOLE
          your boot loader (lilo or loadlin) about how to pass options to the
          kernel at boot time.)
 
+config SERIAL_BFIN
+       tristate "Blackfin serial port support"
+       depends on BFIN
+       select SERIAL_CORE
+       select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561)
+       help
+         Add support for the built-in UARTs on the Blackfin.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bfin_5xx.
+
+config SERIAL_BFIN_CONSOLE
+       bool "Console on Blackfin serial port"
+       depends on SERIAL_BFIN
+       select SERIAL_CORE_CONSOLE
+
+choice
+       prompt "UART Mode"
+       depends on SERIAL_BFIN
+       default SERIAL_BFIN_DMA
+       help
+         This driver supports the built-in serial ports of the Blackfin family
+         of CPUs
+
+config SERIAL_BFIN_DMA
+       bool "DMA mode"
+       depends on DMA_UNCACHED_1M
+       help
+         This driver works under DMA mode. If this option is selected, the
+         blackfin simple dma driver is also enabled.
+
+config SERIAL_BFIN_PIO
+       bool "PIO mode"
+       help
+         This driver works under PIO mode.
+
+endchoice
+
+config SERIAL_BFIN_UART0
+       bool "Enable UART0"
+       depends on SERIAL_BFIN
+       help
+         Enable UART0
+
+config BFIN_UART0_CTSRTS
+       bool "Enable UART0 hardware flow control"
+       depends on SERIAL_BFIN_UART0
+       help
+         Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+         signal.
+
+config UART0_CTS_PIN
+       int "UART0 CTS pin"
+       depends on BFIN_UART0_CTSRTS
+       default 23
+       help
+         The default pin is GPIO_GP7.
+         Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config UART0_RTS_PIN
+       int "UART0 RTS pin"
+       depends on BFIN_UART0_CTSRTS
+       default 22
+       help
+         The default pin is GPIO_GP6.
+         Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config SERIAL_BFIN_UART1
+       bool "Enable UART1"
+       depends on SERIAL_BFIN && (BF534 || BF536 || BF537)
+       help
+         Enable UART1
+
+config BFIN_UART1_CTSRTS
+       bool "Enable UART1 hardware flow control"
+       depends on SERIAL_BFIN_UART1
+       help
+         Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+         signal.
+
+config UART1_CTS_PIN
+       int "UART1 CTS pin"
+       depends on BFIN_UART1_CTSRTS
+       default -1
+       help
+         Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config UART1_RTS_PIN
+       int "UART1 RTS pin"
+       depends on BFIN_UART1_CTSRTS
+       default -1
+       help
+         Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
 config SERIAL_IMX
        bool "IMX serial port support"
        depends on ARM && ARCH_IMX
index 6b3560c..4959bcb 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
 obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
 obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
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)
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
new file mode 100644 (file)
index 0000000..408390f
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+ * File:         drivers/serial/bfin_5xx.c
+ * Based on:     Based on drivers/serial/sa1100.c
+ * Author:       Aubrey Li <aubrey.li@analog.com>
+ *
+ * Created:
+ * Description:  Driver for blackfin 5xx serial ports
+ *
+ * Rev:          $Id: bfin_5xx.c,v 1.19 2006/09/24 02:33:53 aubrey Exp $
+ *
+ * Modified:
+ *               Copyright 2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+
+#include <asm/gpio.h>
+#include <asm/mach/bfin_serial_5xx.h>
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/cacheflush.h>
+#endif
+
+/* UART name and device definitions */
+#define BFIN_SERIAL_NAME       "ttyBF"
+#define BFIN_SERIAL_MAJOR      204
+#define BFIN_SERIAL_MINOR      64
+
+/*
+ * Setup for console. Argument comes from the menuconfig
+ */
+#define DMA_RX_XCOUNT          512
+#define DMA_RX_YCOUNT          (PAGE_SIZE / DMA_RX_XCOUNT)
+
+#define DMA_RX_FLUSH_JIFFIES   5
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart);
+#else
+static void bfin_serial_do_work(struct work_struct *work);
+static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
+static void local_put_char(struct bfin_serial_port *uart, char ch);
+#endif
+
+static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
+
+/*
+ * interrupts are disabled on entry
+ */
+static void bfin_serial_stop_tx(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       disable_dma(uart->tx_dma_channel);
+#else
+       unsigned short ier;
+
+       ier = UART_GET_IER(uart);
+       ier &= ~ETBEI;
+       UART_PUT_IER(uart, ier);
+#endif
+}
+
+/*
+ * port is locked and interrupts are disabled
+ */
+static void bfin_serial_start_tx(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       bfin_serial_dma_tx_chars(uart);
+#else
+       unsigned short ier;
+       ier = UART_GET_IER(uart);
+       ier |= ETBEI;
+       UART_PUT_IER(uart, ier);
+       bfin_serial_tx_chars(uart);
+#endif
+}
+
+/*
+ * Interrupts are enabled
+ */
+static void bfin_serial_stop_rx(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       unsigned short ier;
+
+       ier = UART_GET_IER(uart);
+       ier &= ~ERBFI;
+       UART_PUT_IER(uart, ier);
+}
+
+/*
+ * Set the modem control timer to fire immediately.
+ */
+static void bfin_serial_enable_ms(struct uart_port *port)
+{
+}
+
+#ifdef CONFIG_SERIAL_BFIN_PIO
+static void local_put_char(struct bfin_serial_port *uart, char ch)
+{
+       unsigned short status;
+       int flags = 0;
+
+       spin_lock_irqsave(&uart->port.lock, flags);
+
+       do {
+               status = UART_GET_LSR(uart);
+       } while (!(status & THRE));
+
+       UART_PUT_CHAR(uart, ch);
+       SSYNC();
+
+       spin_unlock_irqrestore(&uart->port.lock, flags);
+}
+
+static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+{
+       struct tty_struct *tty = uart->port.info?uart->port.info->tty:0;
+       unsigned int status, ch, flg;
+#ifdef BF533_FAMILY
+       static int in_break = 0;
+#endif
+
+       status = UART_GET_LSR(uart);
+       ch = UART_GET_CHAR(uart);
+       uart->port.icount.rx++;
+
+#ifdef BF533_FAMILY
+       /* The BF533 family of processors have a nice misbehavior where
+        * they continuously generate characters for a "single" break.
+        * We have to basically ignore this flood until the "next" valid
+        * character comes across.  All other Blackfin families operate
+        * properly though.
+        */
+       if (in_break) {
+               if (ch != 0) {
+                       in_break = 0;
+                       ch = UART_GET_CHAR(uart);
+               }
+               return;
+       }
+#endif
+
+       if (status & BI) {
+#ifdef BF533_FAMILY
+               in_break = 1;
+#endif
+               uart->port.icount.brk++;
+               if (uart_handle_break(&uart->port))
+                       goto ignore_char;
+               flg = TTY_BREAK;
+       } else if (status & PE) {
+               flg = TTY_PARITY;
+               uart->port.icount.parity++;
+       } else if (status & OE) {
+               flg = TTY_OVERRUN;
+               uart->port.icount.overrun++;
+       } else if (status & FE) {
+               flg = TTY_FRAME;
+               uart->port.icount.frame++;
+       } else
+               flg = TTY_NORMAL;
+
+       if (uart_handle_sysrq_char(&uart->port, ch))
+               goto ignore_char;
+       if (tty)
+               uart_insert_char(&uart->port, status, 2, ch, flg);
+
+ignore_char:
+       if (tty)
+               tty_flip_buffer_push(tty);
+}
+
+static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
+{
+       struct circ_buf *xmit = &uart->port.info->xmit;
+
+       if (uart->port.x_char) {
+               UART_PUT_CHAR(uart, uart->port.x_char);
+               uart->port.icount.tx++;
+               uart->port.x_char = 0;
+               return;
+       }
+       /*
+        * Check the modem control lines before
+        * transmitting anything.
+        */
+       bfin_serial_mctrl_check(uart);
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
+               bfin_serial_stop_tx(&uart->port);
+               return;
+       }
+
+       local_put_char(uart, xmit->buf[xmit->tail]);
+       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+       uart->port.icount.tx++;
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&uart->port);
+
+       if (uart_circ_empty(xmit))
+               bfin_serial_stop_tx(&uart->port);
+}
+
+static irqreturn_t bfin_serial_int(int irq, void *dev_id)
+{
+       struct bfin_serial_port *uart = dev_id;
+       unsigned short status;
+
+       spin_lock(&uart->port.lock);
+       status = UART_GET_IIR(uart);
+       do {
+               if ((status & IIR_STATUS) == IIR_TX_READY)
+                       bfin_serial_tx_chars(uart);
+               if ((status & IIR_STATUS) == IIR_RX_READY)
+                       bfin_serial_rx_chars(uart);
+               status = UART_GET_IIR(uart);
+       } while (status & (IIR_TX_READY | IIR_RX_READY));
+       spin_unlock(&uart->port.lock);
+       return IRQ_HANDLED;
+}
+
+static void bfin_serial_do_work(struct work_struct *work)
+{
+       struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue);
+
+       bfin_serial_mctrl_check(uart);
+}
+
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
+{
+       struct circ_buf *xmit = &uart->port.info->xmit;
+       unsigned short ier;
+       int flags = 0;
+
+       if (!uart->tx_done)
+               return;
+
+       uart->tx_done = 0;
+
+       if (uart->port.x_char) {
+               UART_PUT_CHAR(uart, uart->port.x_char);
+               uart->port.icount.tx++;
+               uart->port.x_char = 0;
+               uart->tx_done = 1;
+               return;
+       }
+       /*
+        * Check the modem control lines before
+        * transmitting anything.
+        */
+       bfin_serial_mctrl_check(uart);
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
+               bfin_serial_stop_tx(&uart->port);
+               uart->tx_done = 1;
+               return;
+       }
+
+       spin_lock_irqsave(&uart->port.lock, flags);
+       uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
+       if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail))
+               uart->tx_count = UART_XMIT_SIZE - xmit->tail;
+       blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail),
+                                       (unsigned long)(xmit->buf+xmit->tail+uart->tx_count));
+       set_dma_config(uart->tx_dma_channel,
+               set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,
+                       INTR_ON_BUF,
+                       DIMENSION_LINEAR,
+                       DATA_SIZE_8));
+       set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
+       set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
+       set_dma_x_modify(uart->tx_dma_channel, 1);
+       enable_dma(uart->tx_dma_channel);
+       ier = UART_GET_IER(uart);
+       ier |= ETBEI;
+       UART_PUT_IER(uart, ier);
+       spin_unlock_irqrestore(&uart->port.lock, flags);
+}
+
+static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart)
+{
+       struct tty_struct *tty = uart->port.info->tty;
+       int i, flg, status;
+
+       status = UART_GET_LSR(uart);
+       uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE);;
+
+       if (status & BI) {
+               uart->port.icount.brk++;
+               if (uart_handle_break(&uart->port))
+                       goto dma_ignore_char;
+               flg = TTY_BREAK;
+       } else if (status & PE) {
+               flg = TTY_PARITY;
+               uart->port.icount.parity++;
+       } else if (status & OE) {
+               flg = TTY_OVERRUN;
+               uart->port.icount.overrun++;
+       } else if (status & FE) {
+               flg = TTY_FRAME;
+               uart->port.icount.frame++;
+       } else
+               flg = TTY_NORMAL;
+
+       for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) {
+               if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
+                       goto dma_ignore_char;
+               uart_insert_char(&uart->port, status, 2, uart->rx_dma_buf.buf[i], flg);
+       }
+dma_ignore_char:
+       tty_flip_buffer_push(tty);
+}
+
+void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
+{
+       int x_pos, pos;
+       int flags = 0;
+
+       bfin_serial_dma_tx_chars(uart);
+
+       spin_lock_irqsave(&uart->port.lock, flags);
+       x_pos = DMA_RX_XCOUNT - get_dma_curr_xcount(uart->rx_dma_channel);
+       if (x_pos == DMA_RX_XCOUNT)
+               x_pos = 0;
+
+       pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
+
+       if (pos>uart->rx_dma_buf.tail) {
+               uart->rx_dma_buf.tail = pos;
+               bfin_serial_dma_rx_chars(uart);
+               uart->rx_dma_buf.head = uart->rx_dma_buf.tail;
+       }
+       spin_unlock_irqrestore(&uart->port.lock, flags);
+       uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
+       add_timer(&(uart->rx_dma_timer));
+}
+
+static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
+{
+       struct bfin_serial_port *uart = dev_id;
+       struct circ_buf *xmit = &uart->port.info->xmit;
+       unsigned short ier;
+
+       spin_lock(&uart->port.lock);
+       if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
+               clear_dma_irqstat(uart->tx_dma_channel);
+               disable_dma(uart->tx_dma_channel);
+               ier = UART_GET_IER(uart);
+               ier &= ~ETBEI;
+               UART_PUT_IER(uart, ier);
+               xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
+               uart->port.icount.tx+=uart->tx_count;
+
+               if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+                       uart_write_wakeup(&uart->port);
+
+               if (uart_circ_empty(xmit))
+                       bfin_serial_stop_tx(&uart->port);
+               uart->tx_done = 1;
+       }
+
+       spin_unlock(&uart->port.lock);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
+{
+       struct bfin_serial_port *uart = dev_id;
+       unsigned short irqstat;
+
+       uart->rx_dma_nrows++;
+       if (uart->rx_dma_nrows == DMA_RX_YCOUNT) {
+               uart->rx_dma_nrows = 0;
+               uart->rx_dma_buf.tail = DMA_RX_XCOUNT*DMA_RX_YCOUNT;
+               bfin_serial_dma_rx_chars(uart);
+               uart->rx_dma_buf.head = uart->rx_dma_buf.tail = 0;
+       }
+       spin_lock(&uart->port.lock);
+       irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
+       clear_dma_irqstat(uart->rx_dma_channel);
+
+       spin_unlock(&uart->port.lock);
+       return IRQ_HANDLED;
+}
+#endif
+
+/*
+ * Return TIOCSER_TEMT when transmitter is not busy.
+ */
+static unsigned int bfin_serial_tx_empty(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       unsigned short lsr;
+
+       lsr = UART_GET_LSR(uart);
+       if (lsr & TEMT)
+               return TIOCSER_TEMT;
+       else
+               return 0;
+}
+
+static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
+{
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       if (uart->cts_pin < 0)
+               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+
+       if (gpio_get_value(uart->cts_pin))
+               return TIOCM_DSR | TIOCM_CAR;
+       else
+#endif
+               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       if (uart->rts_pin < 0)
+               return;
+
+       if (mctrl & TIOCM_RTS)
+               gpio_set_value(uart->rts_pin, 0);
+       else
+               gpio_set_value(uart->rts_pin, 1);
+#endif
+}
+
+/*
+ * Handle any change of modem status signal since we were last called.
+ */
+static void bfin_serial_mctrl_check(struct bfin_serial_port *uart)
+{
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       unsigned int status;
+# ifdef CONFIG_SERIAL_BFIN_DMA
+       struct uart_info *info = uart->port.info;
+       struct tty_struct *tty = info->tty;
+
+       status = bfin_serial_get_mctrl(&uart->port);
+       if (!(status & TIOCM_CTS)) {
+               tty->hw_stopped = 1;
+       } else {
+               tty->hw_stopped = 0;
+       }
+# else
+       status = bfin_serial_get_mctrl(&uart->port);
+       uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
+       if (!(status & TIOCM_CTS))
+               schedule_work(&uart->cts_workqueue);
+# endif
+#endif
+}
+
+/*
+ * Interrupts are always disabled.
+ */
+static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static int bfin_serial_startup(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       dma_addr_t dma_handle;
+
+       if (request_dma(uart->rx_dma_channel, "BFIN_UART_RX") < 0) {
+               printk(KERN_NOTICE "Unable to attach Blackfin UART RX DMA channel\n");
+               return -EBUSY;
+       }
+
+       if (request_dma(uart->tx_dma_channel, "BFIN_UART_TX") < 0) {
+               printk(KERN_NOTICE "Unable to attach Blackfin UART TX DMA channel\n");
+               free_dma(uart->rx_dma_channel);
+               return -EBUSY;
+       }
+
+       set_dma_callback(uart->rx_dma_channel, bfin_serial_dma_rx_int, uart);
+       set_dma_callback(uart->tx_dma_channel, bfin_serial_dma_tx_int, uart);
+
+       uart->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA);
+       uart->rx_dma_buf.head = 0;
+       uart->rx_dma_buf.tail = 0;
+       uart->rx_dma_nrows = 0;
+
+       set_dma_config(uart->rx_dma_channel,
+               set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO,
+                               INTR_ON_ROW, DIMENSION_2D,
+                               DATA_SIZE_8));
+       set_dma_x_count(uart->rx_dma_channel, DMA_RX_XCOUNT);
+       set_dma_x_modify(uart->rx_dma_channel, 1);
+       set_dma_y_count(uart->rx_dma_channel, DMA_RX_YCOUNT);
+       set_dma_y_modify(uart->rx_dma_channel, 1);
+       set_dma_start_addr(uart->rx_dma_channel, (unsigned long)uart->rx_dma_buf.buf);
+       enable_dma(uart->rx_dma_channel);
+
+       uart->rx_dma_timer.data = (unsigned long)(uart);
+       uart->rx_dma_timer.function = (void *)bfin_serial_rx_dma_timeout;
+       uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
+       add_timer(&(uart->rx_dma_timer));
+#else
+       if (request_irq
+           (uart->port.irq, bfin_serial_int, IRQF_DISABLED,
+            "BFIN_UART_RX", uart)) {
+               printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
+               return -EBUSY;
+       }
+
+       if (request_irq
+           (uart->port.irq+1, bfin_serial_int, IRQF_DISABLED,
+            "BFIN_UART_TX", uart)) {
+               printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");
+               free_irq(uart->port.irq, uart);
+               return -EBUSY;
+       }
+#endif
+       UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+       return 0;
+}
+
+static void bfin_serial_shutdown(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       disable_dma(uart->tx_dma_channel);
+       free_dma(uart->tx_dma_channel);
+       disable_dma(uart->rx_dma_channel);
+       free_dma(uart->rx_dma_channel);
+       del_timer(&(uart->rx_dma_timer));
+#else
+       free_irq(uart->port.irq, uart);
+       free_irq(uart->port.irq+1, uart);
+#endif
+}
+
+static void
+bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       unsigned long flags;
+       unsigned int baud, quot;
+       unsigned short val, ier, lsr, lcr = 0;
+
+       switch (termios->c_cflag & CSIZE) {
+       case CS8:
+               lcr = WLS(8);
+               break;
+       case CS7:
+               lcr = WLS(7);
+               break;
+       case CS6:
+               lcr = WLS(6);
+               break;
+       case CS5:
+               lcr = WLS(5);
+               break;
+       default:
+               printk(KERN_ERR "%s: word lengh not supported\n",
+                       __FUNCTION__);
+       }
+
+       if (termios->c_cflag & CSTOPB)
+               lcr |= STB;
+       if (termios->c_cflag & PARENB) {
+               lcr |= PEN;
+               if (!(termios->c_cflag & PARODD))
+                       lcr |= EPS;
+       }
+
+       /* These controls are not implemented for this port */
+       termios->c_iflag |= INPCK | BRKINT | PARMRK;
+       termios->c_iflag &= ~(IGNPAR | IGNBRK);
+
+       /* These controls are not implemented for this port */
+       termios->c_iflag |= INPCK | BRKINT | PARMRK;
+       termios->c_iflag &= ~(IGNPAR | IGNBRK);
+
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+       quot = uart_get_divisor(port, baud);
+       spin_lock_irqsave(&uart->port.lock, flags);
+
+       do {
+               lsr = UART_GET_LSR(uart);
+       } while (!(lsr & TEMT));
+
+       /* Disable UART */
+       ier = UART_GET_IER(uart);
+       UART_PUT_IER(uart, 0);
+
+       /* Set DLAB in LCR to Access DLL and DLH */
+       val = UART_GET_LCR(uart);
+       val |= DLAB;
+       UART_PUT_LCR(uart, val);
+       SSYNC();
+
+       UART_PUT_DLL(uart, quot & 0xFF);
+       SSYNC();
+       UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
+       SSYNC();
+
+       /* Clear DLAB in LCR to Access THR RBR IER */
+       val = UART_GET_LCR(uart);
+       val &= ~DLAB;
+       UART_PUT_LCR(uart, val);
+       SSYNC();
+
+       UART_PUT_LCR(uart, lcr);
+
+       /* Enable UART */
+       UART_PUT_IER(uart, ier);
+
+       val = UART_GET_GCTL(uart);
+       val |= UCEN;
+       UART_PUT_GCTL(uart, val);
+
+       spin_unlock_irqrestore(&uart->port.lock, flags);
+}
+
+static const char *bfin_serial_type(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+       return uart->port.type == PORT_BFIN ? "BFIN-UART" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void bfin_serial_release_port(struct uart_port *port)
+{
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int bfin_serial_request_port(struct uart_port *port)
+{
+       return 0;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void bfin_serial_config_port(struct uart_port *port, int flags)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+       if (flags & UART_CONFIG_TYPE &&
+           bfin_serial_request_port(&uart->port) == 0)
+               uart->port.type = PORT_BFIN;
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ * The only change we allow are to the flags and type, and
+ * even then only between PORT_BFIN and PORT_UNKNOWN
+ */
+static int
+bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       return 0;
+}
+
+static struct uart_ops bfin_serial_pops = {
+       .tx_empty       = bfin_serial_tx_empty,
+       .set_mctrl      = bfin_serial_set_mctrl,
+       .get_mctrl      = bfin_serial_get_mctrl,
+       .stop_tx        = bfin_serial_stop_tx,
+       .start_tx       = bfin_serial_start_tx,
+       .stop_rx        = bfin_serial_stop_rx,
+       .enable_ms      = bfin_serial_enable_ms,
+       .break_ctl      = bfin_serial_break_ctl,
+       .startup        = bfin_serial_startup,
+       .shutdown       = bfin_serial_shutdown,
+       .set_termios    = bfin_serial_set_termios,
+       .type           = bfin_serial_type,
+       .release_port   = bfin_serial_release_port,
+       .request_port   = bfin_serial_request_port,
+       .config_port    = bfin_serial_config_port,
+       .verify_port    = bfin_serial_verify_port,
+};
+
+static void __init bfin_serial_init_ports(void)
+{
+       static int first = 1;
+       int i;
+
+       if (!first)
+               return;
+       first = 0;
+
+       for (i = 0; i < nr_ports; i++) {
+               bfin_serial_ports[i].port.uartclk   = get_sclk();
+               bfin_serial_ports[i].port.ops       = &bfin_serial_pops;
+               bfin_serial_ports[i].port.line      = i;
+               bfin_serial_ports[i].port.iotype    = UPIO_MEM;
+               bfin_serial_ports[i].port.membase   =
+                       (void __iomem *)bfin_serial_resource[i].uart_base_addr;
+               bfin_serial_ports[i].port.mapbase   =
+                       bfin_serial_resource[i].uart_base_addr;
+               bfin_serial_ports[i].port.irq       =
+                       bfin_serial_resource[i].uart_irq;
+               bfin_serial_ports[i].port.flags     = UPF_BOOT_AUTOCONF;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+               bfin_serial_ports[i].tx_done        = 1;
+               bfin_serial_ports[i].tx_count       = 0;
+               bfin_serial_ports[i].tx_dma_channel =
+                       bfin_serial_resource[i].uart_tx_dma_channel;
+               bfin_serial_ports[i].rx_dma_channel =
+                       bfin_serial_resource[i].uart_rx_dma_channel;
+               init_timer(&(bfin_serial_ports[i].rx_dma_timer));
+#else
+               INIT_WORK(&bfin_serial_ports[i].cts_workqueue, bfin_serial_do_work);
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+               bfin_serial_ports[i].cts_pin        =
+                       bfin_serial_resource[i].uart_cts_pin;
+               bfin_serial_ports[i].rts_pin        =
+                       bfin_serial_resource[i].uart_rts_pin;
+#endif
+               bfin_serial_hw_init(&bfin_serial_ports[i]);
+
+       }
+}
+
+#ifdef CONFIG_SERIAL_BFIN_CONSOLE
+static void bfin_serial_console_putchar(struct uart_port *port, int ch)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       while (!(UART_GET_LSR(uart)))
+               barrier();
+       UART_PUT_CHAR(uart, ch);
+       SSYNC();
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void
+bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
+{
+       struct bfin_serial_port *uart = &bfin_serial_ports[co->index];
+       int flags = 0;
+
+       spin_lock_irqsave(&uart->port.lock, flags);
+       uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
+       spin_unlock_irqrestore(&uart->port.lock, flags);
+
+}
+
+/*
+ * If the port was already initialised (eg, by a boot loader),
+ * try to determine the current setup.
+ */
+static void __init
+bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
+                          int *parity, int *bits)
+{
+       unsigned short status;
+
+       status = UART_GET_IER(uart) & (ERBFI | ETBEI);
+       if (status == (ERBFI | ETBEI)) {
+               /* ok, the port was enabled */
+               unsigned short lcr, val;
+               unsigned short dlh, dll;
+
+               lcr = UART_GET_LCR(uart);
+
+               *parity = 'n';
+               if (lcr & PEN) {
+                       if (lcr & EPS)
+                               *parity = 'e';
+                       else
+                               *parity = 'o';
+               }
+               switch (lcr & 0x03) {
+                       case 0: *bits = 5; break;
+                       case 1: *bits = 6; break;
+                       case 2: *bits = 7; break;
+                       case 3: *bits = 8; break;
+               }
+               /* Set DLAB in LCR to Access DLL and DLH */
+               val = UART_GET_LCR(uart);
+               val |= DLAB;
+               UART_PUT_LCR(uart, val);
+
+               dll = UART_GET_DLL(uart);
+               dlh = UART_GET_DLH(uart);
+
+               /* Clear DLAB in LCR to Access THR RBR IER */
+               val = UART_GET_LCR(uart);
+               val &= ~DLAB;
+               UART_PUT_LCR(uart, val);
+
+               *baud = get_sclk() / (16*(dll | dlh << 8));
+       }
+       pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
+}
+
+static int __init
+bfin_serial_console_setup(struct console *co, char *options)
+{
+       struct bfin_serial_port *uart;
+       int baud = 57600;
+       int bits = 8;
+       int parity = 'n';
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int flow = 'r';
+#else
+       int flow = 'n';
+#endif
+
+       /*
+        * Check whether an invalid uart number has been specified, and
+        * if so, search for the first available port that does have
+        * console support.
+        */
+       if (co->index == -1 || co->index >= nr_ports)
+               co->index = 0;
+       uart = &bfin_serial_ports[co->index];
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       else
+               bfin_serial_console_get_options(uart, &baud, &parity, &bits);
+
+       return uart_set_options(&uart->port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver bfin_serial_reg;
+static struct console bfin_serial_console = {
+       .name           = BFIN_SERIAL_NAME,
+       .write          = bfin_serial_console_write,
+       .device         = uart_console_device,
+       .setup          = bfin_serial_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &bfin_serial_reg,
+};
+
+static int __init bfin_serial_rs_console_init(void)
+{
+       bfin_serial_init_ports();
+       register_console(&bfin_serial_console);
+       return 0;
+}
+console_initcall(bfin_serial_rs_console_init);
+
+#define BFIN_SERIAL_CONSOLE    &bfin_serial_console
+#else
+#define BFIN_SERIAL_CONSOLE    NULL
+#endif
+
+static struct uart_driver bfin_serial_reg = {
+       .owner                  = THIS_MODULE,
+       .driver_name            = "bfin-uart",
+       .dev_name               = BFIN_SERIAL_NAME,
+       .major                  = BFIN_SERIAL_MAJOR,
+       .minor                  = BFIN_SERIAL_MINOR,
+       .nr                     = NR_PORTS,
+       .cons                   = BFIN_SERIAL_CONSOLE,
+};
+
+static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct bfin_serial_port *uart = platform_get_drvdata(dev);
+
+       if (uart)
+               uart_suspend_port(&bfin_serial_reg, &uart->port);
+
+       return 0;
+}
+
+static int bfin_serial_resume(struct platform_device *dev)
+{
+       struct bfin_serial_port *uart = platform_get_drvdata(dev);
+
+       if (uart)
+               uart_resume_port(&bfin_serial_reg, &uart->port);
+
+       return 0;
+}
+
+static int bfin_serial_probe(struct platform_device *dev)
+{
+       struct resource *res = dev->resource;
+       int i;
+
+       for (i = 0; i < dev->num_resources; i++, res++)
+               if (res->flags & IORESOURCE_MEM)
+                       break;
+
+       if (i < dev->num_resources) {
+               for (i = 0; i < nr_ports; i++, res++) {
+                       if (bfin_serial_ports[i].port.mapbase != res->start)
+                               continue;
+                       bfin_serial_ports[i].port.dev = &dev->dev;
+                       uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+                       platform_set_drvdata(dev, &bfin_serial_ports[i]);
+               }
+       }
+
+       return 0;
+}
+
+static int bfin_serial_remove(struct platform_device *pdev)
+{
+       struct bfin_serial_port *uart = platform_get_drvdata(pdev);
+
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       gpio_free(uart->cts_pin);
+       gpio_free(uart->rts_pin);
+#endif
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (uart)
+               uart_remove_one_port(&bfin_serial_reg, &uart->port);
+
+       return 0;
+}
+
+static struct platform_driver bfin_serial_driver = {
+       .probe          = bfin_serial_probe,
+       .remove         = bfin_serial_remove,
+       .suspend        = bfin_serial_suspend,
+       .resume         = bfin_serial_resume,
+       .driver         = {
+               .name   = "bfin-uart",
+       },
+};
+
+static int __init bfin_serial_init(void)
+{
+       int ret;
+
+       pr_info("Serial: Blackfin serial driver\n");
+
+       bfin_serial_init_ports();
+
+       ret = uart_register_driver(&bfin_serial_reg);
+       if (ret == 0) {
+               ret = platform_driver_register(&bfin_serial_driver);
+               if (ret) {
+                       pr_debug("uart register failed\n");
+                       uart_unregister_driver(&bfin_serial_reg);
+               }
+       }
+       return ret;
+}
+
+static void __exit bfin_serial_exit(void)
+{
+       platform_driver_unregister(&bfin_serial_driver);
+       uart_unregister_driver(&bfin_serial_reg);
+}
+
+module_init(bfin_serial_init);
+module_exit(bfin_serial_exit);
+
+MODULE_AUTHOR("Aubrey.Li <aubrey.li@analog.com>");
+MODULE_DESCRIPTION("Blackfin generic serial port driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR);
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
deleted file mode 100644 (file)
index 4a23340..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * serial.h: Arch-dep definitions for the Etrax100 serial driver.
- *
- * Copyright (C) 1998, 1999, 2000 Axis Communications AB
- */
-
-#ifndef _ETRAX_SERIAL_H
-#define _ETRAX_SERIAL_H
-
-#include <linux/circ_buf.h>
-#include <asm/termios.h>
-
-/* Software state per channel */
-
-#ifdef __KERNEL__
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-#define SERIAL_RECV_DESCRIPTORS 8
-
-struct etrax_recv_buffer {
-       struct etrax_recv_buffer *next;
-       unsigned short length;
-       unsigned char error;
-       unsigned char pad;
-
-       unsigned char buffer[0];
-};
-
-struct e100_serial {
-       int                     baud;
-       volatile u8             *port; /* R_SERIALx_CTRL */
-       u32                     irq;  /* bitnr in R_IRQ_MASK2 for dmaX_descr */
-
-       /* Output registers */
-       volatile u8             *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
-       volatile u32            *ofirstadr;   /* adr to R_DMA_CHx_FIRST */
-       volatile u8             *ocmdadr;     /* adr to R_DMA_CHx_CMD */
-       const volatile u8       *ostatusadr;  /* adr to R_DMA_CHx_STATUS */
-
-       /* Input registers */
-       volatile u8             *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
-       volatile u32            *ifirstadr;   /* adr to R_DMA_CHx_FIRST */
-       volatile u8             *icmdadr;     /* adr to R_DMA_CHx_CMD */
-       volatile u32            *idescradr;   /* adr to R_DMA_CHx_DESCR */
-
-       int                     flags;  /* defined in tty.h */
-
-       u8                      rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
-       u8                      tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
-       u8                      iseteop; /* bit number for R_SET_EOP for the input dma */
-       int                     enabled; /* Set to 1 if the port is enabled in HW config */
-
-       u8              dma_out_enabled:1; /* Set to 1 if DMA should be used */
-       u8              dma_in_enabled:1;  /* Set to 1 if DMA should be used */
-
-       /* end of fields defined in rs_table[] in .c-file */
-       u8              uses_dma_in;  /* Set to 1 if DMA is used */
-       u8              uses_dma_out; /* Set to 1 if DMA is used */
-       u8              forced_eop;   /* a fifo eop has been forced */
-       int                     baud_base;     /* For special baudrates */
-       int                     custom_divisor; /* For special baudrates */
-       struct etrax_dma_descr  tr_descr;
-       struct etrax_dma_descr  rec_descr[SERIAL_RECV_DESCRIPTORS];
-       int                     cur_rec_descr;
-
-       volatile int            tr_running; /* 1 if output is running */
-
-       struct tty_struct       *tty;
-       int                     read_status_mask;
-       int                     ignore_status_mask;
-       int                     x_char; /* xon/xoff character */
-       int                     close_delay;
-       unsigned short          closing_wait;
-       unsigned short          closing_wait2;
-       unsigned long           event;
-       unsigned long           last_active;
-       int                     line;
-       int                     type;  /* PORT_ETRAX */
-       int                     count;      /* # of fd on device */
-       int                     blocked_open; /* # of blocked opens */
-       struct circ_buf         xmit;
-       struct etrax_recv_buffer *first_recv_buffer;
-       struct etrax_recv_buffer *last_recv_buffer;
-       unsigned int            recv_cnt;
-       unsigned int            max_recv_cnt;
-
-       struct work_struct      work;
-       struct async_icount     icount;   /* error-statistics etc.*/
-       struct ktermios         normal_termios;
-       struct ktermios         callout_termios;
-#ifdef DECLARE_WAITQUEUE
-       wait_queue_head_t       open_wait;
-       wait_queue_head_t       close_wait;
-#else
-       struct wait_queue       *open_wait;
-       struct wait_queue       *close_wait;
-#endif
-
-       unsigned long           char_time_usec;       /* The time for 1 char, in usecs */
-       unsigned long           flush_time_usec;      /* How often we should flush */
-       unsigned long           last_tx_active_usec;  /* Last tx usec in the jiffies */
-       unsigned long           last_tx_active;       /* Last tx time in jiffies */
-       unsigned long           last_rx_active_usec;  /* Last rx usec in the jiffies */
-       unsigned long           last_rx_active;       /* Last rx time in jiffies */
-
-       int                     break_detected_cnt;
-       int                     errorcode;
-
-#ifdef CONFIG_ETRAX_RS485
-       struct rs485_control    rs485;  /* RS-485 support */
-#endif
-};
-
-/* this PORT is not in the standard serial.h. it's not actually used for
- * anything since we only have one type of async serial-port anyway in this
- * system.
- */
-
-#define PORT_ETRAX 1
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define RS_EVENT_WRITE_WAKEUP  0
-
-#endif /* __KERNEL__ */
-
-#endif /* !_ETRAX_SERIAL_H */
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 3d2fcc5..d09f209 100644 (file)
@@ -183,6 +183,7 @@ struct mpsc_port_info {
        u8 *txb_p;              /* Phys addr of txb */
        int txr_head;           /* Where new data goes */
        int txr_tail;           /* Where sent data comes off */
+       spinlock_t tx_lock;     /* transmit lock */
 
        /* Mirrored values of regs we can't read (if 'mirror_regs' set) */
        u32 MPSC_MPCR_m;
@@ -1212,6 +1213,9 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
 {
        struct mpsc_tx_desc *txre;
        int rc = 0;
+       unsigned long iflags;
+
+       spin_lock_irqsave(&pi->tx_lock, iflags);
 
        if (!mpsc_sdma_tx_active(pi)) {
                txre = (struct mpsc_tx_desc *)(pi->txr +
@@ -1248,6 +1252,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
                mpsc_sdma_start_tx(pi); /* start next desc if ready */
        }
 
+       spin_unlock_irqrestore(&pi->tx_lock, iflags);
        return rc;
 }
 
@@ -1338,11 +1343,16 @@ static void
 mpsc_start_tx(struct uart_port *port)
 {
        struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+       unsigned long iflags;
+
+       spin_lock_irqsave(&pi->tx_lock, iflags);
 
        mpsc_unfreeze(pi);
        mpsc_copy_tx_data(pi);
        mpsc_sdma_start_tx(pi);
 
+       spin_unlock_irqrestore(&pi->tx_lock, iflags);
+
        pr_debug("mpsc_start_tx[%d]\n", port->line);
        return;
 }
@@ -1625,6 +1635,16 @@ mpsc_console_write(struct console *co, const char *s, uint count)
        struct mpsc_port_info *pi = &mpsc_ports[co->index];
        u8 *bp, *dp, add_cr = 0;
        int i;
+       unsigned long iflags;
+
+       spin_lock_irqsave(&pi->tx_lock, iflags);
+
+       while (pi->txr_head != pi->txr_tail) {
+               while (mpsc_sdma_tx_active(pi))
+                       udelay(100);
+               mpsc_sdma_intr_ack(pi);
+               mpsc_tx_intr(pi);
+       }
 
        while (mpsc_sdma_tx_active(pi))
                udelay(100);
@@ -1668,6 +1688,7 @@ mpsc_console_write(struct console *co, const char *s, uint count)
                pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1);
        }
 
+       spin_unlock_irqrestore(&pi->tx_lock, iflags);
        return;
 }
 
@@ -2005,7 +2026,8 @@ mpsc_drv_probe(struct platform_device *dev)
                if (!(rc = mpsc_drv_map_regs(pi, dev))) {
                        mpsc_drv_get_platform_data(pi, dev, dev->id);
 
-                       if (!(rc = mpsc_make_ready(pi)))
+                       if (!(rc = mpsc_make_ready(pi))) {
+                               spin_lock_init(&pi->tx_lock);
                                if (!(rc = uart_add_one_port(&mpsc_reg,
                                        &pi->port)))
                                        rc = 0;
@@ -2014,6 +2036,7 @@ mpsc_drv_probe(struct platform_device *dev)
                                                (struct uart_port *)pi);
                                        mpsc_drv_unmap_regs(pi);
                                }
+                       }
                        else
                                mpsc_drv_unmap_regs(pi);
                }
index 09b0b73..336d0f4 100644 (file)
@@ -48,7 +48,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
        port->iotype = UPIO_MEM;
        port->type = type;
        port->uartclk = *clk;
-       port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+       port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
+               | UPF_FIXED_PORT;
        port->dev = &ofdev->dev;
        port->custom_divisor = *clk / (16 * (*spd));
 
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 0422c0f..326020f 100644 (file)
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#undef DEBUG
-#ifdef DEBUG
-#define DPRINTK(x...)  printk(x)
-#else
-#define DPRINTK(x...)  do { } while (0)
-#endif
-
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -552,7 +545,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
                return;
        }
 
-       DPRINTK("uart_flush_buffer(%d) called\n", tty->index);
+       pr_debug("uart_flush_buffer(%d) called\n", tty->index);
 
        spin_lock_irqsave(&port->lock, flags);
        uart_circ_clear(&state->info->xmit);
@@ -672,19 +665,21 @@ static int uart_set_info(struct uart_state *state,
         */
        mutex_lock(&state->mutex);
 
-       change_irq  = new_serial.irq != port->irq;
+       change_irq  = !(port->flags & UPF_FIXED_PORT)
+               && new_serial.irq != port->irq;
 
        /*
         * Since changing the 'type' of the port changes its resource
         * allocations, we should treat type changes the same as
         * IO port changes.
         */
-       change_port = new_port != port->iobase ||
-                     (unsigned long)new_serial.iomem_base != port->mapbase ||
-                     new_serial.hub6 != port->hub6 ||
-                     new_serial.io_type != port->iotype ||
-                     new_serial.iomem_reg_shift != port->regshift ||
-                     new_serial.type != port->type;
+       change_port = !(port->flags & UPF_FIXED_PORT)
+               && (new_port != port->iobase ||
+                   (unsigned long)new_serial.iomem_base != port->mapbase ||
+                   new_serial.hub6 != port->hub6 ||
+                   new_serial.io_type != port->iotype ||
+                   new_serial.iomem_reg_shift != port->regshift ||
+                   new_serial.type != port->type);
 
        old_flags = port->flags;
        new_flags = new_serial.flags;
@@ -796,8 +791,10 @@ static int uart_set_info(struct uart_state *state,
                }
        }
 
-       port->irq              = new_serial.irq;
-       port->uartclk          = new_serial.baud_base * 16;
+       if (change_irq)
+               port->irq      = new_serial.irq;
+       if (!(port->flags & UPF_FIXED_PORT))
+               port->uartclk  = new_serial.baud_base * 16;
        port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
                                 (new_flags & UPF_CHANGE_MASK);
        port->custom_divisor   = new_serial.custom_divisor;
@@ -1220,7 +1217,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 
        port = state->port;
 
-       DPRINTK("uart_close(%d) called\n", port->line);
+       pr_debug("uart_close(%d) called\n", port->line);
 
        mutex_lock(&state->mutex);
 
@@ -1339,7 +1336,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
 
        expire = jiffies + timeout;
 
-       DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
+       pr_debug("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
                port->line, jiffies, expire);
 
        /*
@@ -1368,7 +1365,7 @@ static void uart_hangup(struct tty_struct *tty)
        struct uart_state *state = tty->driver_data;
 
        BUG_ON(!kernel_locked());
-       DPRINTK("uart_hangup(%d)\n", state->port->line);
+       pr_debug("uart_hangup(%d)\n", state->port->line);
 
        mutex_lock(&state->mutex);
        if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
@@ -1566,7 +1563,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
        int retval, line = tty->index;
 
        BUG_ON(!kernel_locked());
-       DPRINTK("uart_open(%d) called\n", line);
+       pr_debug("uart_open(%d) called\n", line);
 
        /*
         * tty->driver->num won't change, so we won't fail here with
@@ -2064,6 +2061,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
        case UPIO_MEM32:
        case UPIO_AU:
        case UPIO_TSI:
+       case UPIO_DWAPB:
                snprintf(address, sizeof(address),
                         "MMIO 0x%lx", port->mapbase);
                break;
@@ -2409,6 +2407,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
        case UPIO_MEM32:
        case UPIO_AU:
        case UPIO_TSI:
+       case UPIO_DWAPB:
                return (port1->mapbase == port2->mapbase);
        }
        return 0;
index 46c40bb..1f89496 100644 (file)
@@ -46,6 +46,7 @@
 #endif
 
 #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#include <linux/ctype.h>
 #include <asm/clock.h>
 #include <asm/sh_bios.h>
 #include <asm/kgdb.h>
@@ -61,7 +62,7 @@ struct sci_port {
        unsigned int            type;
 
        /* Port IRQs: ERI, RXI, TXI, BRI (optional) */
-       unsigned int            irqs[SCIx_NR_IRQS]; 
+       unsigned int            irqs[SCIx_NR_IRQS];
 
        /* Port pin configuration */
        void                    (*init_pins)(struct uart_port *port,
@@ -76,6 +77,11 @@ struct sci_port {
        /* Break timer */
        struct timer_list       break_timer;
        int                     break_flag;
+
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+       /* Port clock */
+       struct clk              *clk;
+#endif
 };
 
 #ifdef CONFIG_SH_KGDB
@@ -163,7 +169,7 @@ static void put_string(struct sci_port *sci_port, const char *buffer, int count)
        usegdb |= sh_bios_in_gdb_mode();
 #endif
 #ifdef CONFIG_SH_KGDB
-       usegdb |= (kgdb_in_gdb_mode && (port == kgdb_sci_port));
+       usegdb |= (kgdb_in_gdb_mode && (sci_port == kgdb_sci_port));
 #endif
 
        if (usegdb) {
@@ -204,7 +210,7 @@ static int kgdb_sci_getchar(void)
         int c;
 
         /* Keep trying to read a character, this could be neater */
-        while ((c = get_char(kgdb_sci_port)) < 0)
+        while ((c = get_char(&kgdb_sci_port->port)) < 0)
                cpu_relax();
 
         return c;
@@ -212,7 +218,7 @@ static int kgdb_sci_getchar(void)
 
 static inline void kgdb_sci_putchar(int c)
 {
-        put_char(kgdb_sci_port, c);
+        put_char(&kgdb_sci_port->port, c);
 }
 #endif /* CONFIG_SH_KGDB */
 
@@ -283,12 +289,23 @@ static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
 #endif
 
 #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) 
 /* SH7300 doesn't use RTS/CTS */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
        sci_out(port, SCFCR, 0);
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
+static void sci_init_pins_scif(struct uart_port* port, unsigned int cflag)
+{
+       unsigned int fcr_val = 0;
+
+       set_sh771x_scif_pfc(port);
+       if (cflag & CRTSCTS) {
+               fcr_val |= SCFCR_MCE;
+       }
+       sci_out(port, SCFCR, fcr_val);
+}
 #elif defined(CONFIG_CPU_SH3)
 /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
@@ -350,7 +367,7 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
        } else {
 #ifdef CONFIG_CPU_SUBTYPE_SH7343
                /* Nothing */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
                ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
 #else
                ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
@@ -360,7 +377,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 }
 #endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)
 static inline int scif_txroom(struct uart_port *port)
 {
        return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
@@ -735,12 +754,6 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
 
        /* Handle BREAKs */
        sci_handle_breaks(port);
-
-#ifdef CONFIG_SH_KGDB
-       /* Break into the debugger if a break is detected */
-       BREAKPOINT();
-#endif
-
        sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
 
        return IRQ_HANDLED;
@@ -947,6 +960,10 @@ static int sci_startup(struct uart_port *port)
        if (s->enable)
                s->enable(port);
 
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+       s->clk = clk_get(NULL, "module_clk");
+#endif
+
        sci_request_irq(s);
        sci_start_tx(port);
        sci_start_rx(port, 1);
@@ -964,6 +981,11 @@ static void sci_shutdown(struct uart_port *port)
 
        if (s->disable)
                s->disable(port);
+
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+       clk_put(s->clk);
+       s->clk = NULL;
+#endif
 }
 
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
@@ -971,7 +993,6 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct sci_port *s = &sci_ports[port->line];
        unsigned int status, baud, smr_val;
-       unsigned long flags;
        int t;
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
@@ -983,18 +1004,14 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
                default:
                {
 #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
-                       struct clk *clk = clk_get(NULL, "module_clk");
-                       t = SCBRR_VALUE(baud, clk_get_rate(clk));
-                       clk_put(clk);
+                       t = SCBRR_VALUE(baud, clk_get_rate(s->clk));
 #else
                        t = SCBRR_VALUE(baud);
 #endif
-               }
                        break;
+               }
        }
 
-       spin_lock_irqsave(&port->lock, flags);
-
        do {
                status = sci_in(port, SCxSR);
        } while (!(status & SCxSR_TEND(port)));
@@ -1038,8 +1055,6 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if ((termios->c_cflag & CREAD) != 0)
               sci_start_rx(port,0);
-
-       spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static const char *sci_type(struct uart_port *port)
@@ -1220,10 +1235,13 @@ static int __init serial_console_setup(struct console *co, char *options)
        if (!port->membase || !port->mapbase)
                return -ENODEV;
 
-       spin_lock_init(&port->lock);
-
        port->type = serial_console_port->type;
 
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+       if (!serial_console_port->clk)
+               serial_console_port->clk = clk_get(NULL, "module_clk");
+#endif
+
        if (port->flags & UPF_IOREMAP)
                sci_config_port(port, 0);
 
@@ -1247,7 +1265,7 @@ static struct console serial_console = {
        .device         = uart_console_device,
        .write          = serial_console_write,
        .setup          = serial_console_setup,
-       .flags          = CON_PRINTBUFFER, 
+       .flags          = CON_PRINTBUFFER,
        .index          = -1,
        .data           = &sci_uart_driver,
 };
@@ -1292,11 +1310,23 @@ int __init kgdb_console_setup(struct console *co, char *options)
        int parity = 'n';
        int flow = 'n';
 
-       spin_lock_init(&port->lock);
-
        if (co->index != kgdb_portnum)
                co->index = kgdb_portnum;
 
+       kgdb_sci_port = &sci_ports[co->index];
+       port = &kgdb_sci_port->port;
+
+       /*
+        * Also need to check port->type, we don't actually have any
+        * UPIO_PORT ports, but uart_report_port() handily misreports
+        * it anyways if we don't have a port available by the time this is
+        * called.
+        */
+       if (!port->type)
+               return -ENODEV;
+       if (!port->membase || !port->mapbase)
+               return -ENODEV;
+
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
        else
@@ -1311,11 +1341,12 @@ int __init kgdb_console_setup(struct console *co, char *options)
 
 #ifdef CONFIG_SH_KGDB_CONSOLE
 static struct console kgdb_console = {
-        .name          = "ttySC",
-        .write         = kgdb_console_write,
-        .setup         = kgdb_console_setup,
-        .flags         = CON_PRINTBUFFER | CON_ENABLED,
-        .index         = -1,
+       .name           = "ttySC",
+       .device         = uart_console_device,
+       .write          = kgdb_console_write,
+       .setup          = kgdb_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
        .data           = &sci_uart_driver,
 };
 
@@ -1361,9 +1392,19 @@ static int __devinit sci_probe(struct platform_device *dev)
        struct plat_sci_port *p = dev->dev.platform_data;
        int i;
 
-       for (i = 0; p && p->flags != 0 && i < SCI_NPORTS; p++, i++) {
+       for (i = 0; p && p->flags != 0; p++, i++) {
                struct sci_port *sciport = &sci_ports[i];
 
+               /* Sanity check */
+               if (unlikely(i == SCI_NPORTS)) {
+                       dev_notice(&dev->dev, "Attempting to register port "
+                                  "%d when only %d are available.\n",
+                                  i+1, SCI_NPORTS);
+                       dev_notice(&dev->dev, "Consider bumping "
+                                  "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
+                       break;
+               }
+
                sciport->port.mapbase   = p->mapbase;
 
                /*
@@ -1386,6 +1427,12 @@ static int __devinit sci_probe(struct platform_device *dev)
                uart_add_one_port(&sci_uart_driver, &sciport->port);
        }
 
+#if defined(CONFIG_SH_KGDB) && !defined(CONFIG_SH_KGDB_CONSOLE)
+       kgdb_sci_port   = &sci_ports[kgdb_portnum];
+       kgdb_getchar    = kgdb_sci_getchar;
+       kgdb_putchar    = kgdb_sci_putchar;
+#endif
+
 #ifdef CONFIG_CPU_FREQ
        cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
        dev_info(&dev->dev, "sci: CPU frequency notifier registered\n");
index 77f7d63..fb04fb5 100644 (file)
 # define SCPDR  0xA4050136        /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) 
 # define SCSPTR0 0xA4400000      /* 16 bit SCIF */
-# define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
+# define SCI_NPORTS 2
+# define SCIF_ORER 0x0001   /* overrun error bit */
+# define PACR 0xa4050100
+# define PBCR 0xa4050102
+# define SCSCR_INIT(port)          0x3B
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH73180)
 # define SCPDR  0xA4050138        /* 16 bit SCIF */
 # define SCIF_ORER     0x0001          /* Overrun error bit */
 # define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
+# define SCSPTR0       0xffea0024      /* 16 bit SCIF */
+# define SCSPTR1       0xffeb0024      /* 16 bit SCIF */
+# define SCSPTR2       0xffec0024      /* 16 bit SCIF */
+# define SCSPTR3       0xffed0024      /* 16 bit SCIF */
+# define SCSPTR4       0xffee0024      /* 16 bit SCIF */
+# define SCSPTR5       0xffef0024      /* 16 bit SCIF */
+# define SCIF_OPER     0x0001          /* Overrun error bit */
+# define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7206)
 # define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
 # define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
 #define SCI_CTRL_FLAGS_RIE  0x40 /* all */
 #define SCI_CTRL_FLAGS_TE   0x20 /* all */
 #define SCI_CTRL_FLAGS_RE   0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
 #else
 #define SCI_CTRL_FLAGS_REIE 0
   }
 
 #ifdef CONFIG_CPU_SH3
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7710)
+#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
+#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
+                               sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
+                                h8_sci_offset, h8_sci_size) \
+  CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
+#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
+         CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) 
 #define SCIF_FNS(name, scif_offset, scif_size) \
   CPU_SCIF_FNS(name, scif_offset, scif_size)
 #else
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7710)
+    defined(CONFIG_CPU_SUBTYPE_SH7705) 
+
 SCIF_FNS(SCSMR,  0x00, 16)
 SCIF_FNS(SCBRR,  0x04,  8)
 SCIF_FNS(SCSCR,  0x08, 16)
@@ -385,7 +408,9 @@ SCIx_FNS(SCxTDR, 0x06,  8, 0x0c,  8, 0x06,  8, 0x0C,  8, 0x03,  8)
 SCIx_FNS(SCxSR,  0x08,  8, 0x10,  8, 0x08, 16, 0x10, 16, 0x04,  8)
 SCIx_FNS(SCxRDR, 0x0a,  8, 0x14,  8, 0x0A,  8, 0x14,  8, 0x05,  8)
 SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)
 SCIF_FNS(SCFDR,                             0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
@@ -471,13 +496,24 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
        return 1;
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
 static inline int sci_rxd_in(struct uart_port *port)
 {
-       if (port->mapbase == SCSPTR0)
-               return ctrl_inw(SCSPTR0 + 0x10) & 0x01 ? 1 : 0;
-       return 1;
+         return sci_in(port,SCxSR)&0x0010 ? 1 : 0;
+}
+static inline void set_sh771x_scif_pfc(struct uart_port *port)
+{
+       if (port->mapbase == 0xA4400000){
+               ctrl_outw(ctrl_inw(PACR)&0xffc0,PACR);
+               ctrl_outw(ctrl_inw(PBCR)&0x0fff,PBCR);
+               return;
+       }
+       if (port->mapbase == 0xA4410000){
+               ctrl_outw(ctrl_inw(PBCR)&0xf003,PBCR);
+               return;
+       }
 }
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
       defined(CONFIG_CPU_SUBTYPE_SH7751) || \
       defined(CONFIG_CPU_SUBTYPE_SH4_202)
@@ -576,6 +612,23 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
        return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xffea0000)
+               return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffeb0000)
+               return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffec0000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffed0000)
+               return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffee0000)
+               return ctrl_inw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffef0000)
+               return ctrl_inw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */
+       return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_SH7206)
 static inline int sci_rxd_in(struct uart_port *port)
 {
@@ -634,7 +687,9 @@ static inline int sci_rxd_in(struct uart_port *port)
  * -- Mitch Davis - 15 Jul 2000
  */
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705)
 #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
index bfd4417..2a63cdb 100644 (file)
@@ -1312,7 +1312,7 @@ static void sunsu_console_write(struct console *co, const char *s,
  *     - initialize the serial port
  *     Return non-zero if we didn't find a serial port.
  */
-static int sunsu_console_setup(struct console *co, char *options)
+static int __init sunsu_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
        int baud = 9600;
@@ -1343,7 +1343,7 @@ static int sunsu_console_setup(struct console *co, char *options)
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-static struct console sunsu_cons = {
+static struct console sunsu_console = {
        .name   =       "ttyS",
        .write  =       sunsu_console_write,
        .device =       uart_console_device,
@@ -1373,9 +1373,9 @@ static inline struct console *SUNSU_CONSOLE(int num_uart)
        if (i == num_uart)
                return NULL;
 
-       sunsu_cons.index = i;
+       sunsu_console.index = i;
 
-       return &sunsu_cons;
+       return &sunsu_console;
 }
 #else
 #define SUNSU_CONSOLE(num_uart)                (NULL)
index 7e54e48..4a012d9 100644 (file)
@@ -58,6 +58,12 @@ config SPI_ATMEL
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
 
+config SPI_BFIN
+       tristate "SPI controller driver for ADI Blackfin5xx"
+       depends on SPI_MASTER && BFIN
+       help
+         This is the SPI controller master driver for Blackfin 5xx processor.
+
 config SPI_BITBANG
        tristate "Bitbanging SPI master"
        depends on SPI_MASTER && EXPERIMENTAL
@@ -157,7 +163,6 @@ config SPI_AT25
 # Add new SPI protocol masters in alphabetical order above this line
 #
 
-
 # (slave support would go here)
 
 endmenu # "SPI support"
index 3c280ad..a95ade8 100644 (file)
@@ -11,8 +11,9 @@ endif
 obj-$(CONFIG_SPI_MASTER)               += spi.o
 
 # SPI master controller drivers (bus)
-obj-$(CONFIG_SPI_BITBANG)              += spi_bitbang.o
 obj-$(CONFIG_SPI_ATMEL)                        += atmel_spi.o
+obj-$(CONFIG_SPI_BFIN)                 += spi_bfin5xx.o
+obj-$(CONFIG_SPI_BITBANG)              += spi_bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi_butterfly.o
 obj-$(CONFIG_SPI_IMX)                  += spi_imx.o
 obj-$(CONFIG_SPI_PXA2XX)               += pxa2xx_spi.o
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
new file mode 100644 (file)
index 0000000..ce3c0ce
--- /dev/null
@@ -0,0 +1,1313 @@
+/*
+ * File:         drivers/spi/bfin5xx_spi.c
+ * Based on:     N/A
+ * Author:       Luke Yang (Analog Devices Inc.)
+ *
+ * Created:      March. 10th 2006
+ * Description:  SPI controller driver for Blackfin 5xx
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Modified:
+ *     March 10, 2006  bfin5xx_spi.c Created. (Luke Yang)
+ *      August 7, 2006  added full duplex mode (Axel Weiss & Luke Yang)
+ *
+ * Copyright 2004-2006 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, 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 ;  see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/dma.h>
+
+#include <asm/bfin5xx_spi.h>
+
+MODULE_AUTHOR("Luke Yang");
+MODULE_DESCRIPTION("Blackfin 5xx SPI Contoller");
+MODULE_LICENSE("GPL");
+
+#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+
+#define DEFINE_SPI_REG(reg, off) \
+static inline u16 read_##reg(void) \
+            { return *(volatile unsigned short*)(SPI0_REGBASE + off); } \
+static inline void write_##reg(u16 v) \
+            {*(volatile unsigned short*)(SPI0_REGBASE + off) = v;\
+             SSYNC();}
+
+DEFINE_SPI_REG(CTRL, 0x00)
+DEFINE_SPI_REG(FLAG, 0x04)
+DEFINE_SPI_REG(STAT, 0x08)
+DEFINE_SPI_REG(TDBR, 0x0C)
+DEFINE_SPI_REG(RDBR, 0x10)
+DEFINE_SPI_REG(BAUD, 0x14)
+DEFINE_SPI_REG(SHAW, 0x18)
+#define START_STATE ((void*)0)
+#define RUNNING_STATE ((void*)1)
+#define DONE_STATE ((void*)2)
+#define ERROR_STATE ((void*)-1)
+#define QUEUE_RUNNING 0
+#define QUEUE_STOPPED 1
+int dma_requested;
+
+struct driver_data {
+       /* Driver model hookup */
+       struct platform_device *pdev;
+
+       /* SPI framework hookup */
+       struct spi_master *master;
+
+       /* BFIN hookup */
+       struct bfin5xx_spi_master *master_info;
+
+       /* Driver message queue */
+       struct workqueue_struct *workqueue;
+       struct work_struct pump_messages;
+       spinlock_t lock;
+       struct list_head queue;
+       int busy;
+       int run;
+
+       /* Message Transfer pump */
+       struct tasklet_struct pump_transfers;
+
+       /* Current message transfer state info */
+       struct spi_message *cur_msg;
+       struct spi_transfer *cur_transfer;
+       struct chip_data *cur_chip;
+       size_t len_in_bytes;
+       size_t len;
+       void *tx;
+       void *tx_end;
+       void *rx;
+       void *rx_end;
+       int dma_mapped;
+       dma_addr_t rx_dma;
+       dma_addr_t tx_dma;
+       size_t rx_map_len;
+       size_t tx_map_len;
+       u8 n_bytes;
+       void (*write) (struct driver_data *);
+       void (*read) (struct driver_data *);
+       void (*duplex) (struct driver_data *);
+};
+
+struct chip_data {
+       u16 ctl_reg;
+       u16 baud;
+       u16 flag;
+
+       u8 chip_select_num;
+       u8 n_bytes;
+       u32 width;              /* 0 or 1 */
+       u8 enable_dma;
+       u8 bits_per_word;       /* 8 or 16 */
+       u8 cs_change_per_word;
+       u8 cs_chg_udelay;
+       void (*write) (struct driver_data *);
+       void (*read) (struct driver_data *);
+       void (*duplex) (struct driver_data *);
+};
+
+void bfin_spi_enable(struct driver_data *drv_data)
+{
+       u16 cr;
+
+       cr = read_CTRL();
+       write_CTRL(cr | BIT_CTL_ENABLE);
+       SSYNC();
+}
+
+void bfin_spi_disable(struct driver_data *drv_data)
+{
+       u16 cr;
+
+       cr = read_CTRL();
+       write_CTRL(cr & (~BIT_CTL_ENABLE));
+       SSYNC();
+}
+
+/* Caculate the SPI_BAUD register value based on input HZ */
+static u16 hz_to_spi_baud(u32 speed_hz)
+{
+       u_long sclk = get_sclk();
+       u16 spi_baud = (sclk / (2 * speed_hz));
+
+       if ((sclk % (2 * speed_hz)) > 0)
+               spi_baud++;
+
+       pr_debug("sclk = %ld, speed_hz = %d, spi_baud = %d\n", sclk, speed_hz,
+                spi_baud);
+
+       return spi_baud;
+}
+
+static int flush(struct driver_data *drv_data)
+{
+       unsigned long limit = loops_per_jiffy << 1;
+
+       /* wait for stop and clear stat */
+       while (!(read_STAT() & BIT_STAT_SPIF) && limit--)
+               continue;
+
+       write_STAT(BIT_STAT_CLR);
+
+       return limit;
+}
+
+/* stop controller and re-config current chip*/
+static void restore_state(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       /* Clear status and disable clock */
+       write_STAT(BIT_STAT_CLR);
+       bfin_spi_disable(drv_data);
+       pr_debug("restoring spi ctl state\n");
+
+#if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
+       pr_debug("chip select number is %d\n", chip->chip_select_num);
+
+       switch (chip->chip_select_num) {
+       case 1:
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00);
+               SSYNC();
+               break;
+
+       case 2:
+       case 3:
+               bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJSE_SPI);
+               SSYNC();
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800);
+               SSYNC();
+               break;
+
+       case 4:
+               bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS4E_SPI);
+               SSYNC();
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3840);
+               SSYNC();
+               break;
+
+       case 5:
+               bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS5E_SPI);
+               SSYNC();
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3820);
+               SSYNC();
+               break;
+
+       case 6:
+               bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS6E_SPI);
+               SSYNC();
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3810);
+               SSYNC();
+               break;
+
+       case 7:
+               bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJCE_SPI);
+               SSYNC();
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800);
+               SSYNC();
+               break;
+       }
+#endif
+
+       /* Load the registers */
+       write_CTRL(chip->ctl_reg);
+       write_BAUD(chip->baud);
+       write_FLAG(chip->flag);
+}
+
+/* used to kick off transfer in rx mode */
+static unsigned short dummy_read(void)
+{
+       unsigned short tmp;
+       tmp = read_RDBR();
+       return tmp;
+}
+
+static void null_writer(struct driver_data *drv_data)
+{
+       u8 n_bytes = drv_data->n_bytes;
+
+       while (drv_data->tx < drv_data->tx_end) {
+               write_TDBR(0);
+               while ((read_STAT() & BIT_STAT_TXS))
+                       continue;
+               drv_data->tx += n_bytes;
+       }
+}
+
+static void null_reader(struct driver_data *drv_data)
+{
+       u8 n_bytes = drv_data->n_bytes;
+       dummy_read();
+
+       while (drv_data->rx < drv_data->rx_end) {
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               dummy_read();
+               drv_data->rx += n_bytes;
+       }
+}
+
+static void u8_writer(struct driver_data *drv_data)
+{
+       pr_debug("cr8-s is 0x%x\n", read_STAT());
+       while (drv_data->tx < drv_data->tx_end) {
+               write_TDBR(*(u8 *) (drv_data->tx));
+               while (read_STAT() & BIT_STAT_TXS)
+                       continue;
+               ++drv_data->tx;
+       }
+
+       /* poll for SPI completion before returning */
+       while (!(read_STAT() & BIT_STAT_SPIF))
+               continue;
+}
+
+static void u8_cs_chg_writer(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       while (drv_data->tx < drv_data->tx_end) {
+               write_FLAG(chip->flag);
+               SSYNC();
+
+               write_TDBR(*(u8 *) (drv_data->tx));
+               while (read_STAT() & BIT_STAT_TXS)
+                       continue;
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               write_FLAG(0xFF00 | chip->flag);
+               SSYNC();
+               if (chip->cs_chg_udelay)
+                       udelay(chip->cs_chg_udelay);
+               ++drv_data->tx;
+       }
+       write_FLAG(0xFF00);
+       SSYNC();
+}
+
+static void u8_reader(struct driver_data *drv_data)
+{
+       pr_debug("cr-8 is 0x%x\n", read_STAT());
+
+       /* clear TDBR buffer before read(else it will be shifted out) */
+       write_TDBR(0xFFFF);
+
+       dummy_read();
+
+       while (drv_data->rx < drv_data->rx_end - 1) {
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               *(u8 *) (drv_data->rx) = read_RDBR();
+               ++drv_data->rx;
+       }
+
+       while (!(read_STAT() & BIT_STAT_RXS))
+               continue;
+       *(u8 *) (drv_data->rx) = read_SHAW();
+       ++drv_data->rx;
+}
+
+static void u8_cs_chg_reader(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       while (drv_data->rx < drv_data->rx_end) {
+               write_FLAG(chip->flag);
+               SSYNC();
+
+               read_RDBR();    /* kick off */
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               *(u8 *) (drv_data->rx) = read_SHAW();
+               write_FLAG(0xFF00 | chip->flag);
+               SSYNC();
+               if (chip->cs_chg_udelay)
+                       udelay(chip->cs_chg_udelay);
+               ++drv_data->rx;
+       }
+       write_FLAG(0xFF00);
+       SSYNC();
+}
+
+static void u8_duplex(struct driver_data *drv_data)
+{
+       /* in duplex mode, clk is triggered by writing of TDBR */
+       while (drv_data->rx < drv_data->rx_end) {
+               write_TDBR(*(u8 *) (drv_data->tx));
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               *(u8 *) (drv_data->rx) = read_RDBR();
+               ++drv_data->rx;
+               ++drv_data->tx;
+       }
+}
+
+static void u8_cs_chg_duplex(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       while (drv_data->rx < drv_data->rx_end) {
+               write_FLAG(chip->flag);
+               SSYNC();
+
+               write_TDBR(*(u8 *) (drv_data->tx));
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               *(u8 *) (drv_data->rx) = read_RDBR();
+               write_FLAG(0xFF00 | chip->flag);
+               SSYNC();
+               if (chip->cs_chg_udelay)
+                       udelay(chip->cs_chg_udelay);
+               ++drv_data->rx;
+               ++drv_data->tx;
+       }
+       write_FLAG(0xFF00);
+       SSYNC();
+}
+
+static void u16_writer(struct driver_data *drv_data)
+{
+       pr_debug("cr16 is 0x%x\n", read_STAT());
+       while (drv_data->tx < drv_data->tx_end) {
+               write_TDBR(*(u16 *) (drv_data->tx));
+               while ((read_STAT() & BIT_STAT_TXS))
+                       continue;
+               drv_data->tx += 2;
+       }
+
+       /* poll for SPI completion before returning */
+       while (!(read_STAT() & BIT_STAT_SPIF))
+               continue;
+}
+
+static void u16_cs_chg_writer(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       while (drv_data->tx < drv_data->tx_end) {
+               write_FLAG(chip->flag);
+               SSYNC();
+
+               write_TDBR(*(u16 *) (drv_data->tx));
+               while ((read_STAT() & BIT_STAT_TXS))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               write_FLAG(0xFF00 | chip->flag);
+               SSYNC();
+               if (chip->cs_chg_udelay)
+                       udelay(chip->cs_chg_udelay);
+               drv_data->tx += 2;
+       }
+       write_FLAG(0xFF00);
+       SSYNC();
+}
+
+static void u16_reader(struct driver_data *drv_data)
+{
+       pr_debug("cr-16 is 0x%x\n", read_STAT());
+       dummy_read();
+
+       while (drv_data->rx < (drv_data->rx_end - 2)) {
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               *(u16 *) (drv_data->rx) = read_RDBR();
+               drv_data->rx += 2;
+       }
+
+       while (!(read_STAT() & BIT_STAT_RXS))
+               continue;
+       *(u16 *) (drv_data->rx) = read_SHAW();
+       drv_data->rx += 2;
+}
+
+static void u16_cs_chg_reader(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       while (drv_data->rx < drv_data->rx_end) {
+               write_FLAG(chip->flag);
+               SSYNC();
+
+               read_RDBR();    /* kick off */
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               *(u16 *) (drv_data->rx) = read_SHAW();
+               write_FLAG(0xFF00 | chip->flag);
+               SSYNC();
+               if (chip->cs_chg_udelay)
+                       udelay(chip->cs_chg_udelay);
+               drv_data->rx += 2;
+       }
+       write_FLAG(0xFF00);
+       SSYNC();
+}
+
+static void u16_duplex(struct driver_data *drv_data)
+{
+       /* in duplex mode, clk is triggered by writing of TDBR */
+       while (drv_data->tx < drv_data->tx_end) {
+               write_TDBR(*(u16 *) (drv_data->tx));
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               *(u16 *) (drv_data->rx) = read_RDBR();
+               drv_data->rx += 2;
+               drv_data->tx += 2;
+       }
+}
+
+static void u16_cs_chg_duplex(struct driver_data *drv_data)
+{
+       struct chip_data *chip = drv_data->cur_chip;
+
+       while (drv_data->tx < drv_data->tx_end) {
+               write_FLAG(chip->flag);
+               SSYNC();
+
+               write_TDBR(*(u16 *) (drv_data->tx));
+               while (!(read_STAT() & BIT_STAT_SPIF))
+                       continue;
+               while (!(read_STAT() & BIT_STAT_RXS))
+                       continue;
+               *(u16 *) (drv_data->rx) = read_RDBR();
+               write_FLAG(0xFF00 | chip->flag);
+               SSYNC();
+               if (chip->cs_chg_udelay)
+                       udelay(chip->cs_chg_udelay);
+               drv_data->rx += 2;
+               drv_data->tx += 2;
+       }
+       write_FLAG(0xFF00);
+       SSYNC();
+}
+
+/* test if ther is more transfer to be done */
+static void *next_transfer(struct driver_data *drv_data)
+{
+       struct spi_message *msg = drv_data->cur_msg;
+       struct spi_transfer *trans = drv_data->cur_transfer;
+
+       /* Move to next transfer */
+       if (trans->transfer_list.next != &msg->transfers) {
+               drv_data->cur_transfer =
+                   list_entry(trans->transfer_list.next,
+                              struct spi_transfer, transfer_list);
+               return RUNNING_STATE;
+       } else
+               return DONE_STATE;
+}
+
+/*
+ * caller already set message->status;
+ * dma and pio irqs are blocked give finished message back
+ */
+static void giveback(struct driver_data *drv_data)
+{
+       struct spi_transfer *last_transfer;
+       unsigned long flags;
+       struct spi_message *msg;
+
+       spin_lock_irqsave(&drv_data->lock, flags);
+       msg = drv_data->cur_msg;
+       drv_data->cur_msg = NULL;
+       drv_data->cur_transfer = NULL;
+       drv_data->cur_chip = NULL;
+       queue_work(drv_data->workqueue, &drv_data->pump_messages);
+       spin_unlock_irqrestore(&drv_data->lock, flags);
+
+       last_transfer = list_entry(msg->transfers.prev,
+                                  struct spi_transfer, transfer_list);
+
+       msg->state = NULL;
+
+       /* disable chip select signal. And not stop spi in autobuffer mode */
+       if (drv_data->tx_dma != 0xFFFF) {
+               write_FLAG(0xFF00);
+               bfin_spi_disable(drv_data);
+       }
+
+       if (msg->complete)
+               msg->complete(msg->context);
+}
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct driver_data *drv_data = (struct driver_data *)dev_id;
+       struct spi_message *msg = drv_data->cur_msg;
+
+       pr_debug("in dma_irq_handler\n");
+       clear_dma_irqstat(CH_SPI);
+
+       /*
+        * wait for the last transaction shifted out.  yes, these two
+        * while loops are supposed to be the same (see the HRM).
+        */
+       if (drv_data->tx != NULL) {
+               while (bfin_read_SPI_STAT() & TXS)
+                       continue;
+               while (bfin_read_SPI_STAT() & TXS)
+                       continue;
+       }
+
+       while (!(bfin_read_SPI_STAT() & SPIF))
+               continue;
+
+       bfin_spi_disable(drv_data);
+
+       msg->actual_length += drv_data->len_in_bytes;
+
+       /* Move to next transfer */
+       msg->state = next_transfer(drv_data);
+
+       /* Schedule transfer tasklet */
+       tasklet_schedule(&drv_data->pump_transfers);
+
+       /* free the irq handler before next transfer */
+       pr_debug("disable dma channel irq%d\n", CH_SPI);
+       dma_disable_irq(CH_SPI);
+
+       return IRQ_HANDLED;
+}
+
+static void pump_transfers(unsigned long data)
+{
+       struct driver_data *drv_data = (struct driver_data *)data;
+       struct spi_message *message = NULL;
+       struct spi_transfer *transfer = NULL;
+       struct spi_transfer *previous = NULL;
+       struct chip_data *chip = NULL;
+       u16 cr, width, dma_width, dma_config;
+       u32 tranf_success = 1;
+
+       /* Get current state information */
+       message = drv_data->cur_msg;
+       transfer = drv_data->cur_transfer;
+       chip = drv_data->cur_chip;
+
+       /*
+        * if msg is error or done, report it back using complete() callback
+        */
+
+        /* Handle for abort */
+       if (message->state == ERROR_STATE) {
+               message->status = -EIO;
+               giveback(drv_data);
+               return;
+       }
+
+       /* Handle end of message */
+       if (message->state == DONE_STATE) {
+               message->status = 0;
+               giveback(drv_data);
+               return;
+       }
+
+       /* Delay if requested at end of transfer */
+       if (message->state == RUNNING_STATE) {
+               previous = list_entry(transfer->transfer_list.prev,
+                                     struct spi_transfer, transfer_list);
+               if (previous->delay_usecs)
+                       udelay(previous->delay_usecs);
+       }
+
+       /* Setup the transfer state based on the type of transfer */
+       if (flush(drv_data) == 0) {
+               dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
+               message->status = -EIO;
+               giveback(drv_data);
+               return;
+       }
+
+       if (transfer->tx_buf != NULL) {
+               drv_data->tx = (void *)transfer->tx_buf;
+               drv_data->tx_end = drv_data->tx + transfer->len;
+               pr_debug("tx_buf is %p, tx_end is %p\n", transfer->tx_buf,
+                        drv_data->tx_end);
+       } else {
+               drv_data->tx = NULL;
+       }
+
+       if (transfer->rx_buf != NULL) {
+               drv_data->rx = transfer->rx_buf;
+               drv_data->rx_end = drv_data->rx + transfer->len;
+               pr_debug("rx_buf is %p, rx_end is %p\n", transfer->rx_buf,
+                        drv_data->rx_end);
+       } else {
+               drv_data->rx = NULL;
+       }
+
+       drv_data->rx_dma = transfer->rx_dma;
+       drv_data->tx_dma = transfer->tx_dma;
+       drv_data->len_in_bytes = transfer->len;
+
+       width = chip->width;
+       if (width == CFG_SPI_WORDSIZE16) {
+               drv_data->len = (transfer->len) >> 1;
+       } else {
+               drv_data->len = transfer->len;
+       }
+       drv_data->write = drv_data->tx ? chip->write : null_writer;
+       drv_data->read = drv_data->rx ? chip->read : null_reader;
+       drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
+       pr_debug
+           ("transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
+            drv_data->write, chip->write, null_writer);
+
+       /* speed and width has been set on per message */
+       message->state = RUNNING_STATE;
+       dma_config = 0;
+
+       /* restore spi status for each spi transfer */
+       if (transfer->speed_hz) {
+               write_BAUD(hz_to_spi_baud(transfer->speed_hz));
+       } else {
+               write_BAUD(chip->baud);
+       }
+       write_FLAG(chip->flag);
+
+       pr_debug("now pumping a transfer: width is %d, len is %d\n", width,
+                transfer->len);
+
+       /*
+        * Try to map dma buffer and do a dma transfer if
+        * successful use different way to r/w according to
+        * drv_data->cur_chip->enable_dma
+        */
+       if (drv_data->cur_chip->enable_dma && drv_data->len > 6) {
+
+               write_STAT(BIT_STAT_CLR);
+               disable_dma(CH_SPI);
+               clear_dma_irqstat(CH_SPI);
+               bfin_spi_disable(drv_data);
+
+               /* config dma channel */
+               pr_debug("doing dma transfer\n");
+               if (width == CFG_SPI_WORDSIZE16) {
+                       set_dma_x_count(CH_SPI, drv_data->len);
+                       set_dma_x_modify(CH_SPI, 2);
+                       dma_width = WDSIZE_16;
+               } else {
+                       set_dma_x_count(CH_SPI, drv_data->len);
+                       set_dma_x_modify(CH_SPI, 1);
+                       dma_width = WDSIZE_8;
+               }
+
+               /* set transfer width,direction. And enable spi */
+               cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+
+               /* dirty hack for autobuffer DMA mode */
+               if (drv_data->tx_dma == 0xFFFF) {
+                       pr_debug("doing autobuffer DMA out.\n");
+
+                       /* no irq in autobuffer mode */
+                       dma_config =
+                           (DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
+                       set_dma_config(CH_SPI, dma_config);
+                       set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx);
+                       enable_dma(CH_SPI);
+                       write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) |
+                                  (CFG_SPI_ENABLE << 14));
+
+                       /* just return here, there can only be one transfer in this mode */
+                       message->status = 0;
+                       giveback(drv_data);
+                       return;
+               }
+
+               /* In dma mode, rx or tx must be NULL in one transfer */
+               if (drv_data->rx != NULL) {
+                       /* set transfer mode, and enable SPI */
+                       pr_debug("doing DMA in.\n");
+
+                       /* disable SPI before write to TDBR */
+                       write_CTRL(cr & ~BIT_CTL_ENABLE);
+
+                       /* clear tx reg soformer data is not shifted out */
+                       write_TDBR(0xFF);
+
+                       set_dma_x_count(CH_SPI, drv_data->len);
+
+                       /* start dma */
+                       dma_enable_irq(CH_SPI);
+                       dma_config = (WNR | RESTART | dma_width | DI_EN);
+                       set_dma_config(CH_SPI, dma_config);
+                       set_dma_start_addr(CH_SPI, (unsigned long)drv_data->rx);
+                       enable_dma(CH_SPI);
+
+                       cr |=
+                           CFG_SPI_DMAREAD | (width << 8) | (CFG_SPI_ENABLE <<
+                                                             14);
+                       /* set transfer mode, and enable SPI */
+                       write_CTRL(cr);
+               } else if (drv_data->tx != NULL) {
+                       pr_debug("doing DMA out.\n");
+
+                       /* start dma */
+                       dma_enable_irq(CH_SPI);
+                       dma_config = (RESTART | dma_width | DI_EN);
+                       set_dma_config(CH_SPI, dma_config);
+                       set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx);
+                       enable_dma(CH_SPI);
+
+                       write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) |
+                                  (CFG_SPI_ENABLE << 14));
+
+               }
+       } else {
+               /* IO mode write then read */
+               pr_debug("doing IO transfer\n");
+
+               write_STAT(BIT_STAT_CLR);
+
+               if (drv_data->tx != NULL && drv_data->rx != NULL) {
+                       /* full duplex mode */
+                       BUG_ON((drv_data->tx_end - drv_data->tx) !=
+                              (drv_data->rx_end - drv_data->rx));
+                       cr = (read_CTRL() & (~BIT_CTL_TIMOD));  /* clear the TIMOD bits */
+                       cr |=
+                           CFG_SPI_WRITE | (width << 8) | (CFG_SPI_ENABLE <<
+                                                           14);
+                       pr_debug("IO duplex: cr is 0x%x\n", cr);
+
+                       write_CTRL(cr);
+                       SSYNC();
+
+                       drv_data->duplex(drv_data);
+
+                       if (drv_data->tx != drv_data->tx_end)
+                               tranf_success = 0;
+               } else if (drv_data->tx != NULL) {
+                       /* write only half duplex */
+                       cr = (read_CTRL() & (~BIT_CTL_TIMOD));  /* clear the TIMOD bits */
+                       cr |=
+                           CFG_SPI_WRITE | (width << 8) | (CFG_SPI_ENABLE <<
+                                                           14);
+                       pr_debug("IO write: cr is 0x%x\n", cr);
+
+                       write_CTRL(cr);
+                       SSYNC();
+
+                       drv_data->write(drv_data);
+
+                       if (drv_data->tx != drv_data->tx_end)
+                               tranf_success = 0;
+               } else if (drv_data->rx != NULL) {
+                       /* read only half duplex */
+                       cr = (read_CTRL() & (~BIT_CTL_TIMOD));  /* cleare the TIMOD bits */
+                       cr |=
+                           CFG_SPI_READ | (width << 8) | (CFG_SPI_ENABLE <<
+                                                          14);
+                       pr_debug("IO read: cr is 0x%x\n", cr);
+
+                       write_CTRL(cr);
+                       SSYNC();
+
+                       drv_data->read(drv_data);
+                       if (drv_data->rx != drv_data->rx_end)
+                               tranf_success = 0;
+               }
+
+               if (!tranf_success) {
+                       pr_debug("IO write error!\n");
+                       message->state = ERROR_STATE;
+               } else {
+                       /* Update total byte transfered */
+                       message->actual_length += drv_data->len;
+
+                       /* Move to next transfer of this msg */
+                       message->state = next_transfer(drv_data);
+               }
+
+               /* Schedule next transfer tasklet */
+               tasklet_schedule(&drv_data->pump_transfers);
+
+       }
+}
+
+/* pop a msg from queue and kick off real transfer */
+static void pump_messages(struct work_struct *work)
+{
+       struct driver_data *drv_data = container_of(work, struct driver_data, pump_messages);
+       unsigned long flags;
+
+       /* Lock queue and check for queue work */
+       spin_lock_irqsave(&drv_data->lock, flags);
+       if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+               /* pumper kicked off but no work to do */
+               drv_data->busy = 0;
+               spin_unlock_irqrestore(&drv_data->lock, flags);
+               return;
+       }
+
+       /* Make sure we are not already running a message */
+       if (drv_data->cur_msg) {
+               spin_unlock_irqrestore(&drv_data->lock, flags);
+               return;
+       }
+
+       /* Extract head of queue */
+       drv_data->cur_msg = list_entry(drv_data->queue.next,
+                                      struct spi_message, queue);
+       list_del_init(&drv_data->cur_msg->queue);
+
+       /* Initial message state */
+       drv_data->cur_msg->state = START_STATE;
+       drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+                                           struct spi_transfer, transfer_list);
+
+       /* Setup the SSP using the per chip configuration */
+       drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+       restore_state(drv_data);
+       pr_debug
+           ("got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
+            drv_data->cur_chip->baud, drv_data->cur_chip->flag,
+            drv_data->cur_chip->ctl_reg);
+       pr_debug("the first transfer len is %d\n", drv_data->cur_transfer->len);
+
+       /* Mark as busy and launch transfers */
+       tasklet_schedule(&drv_data->pump_transfers);
+
+       drv_data->busy = 1;
+       spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+/*
+ * got a msg to transfer, queue it in drv_data->queue.
+ * And kick off message pumper
+ */
+static int transfer(struct spi_device *spi, struct spi_message *msg)
+{
+       struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+       unsigned long flags;
+
+       spin_lock_irqsave(&drv_data->lock, flags);
+
+       if (drv_data->run == QUEUE_STOPPED) {
+               spin_unlock_irqrestore(&drv_data->lock, flags);
+               return -ESHUTDOWN;
+       }
+
+       msg->actual_length = 0;
+       msg->status = -EINPROGRESS;
+       msg->state = START_STATE;
+
+       pr_debug("adding an msg in transfer() \n");
+       list_add_tail(&msg->queue, &drv_data->queue);
+
+       if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+               queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+       spin_unlock_irqrestore(&drv_data->lock, flags);
+
+       return 0;
+}
+
+/* first setup for new devices */
+static int setup(struct spi_device *spi)
+{
+       struct bfin5xx_spi_chip *chip_info = NULL;
+       struct chip_data *chip;
+       struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+       u8 spi_flg;
+
+       /* Abort device setup if requested features are not supported */
+       if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
+               dev_err(&spi->dev, "requested mode not fully supported\n");
+               return -EINVAL;
+       }
+
+       /* Zero (the default) here means 8 bits */
+       if (!spi->bits_per_word)
+               spi->bits_per_word = 8;
+
+       if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
+               return -EINVAL;
+
+       /* Only alloc (or use chip_info) on first setup */
+       chip = spi_get_ctldata(spi);
+       if (chip == NULL) {
+               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+               if (!chip)
+                       return -ENOMEM;
+
+               chip->enable_dma = 0;
+               chip_info = spi->controller_data;
+       }
+
+       /* chip_info isn't always needed */
+       if (chip_info) {
+               chip->enable_dma = chip_info->enable_dma != 0
+                   && drv_data->master_info->enable_dma;
+               chip->ctl_reg = chip_info->ctl_reg;
+               chip->bits_per_word = chip_info->bits_per_word;
+               chip->cs_change_per_word = chip_info->cs_change_per_word;
+               chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+       }
+
+       /* translate common spi framework into our register */
+       if (spi->mode & SPI_CPOL)
+               chip->ctl_reg |= CPOL;
+       if (spi->mode & SPI_CPHA)
+               chip->ctl_reg |= CPHA;
+       if (spi->mode & SPI_LSB_FIRST)
+               chip->ctl_reg |= LSBF;
+       /* we dont support running in slave mode (yet?) */
+       chip->ctl_reg |= MSTR;
+
+       /*
+        * if any one SPI chip is registered and wants DMA, request the
+        * DMA channel for it
+        */
+       if (chip->enable_dma && !dma_requested) {
+               /* register dma irq handler */
+               if (request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) {
+                       pr_debug
+                           ("Unable to request BlackFin SPI DMA channel\n");
+                       return -ENODEV;
+               }
+               if (set_dma_callback(CH_SPI, (void *)dma_irq_handler, drv_data)
+                   < 0) {
+                       pr_debug("Unable to set dma callback\n");
+                       return -EPERM;
+               }
+               dma_disable_irq(CH_SPI);
+               dma_requested = 1;
+       }
+
+       /*
+        * Notice: for blackfin, the speed_hz is the value of register
+        * SPI_BAUD, not the real baudrate
+        */
+       chip->baud = hz_to_spi_baud(spi->max_speed_hz);
+       spi_flg = ~(1 << (spi->chip_select));
+       chip->flag = ((u16) spi_flg << 8) | (1 << (spi->chip_select));
+       chip->chip_select_num = spi->chip_select;
+
+       switch (chip->bits_per_word) {
+       case 8:
+               chip->n_bytes = 1;
+               chip->width = CFG_SPI_WORDSIZE8;
+               chip->read = chip->cs_change_per_word ?
+                       u8_cs_chg_reader : u8_reader;
+               chip->write = chip->cs_change_per_word ?
+                       u8_cs_chg_writer : u8_writer;
+               chip->duplex = chip->cs_change_per_word ?
+                       u8_cs_chg_duplex : u8_duplex;
+               break;
+
+       case 16:
+               chip->n_bytes = 2;
+               chip->width = CFG_SPI_WORDSIZE16;
+               chip->read = chip->cs_change_per_word ?
+                       u16_cs_chg_reader : u16_reader;
+               chip->write = chip->cs_change_per_word ?
+                       u16_cs_chg_writer : u16_writer;
+               chip->duplex = chip->cs_change_per_word ?
+                       u16_cs_chg_duplex : u16_duplex;
+               break;
+
+       default:
+               dev_err(&spi->dev, "%d bits_per_word is not supported\n",
+                               chip->bits_per_word);
+               kfree(chip);
+               return -ENODEV;
+       }
+
+       pr_debug("setup spi chip %s, width is %d, dma is %d,",
+                       spi->modalias, chip->width, chip->enable_dma);
+       pr_debug("ctl_reg is 0x%x, flag_reg is 0x%x\n",
+                       chip->ctl_reg, chip->flag);
+
+       spi_set_ctldata(spi, chip);
+
+       return 0;
+}
+
+/*
+ * callback for spi framework.
+ * clean driver specific data
+ */
+static void cleanup(const struct spi_device *spi)
+{
+       struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+
+       kfree(chip);
+}
+
+static inline int init_queue(struct driver_data *drv_data)
+{
+       INIT_LIST_HEAD(&drv_data->queue);
+       spin_lock_init(&drv_data->lock);
+
+       drv_data->run = QUEUE_STOPPED;
+       drv_data->busy = 0;
+
+       /* init transfer tasklet */
+       tasklet_init(&drv_data->pump_transfers,
+                    pump_transfers, (unsigned long)drv_data);
+
+       /* init messages workqueue */
+       INIT_WORK(&drv_data->pump_messages, pump_messages);
+       drv_data->workqueue =
+           create_singlethread_workqueue(drv_data->master->cdev.dev->bus_id);
+       if (drv_data->workqueue == NULL)
+               return -EBUSY;
+
+       return 0;
+}
+
+static inline int start_queue(struct driver_data *drv_data)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&drv_data->lock, flags);
+
+       if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+               spin_unlock_irqrestore(&drv_data->lock, flags);
+               return -EBUSY;
+       }
+
+       drv_data->run = QUEUE_RUNNING;
+       drv_data->cur_msg = NULL;
+       drv_data->cur_transfer = NULL;
+       drv_data->cur_chip = NULL;
+       spin_unlock_irqrestore(&drv_data->lock, flags);
+
+       queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+       return 0;
+}
+
+static inline int stop_queue(struct driver_data *drv_data)
+{
+       unsigned long flags;
+       unsigned limit = 500;
+       int status = 0;
+
+       spin_lock_irqsave(&drv_data->lock, flags);
+
+       /*
+        * This is a bit lame, but is optimized for the common execution path.
+        * A wait_queue on the drv_data->busy could be used, but then the common
+        * execution path (pump_messages) would be required to call wake_up or
+        * friends on every SPI message. Do this instead
+        */
+       drv_data->run = QUEUE_STOPPED;
+       while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+               spin_unlock_irqrestore(&drv_data->lock, flags);
+               msleep(10);
+               spin_lock_irqsave(&drv_data->lock, flags);
+       }
+
+       if (!list_empty(&drv_data->queue) || drv_data->busy)
+               status = -EBUSY;
+
+       spin_unlock_irqrestore(&drv_data->lock, flags);
+
+       return status;
+}
+
+static inline int destroy_queue(struct driver_data *drv_data)
+{
+       int status;
+
+       status = stop_queue(drv_data);
+       if (status != 0)
+               return status;
+
+       destroy_workqueue(drv_data->workqueue);
+
+       return 0;
+}
+
+static int __init bfin5xx_spi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct bfin5xx_spi_master *platform_info;
+       struct spi_master *master;
+       struct driver_data *drv_data = 0;
+       int status = 0;
+
+       platform_info = dev->platform_data;
+
+       /* Allocate master with space for drv_data */
+       master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+       if (!master) {
+               dev_err(&pdev->dev, "can not alloc spi_master\n");
+               return -ENOMEM;
+       }
+       drv_data = spi_master_get_devdata(master);
+       drv_data->master = master;
+       drv_data->master_info = platform_info;
+       drv_data->pdev = pdev;
+
+       master->bus_num = pdev->id;
+       master->num_chipselect = platform_info->num_chipselect;
+       master->cleanup = cleanup;
+       master->setup = setup;
+       master->transfer = transfer;
+
+       /* Initial and start queue */
+       status = init_queue(drv_data);
+       if (status != 0) {
+               dev_err(&pdev->dev, "problem initializing queue\n");
+               goto out_error_queue_alloc;
+       }
+       status = start_queue(drv_data);
+       if (status != 0) {
+               dev_err(&pdev->dev, "problem starting queue\n");
+               goto out_error_queue_alloc;
+       }
+
+       /* Register with the SPI framework */
+       platform_set_drvdata(pdev, drv_data);
+       status = spi_register_master(master);
+       if (status != 0) {
+               dev_err(&pdev->dev, "problem registering spi master\n");
+               goto out_error_queue_alloc;
+       }
+       pr_debug("controller probe successfully\n");
+       return status;
+
+      out_error_queue_alloc:
+       destroy_queue(drv_data);
+       spi_master_put(master);
+       return status;
+}
+
+/* stop hardware and remove the driver */
+static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
+{
+       struct driver_data *drv_data = platform_get_drvdata(pdev);
+       int status = 0;
+
+       if (!drv_data)
+               return 0;
+
+       /* Remove the queue */
+       status = destroy_queue(drv_data);
+       if (status != 0)
+               return status;
+
+       /* Disable the SSP at the peripheral and SOC level */
+       bfin_spi_disable(drv_data);
+
+       /* Release DMA */
+       if (drv_data->master_info->enable_dma) {
+               if (dma_channel_active(CH_SPI))
+                       free_dma(CH_SPI);
+       }
+
+       /* Disconnect from the SPI framework */
+       spi_unregister_master(drv_data->master);
+
+       /* Prevent double remove */
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin5xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct driver_data *drv_data = platform_get_drvdata(pdev);
+       int status = 0;
+
+       status = stop_queue(drv_data);
+       if (status != 0)
+               return status;
+
+       /* stop hardware */
+       bfin_spi_disable(drv_data);
+
+       return 0;
+}
+
+static int bfin5xx_spi_resume(struct platform_device *pdev)
+{
+       struct driver_data *drv_data = platform_get_drvdata(pdev);
+       int status = 0;
+
+       /* Enable the SPI interface */
+       bfin_spi_enable(drv_data);
+
+       /* Start the queue running */
+       status = start_queue(drv_data);
+       if (status != 0) {
+               dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+               return status;
+       }
+
+       return 0;
+}
+#else
+#define bfin5xx_spi_suspend NULL
+#define bfin5xx_spi_resume NULL
+#endif                         /* CONFIG_PM */
+
+static struct platform_driver bfin5xx_spi_driver = {
+       .driver = {
+                  .name = "bfin-spi-master",
+                  .bus = &platform_bus_type,
+                  .owner = THIS_MODULE,
+                  },
+       .probe = bfin5xx_spi_probe,
+       .remove = __devexit_p(bfin5xx_spi_remove),
+       .suspend = bfin5xx_spi_suspend,
+       .resume = bfin5xx_spi_resume,
+};
+
+static int __init bfin5xx_spi_init(void)
+{
+       return platform_driver_register(&bfin5xx_spi_driver);
+}
+
+module_init(bfin5xx_spi_init);
+
+static void __exit bfin5xx_spi_exit(void)
+{
+       platform_driver_unregister(&bfin5xx_spi_driver);
+}
+
+module_exit(bfin5xx_spi_exit);
index b10211c..d5a710f 100644 (file)
@@ -342,8 +342,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
                goto err_register;
        }
 
-       dev_dbg(hw->dev, "shutdown=%d\n", hw->bitbang.shutdown);
-
        /* register all the devices associated */
 
        bi = &hw->pdata->board_info[0];
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 4d781a2..9310745 100644 (file)
@@ -73,13 +73,6 @@ static const struct hc_driver ps3_ehci_hc_driver = {
 #endif
 };
 
-#if !defined(DEBUG)
-#undef dev_dbg
-static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
-       const struct device *_dev, const char *fmt, ...) {return 0;}
-#endif
-
-
 static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
 {
        int result;
index 62283a3..c849f72 100644 (file)
@@ -75,14 +75,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
 #endif
 };
 
-/* redefine dev_dbg to do a syntax check */
-
-#if !defined(DEBUG)
-#undef dev_dbg
-static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
-       const struct device *_dev, const char *fmt, ...) {return 0;}
-#endif
-
 static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
 {
        int result;
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 a0cc05d..60d2944 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/usb.h>
 #include <linux/types.h>
 #include <linux/ethtool.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
index b1cb72c..344c375 100644 (file)
@@ -191,7 +191,7 @@ config FB_ARMCLCD
 
          If you want to compile this as a module (=code which can be
          inserted into and removed from the running kernel), say M
-         here and read <file:Documentation/modules.txt>.  The module
+         here and read <file:Documentation/kbuild/modules.txt>.  The module
          will be called amba-clcd.
 
 choice
@@ -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.
@@ -1380,6 +1383,32 @@ config FB_LEO
          This is the frame buffer device driver for the SBUS-based Sun ZX
          (leo) frame buffer cards.
 
+config FB_XVR500
+       bool "Sun XVR-500 3DLABS Wildcat support"
+       depends on FB && PCI && SPARC64
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the framebuffer device for the Sun XVR-500 and similar
+         graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+         only works on sparc64 systems where the system firwmare has
+         mostly initialized the card already.  It is treated as a
+         completely dumb framebuffer device.
+
+config FB_XVR2500
+       bool "Sun XVR-2500 3DLABS Wildcat support"
+       depends on FB && PCI && SPARC64
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the framebuffer device for the Sun XVR-2500 and similar
+         graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+         only works on sparc64 systems where the system firwmare has
+         mostly initialized the card already.  It is treated as a
+         completely dumb framebuffer device.
+
 config FB_PCI
        bool "PCI framebuffers"
        depends on (FB = y) && PCI && SPARC
@@ -1491,7 +1520,7 @@ config FB_PXA
          This driver is also available as a module ( = code which can be
          inserted and removed from the running kernel whenever you want). The
          module will be called pxafb. If you want to compile it as a module,
-         say M here and read <file:Documentation/modules.txt>.
+         say M here and read <file:Documentation/kbuild/modules.txt>.
 
          If unsure, say N.
 
@@ -1544,7 +1573,7 @@ config FB_W100
          This driver is also available as a module ( = code which can be
          inserted and removed from the running kernel whenever you want). The
          module will be called w100fb. If you want to compile it as a module,
-         say M here and read <file:Documentation/modules.txt>.
+         say M here and read <file:Documentation/kbuild/modules.txt>.
 
          If unsure, say N.
 
@@ -1561,7 +1590,7 @@ config FB_S3C2410
          This driver is also available as a module ( = code which can be
          inserted and removed from the running kernel whenever you want). The
          module will be called s3c2410fb. If you want to compile it as a module,
-         say M here and read <file:Documentation/modules.txt>.
+         say M here and read <file:Documentation/kbuild/modules.txt>.
 
          If unsure, say N.
 config FB_S3C2410_DEBUG
index 760305c..558473d 100644 (file)
@@ -63,9 +63,12 @@ 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_XVR500)           += sunxvr500.o
+obj-$(CONFIG_FB_XVR2500)          += sunxvr2500.o
 obj-$(CONFIG_FB_IGA)              += igafb.o
 obj-$(CONFIG_FB_APOLLO)           += dnfb.o
 obj-$(CONFIG_FB_Q40)              += q40fb.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>
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c
new file mode 100644 (file)
index 0000000..4316c7f
--- /dev/null
@@ -0,0 +1,277 @@
+/* s3d.c: Sun 3DLABS XVR-2500 et al. driver for sparc64 systems
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+
+struct s3d_info {
+       struct fb_info          *info;
+       struct pci_dev          *pdev;
+
+       char __iomem            *fb_base;
+       unsigned long           fb_base_phys;
+
+       struct device_node      *of_node;
+
+       unsigned int            width;
+       unsigned int            height;
+       unsigned int            depth;
+       unsigned int            fb_size;
+
+       u32                     pseudo_palette[256];
+};
+
+static int __devinit s3d_get_props(struct s3d_info *sp)
+{
+       sp->width = of_getintprop_default(sp->of_node, "width", 0);
+       sp->height = of_getintprop_default(sp->of_node, "height", 0);
+       sp->depth = of_getintprop_default(sp->of_node, "depth", 8);
+
+       if (!sp->width || !sp->height) {
+               printk(KERN_ERR "s3d: Critical properties missing for %s\n",
+                      pci_name(sp->pdev));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int s3d_setcolreg(unsigned regno,
+                        unsigned red, unsigned green, unsigned blue,
+                        unsigned transp, struct fb_info *info)
+{
+       u32 value;
+
+       if (regno >= 256)
+               return 1;
+
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+
+       value = (blue << 24) | (green << 16) | (red << 8);
+       ((u32 *)info->pseudo_palette)[regno] = value;
+
+       return 0;
+}
+
+static struct fb_ops s3d_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_setcolreg           = s3d_setcolreg,
+       .fb_fillrect            = cfb_fillrect,
+       .fb_copyarea            = cfb_copyarea,
+       .fb_imageblit           = cfb_imageblit,
+};
+
+static int __devinit s3d_set_fbinfo(struct s3d_info *sp)
+{
+       struct fb_info *info = sp->info;
+       struct fb_var_screeninfo *var = &info->var;
+
+       info->flags = FBINFO_DEFAULT;
+       info->fbops = &s3d_ops;
+       info->screen_base = sp->fb_base;
+       info->screen_size = sp->fb_size;
+
+       info->pseudo_palette = sp->pseudo_palette;
+
+       /* Fill fix common fields */
+       strlcpy(info->fix.id, "s3d", sizeof(info->fix.id));
+        info->fix.smem_start = sp->fb_base_phys;
+        info->fix.smem_len = sp->fb_size;
+        info->fix.type = FB_TYPE_PACKED_PIXELS;
+       if (sp->depth == 32 || sp->depth == 24)
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+       else
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+       var->xres = sp->width;
+       var->yres = sp->height;
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+       var->bits_per_pixel = sp->depth;
+
+       var->red.offset = 8;
+       var->red.length = 8;
+       var->green.offset = 16;
+       var->green.length = 8;
+       var->blue.offset = 24;
+       var->blue.length = 8;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+
+       if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+               printk(KERN_ERR "s3d: Cannot allocate color map.\n");
+               return -ENOMEM;
+       }
+
+        return 0;
+}
+
+static int __devinit s3d_pci_register(struct pci_dev *pdev,
+                                     const struct pci_device_id *ent)
+{
+       struct fb_info *info;
+       struct s3d_info *sp;
+       int err;
+
+       err = pci_enable_device(pdev);
+       if (err < 0) {
+               printk(KERN_ERR "s3d: Cannot enable PCI device %s\n",
+                      pci_name(pdev));
+               goto err_out;
+       }
+
+       info = framebuffer_alloc(sizeof(struct s3d_info), &pdev->dev);
+       if (!info) {
+               printk(KERN_ERR "s3d: Cannot allocate fb_info\n");
+               err = -ENOMEM;
+               goto err_disable;
+       }
+
+       sp = info->par;
+       sp->info = info;
+       sp->pdev = pdev;
+       sp->of_node = pci_device_to_OF_node(pdev);
+       if (!sp->of_node) {
+               printk(KERN_ERR "s3d: Cannot find OF node of %s\n",
+                      pci_name(pdev));
+               err = -ENODEV;
+               goto err_release_fb;
+       }
+
+       sp->fb_base_phys = pci_resource_start (pdev, 1);
+
+       err = pci_request_region(pdev, 1, "s3d framebuffer");
+       if (err < 0) {
+               printk("s3d: Cannot request region 1 for %s\n",
+                      pci_name(pdev));
+               goto err_release_fb;
+       }
+
+       err = s3d_get_props(sp);
+       if (err)
+               goto err_release_pci;
+
+       /* XXX 'linebytes' is often wrong, it is equal to the width
+        * XXX with depth of 32 on my XVR-2500 which is clearly not
+        * XXX right.  So we don't try to use it.
+        */
+       switch (sp->depth) {
+       case 8:
+               info->fix.line_length = sp->width;
+               break;
+       case 16:
+               info->fix.line_length = sp->width * 2;
+               break;
+       case 24:
+               info->fix.line_length = sp->width * 3;
+               break;
+       case 32:
+               info->fix.line_length = sp->width * 4;
+               break;
+       }
+       sp->fb_size = info->fix.line_length * sp->height;
+
+       sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size);
+       if (!sp->fb_base)
+               goto err_release_pci;
+
+       err = s3d_set_fbinfo(sp);
+       if (err)
+               goto err_unmap_fb;
+
+       pci_set_drvdata(pdev, info);
+
+       printk("s3d: Found device at %s\n", pci_name(pdev));
+
+       err = register_framebuffer(info);
+       if (err < 0) {
+               printk(KERN_ERR "s3d: Could not register framebuffer %s\n",
+                      pci_name(pdev));
+               goto err_unmap_fb;
+       }
+
+       return 0;
+
+err_unmap_fb:
+       iounmap(sp->fb_base);
+
+err_release_pci:
+       pci_release_region(pdev, 1);
+
+err_release_fb:
+        framebuffer_release(info);
+
+err_disable:
+       pci_disable_device(pdev);
+
+err_out:
+       return err;
+}
+
+static void __devexit s3d_pci_unregister(struct pci_dev *pdev)
+{
+       struct fb_info *info = pci_get_drvdata(pdev);
+       struct s3d_info *sp = info->par;
+
+       unregister_framebuffer(info);
+
+       iounmap(sp->fb_base);
+
+       pci_release_region(pdev, 1);
+
+        framebuffer_release(info);
+
+       pci_disable_device(pdev);
+}
+
+static struct pci_device_id s3d_pci_table[] = {
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002c),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002d),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002e),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002f),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0030),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0031),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0032),       },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0033),       },
+       { 0, }
+};
+
+static struct pci_driver s3d_driver = {
+       .name           = "s3d",
+       .id_table       = s3d_pci_table,
+       .probe          = s3d_pci_register,
+       .remove         = __devexit_p(s3d_pci_unregister),
+};
+
+static int __init s3d_init(void)
+{
+       if (fb_get_options("s3d", NULL))
+               return -ENODEV;
+
+       return pci_register_driver(&s3d_driver);
+}
+
+static void __exit s3d_exit(void)
+{
+       pci_unregister_driver(&s3d_driver);
+}
+
+module_init(s3d_init);
+module_exit(s3d_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for Sun XVR-2500 graphics");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
new file mode 100644 (file)
index 0000000..08880a6
--- /dev/null
@@ -0,0 +1,443 @@
+/* sunxvr500.c: Sun 3DLABS XVR-500 Expert3D driver for sparc64 systems
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+
+/* XXX This device has a 'dev-comm' property which aparently is
+ * XXX a pointer into the openfirmware's address space which is
+ * XXX a shared area the kernel driver can use to keep OBP
+ * XXX informed about the current resolution setting.  The idea
+ * XXX is that the kernel can change resolutions, and as long
+ * XXX as the values in the 'dev-comm' area are accurate then
+ * XXX OBP can still render text properly to the console.
+ * XXX
+ * XXX I'm still working out the layout of this and whether there
+ * XXX are any signatures we need to look for etc.
+ */
+struct e3d_info {
+       struct fb_info          *info;
+       struct pci_dev          *pdev;
+
+       spinlock_t              lock;
+
+       char __iomem            *fb_base;
+       unsigned long           fb_base_phys;
+
+       unsigned long           fb8_buf_diff;
+       unsigned long           regs_base_phys;
+
+       void __iomem            *ramdac;
+
+       struct device_node      *of_node;
+
+       unsigned int            width;
+       unsigned int            height;
+       unsigned int            depth;
+       unsigned int            fb_size;
+
+       u32                     fb_base_reg;
+       u32                     fb8_0_off;
+       u32                     fb8_1_off;
+
+       u32                     pseudo_palette[256];
+};
+
+static int __devinit e3d_get_props(struct e3d_info *ep)
+{
+       ep->width = of_getintprop_default(ep->of_node, "width", 0);
+       ep->height = of_getintprop_default(ep->of_node, "height", 0);
+       ep->depth = of_getintprop_default(ep->of_node, "depth", 8);
+
+       if (!ep->width || !ep->height) {
+               printk(KERN_ERR "e3d: Critical properties missing for %s\n",
+                      pci_name(ep->pdev));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* My XVR-500 comes up, at 1280x768 and a FB base register value of
+ * 0x04000000, the following video layout register values:
+ *
+ * RAMDAC_VID_WH       0x03ff04ff
+ * RAMDAC_VID_CFG      0x1a0b0088
+ * RAMDAC_VID_32FB_0   0x04000000
+ * RAMDAC_VID_32FB_1   0x04800000
+ * RAMDAC_VID_8FB_0    0x05000000
+ * RAMDAC_VID_8FB_1    0x05200000
+ * RAMDAC_VID_XXXFB    0x05400000
+ * RAMDAC_VID_YYYFB    0x05c00000
+ * RAMDAC_VID_ZZZFB    0x05e00000
+ */
+/* Video layout registers */
+#define RAMDAC_VID_WH          0x00000070UL /* (height-1)<<16 | (width-1) */
+#define RAMDAC_VID_CFG         0x00000074UL /* 0x1a000088|(linesz_log2<<16) */
+#define RAMDAC_VID_32FB_0      0x00000078UL /* PCI base 32bpp FB buffer 0 */
+#define RAMDAC_VID_32FB_1      0x0000007cUL /* PCI base 32bpp FB buffer 1 */
+#define RAMDAC_VID_8FB_0       0x00000080UL /* PCI base 8bpp FB buffer 0 */
+#define RAMDAC_VID_8FB_1       0x00000084UL /* PCI base 8bpp FB buffer 1 */
+#define RAMDAC_VID_XXXFB       0x00000088UL /* PCI base of XXX FB */
+#define RAMDAC_VID_YYYFB       0x0000008cUL /* PCI base of YYY FB */
+#define RAMDAC_VID_ZZZFB       0x00000090UL /* PCI base of ZZZ FB */
+
+/* CLUT registers */
+#define RAMDAC_INDEX           0x000000bcUL
+#define RAMDAC_DATA            0x000000c0UL
+
+static void e3d_clut_write(struct e3d_info *ep, int index, u32 val)
+{
+       void __iomem *ramdac = ep->ramdac;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       writel(index, ramdac + RAMDAC_INDEX);
+       writel(val, ramdac + RAMDAC_DATA);
+
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static int e3d_setcolreg(unsigned regno,
+                        unsigned red, unsigned green, unsigned blue,
+                        unsigned transp, struct fb_info *info)
+{
+       struct e3d_info *ep = info->par;
+       u32 red_8, green_8, blue_8;
+       u32 red_10, green_10, blue_10;
+       u32 value;
+
+       if (regno >= 256)
+               return 1;
+
+       red_8 = red >> 8;
+       green_8 = green >> 8;
+       blue_8 = blue >> 8;
+
+       value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8);
+       ((u32 *)info->pseudo_palette)[regno] = value;
+
+
+       red_10 = red >> 6;
+       green_10 = green >> 6;
+       blue_10 = blue >> 6;
+
+       value = (blue_10 << 20) | (green_10 << 10) | (red_10 << 0);
+       e3d_clut_write(ep, regno, value);
+
+       return 0;
+}
+
+/* XXX This is a bit of a hack.  I can't figure out exactly how the
+ * XXX two 8bpp areas of the framebuffer work.  I imagine there is
+ * XXX a WID attribute somewhere else in the framebuffer which tells
+ * XXX the ramdac which of the two 8bpp framebuffer regions to take
+ * XXX the pixel from.  So, for now, render into both regions to make
+ * XXX sure the pixel shows up.
+ */
+static void e3d_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct e3d_info *ep = info->par;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       cfb_imageblit(info, image);
+       info->screen_base += ep->fb8_buf_diff;
+       cfb_imageblit(info, image);
+       info->screen_base -= ep->fb8_buf_diff;
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static void e3d_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       struct e3d_info *ep = info->par;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       cfb_fillrect(info, rect);
+       info->screen_base += ep->fb8_buf_diff;
+       cfb_fillrect(info, rect);
+       info->screen_base -= ep->fb8_buf_diff;
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static void e3d_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+       struct e3d_info *ep = info->par;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       cfb_copyarea(info, area);
+       info->screen_base += ep->fb8_buf_diff;
+       cfb_copyarea(info, area);
+       info->screen_base -= ep->fb8_buf_diff;
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static struct fb_ops e3d_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_setcolreg           = e3d_setcolreg,
+       .fb_fillrect            = e3d_fillrect,
+       .fb_copyarea            = e3d_copyarea,
+       .fb_imageblit           = e3d_imageblit,
+};
+
+static int __devinit e3d_set_fbinfo(struct e3d_info *ep)
+{
+       struct fb_info *info = ep->info;
+       struct fb_var_screeninfo *var = &info->var;
+
+       info->flags = FBINFO_DEFAULT;
+       info->fbops = &e3d_ops;
+       info->screen_base = ep->fb_base;
+       info->screen_size = ep->fb_size;
+
+       info->pseudo_palette = ep->pseudo_palette;
+
+       /* Fill fix common fields */
+       strlcpy(info->fix.id, "e3d", sizeof(info->fix.id));
+        info->fix.smem_start = ep->fb_base_phys;
+        info->fix.smem_len = ep->fb_size;
+        info->fix.type = FB_TYPE_PACKED_PIXELS;
+       if (ep->depth == 32 || ep->depth == 24)
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+       else
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+       var->xres = ep->width;
+       var->yres = ep->height;
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+       var->bits_per_pixel = ep->depth;
+
+       var->red.offset = 8;
+       var->red.length = 8;
+       var->green.offset = 16;
+       var->green.length = 8;
+       var->blue.offset = 24;
+       var->blue.length = 8;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+
+       if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+               printk(KERN_ERR "e3d: Cannot allocate color map.\n");
+               return -ENOMEM;
+       }
+
+        return 0;
+}
+
+static int __devinit e3d_pci_register(struct pci_dev *pdev,
+                                     const struct pci_device_id *ent)
+{
+       struct fb_info *info;
+       struct e3d_info *ep;
+       unsigned int line_length;
+       int err;
+
+       err = pci_enable_device(pdev);
+       if (err < 0) {
+               printk(KERN_ERR "e3d: Cannot enable PCI device %s\n",
+                      pci_name(pdev));
+               goto err_out;
+       }
+
+       info = framebuffer_alloc(sizeof(struct e3d_info), &pdev->dev);
+       if (!info) {
+               printk(KERN_ERR "e3d: Cannot allocate fb_info\n");
+               err = -ENOMEM;
+               goto err_disable;
+       }
+
+       ep = info->par;
+       ep->info = info;
+       ep->pdev = pdev;
+       spin_lock_init(&ep->lock);
+       ep->of_node = pci_device_to_OF_node(pdev);
+       if (!ep->of_node) {
+               printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
+                      pci_name(pdev));
+               err = -ENODEV;
+               goto err_release_fb;
+       }
+
+       /* Read the PCI base register of the frame buffer, which we
+        * need in order to interpret the RAMDAC_VID_*FB* values in
+        * the ramdac correctly.
+        */
+       pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
+                             &ep->fb_base_reg);
+       ep->fb_base_reg &= PCI_BASE_ADDRESS_MEM_MASK;
+
+       ep->regs_base_phys = pci_resource_start (pdev, 1);
+       err = pci_request_region(pdev, 1, "e3d regs");
+       if (err < 0) {
+               printk("e3d: Cannot request region 1 for %s\n",
+                      pci_name(pdev));
+               goto err_release_fb;
+       }
+       ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
+       if (!ep->ramdac)
+               goto err_release_pci1;
+
+       ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
+       ep->fb8_0_off -= ep->fb_base_reg;
+
+       ep->fb8_1_off = readl(ep->ramdac + RAMDAC_VID_8FB_1);
+       ep->fb8_1_off -= ep->fb_base_reg;
+
+       ep->fb8_buf_diff = ep->fb8_1_off - ep->fb8_0_off;
+
+       ep->fb_base_phys = pci_resource_start (pdev, 0);
+       ep->fb_base_phys += ep->fb8_0_off;
+
+       err = pci_request_region(pdev, 0, "e3d framebuffer");
+       if (err < 0) {
+               printk("e3d: Cannot request region 0 for %s\n",
+                      pci_name(pdev));
+               goto err_unmap_ramdac;
+       }
+
+       err = e3d_get_props(ep);
+       if (err)
+               goto err_release_pci0;
+
+       line_length = (readl(ep->ramdac + RAMDAC_VID_CFG) >> 16) & 0xff;
+       line_length = 1 << line_length;
+
+       switch (ep->depth) {
+       case 8:
+               info->fix.line_length = line_length;
+               break;
+       case 16:
+               info->fix.line_length = line_length * 2;
+               break;
+       case 24:
+               info->fix.line_length = line_length * 3;
+               break;
+       case 32:
+               info->fix.line_length = line_length * 4;
+               break;
+       }
+       ep->fb_size = info->fix.line_length * ep->height;
+
+       ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
+       if (!ep->fb_base)
+               goto err_release_pci0;
+
+       err = e3d_set_fbinfo(ep);
+       if (err)
+               goto err_unmap_fb;
+
+       pci_set_drvdata(pdev, info);
+
+       printk("e3d: Found device at %s\n", pci_name(pdev));
+
+       err = register_framebuffer(info);
+       if (err < 0) {
+               printk(KERN_ERR "e3d: Could not register framebuffer %s\n",
+                      pci_name(pdev));
+               goto err_unmap_fb;
+       }
+
+       return 0;
+
+err_unmap_fb:
+       iounmap(ep->fb_base);
+
+err_release_pci0:
+       pci_release_region(pdev, 0);
+
+err_unmap_ramdac:
+       iounmap(ep->ramdac);
+
+err_release_pci1:
+       pci_release_region(pdev, 1);
+
+err_release_fb:
+        framebuffer_release(info);
+
+err_disable:
+       pci_disable_device(pdev);
+
+err_out:
+       return err;
+}
+
+static void __devexit e3d_pci_unregister(struct pci_dev *pdev)
+{
+       struct fb_info *info = pci_get_drvdata(pdev);
+       struct e3d_info *ep = info->par;
+
+       unregister_framebuffer(info);
+
+       iounmap(ep->ramdac);
+       iounmap(ep->fb_base);
+
+       pci_release_region(pdev, 0);
+       pci_release_region(pdev, 1);
+
+        framebuffer_release(info);
+
+       pci_disable_device(pdev);
+}
+
+static struct pci_device_id e3d_pci_table[] = {
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0),        },
+       {       PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2),        },
+       {       .vendor = PCI_VENDOR_ID_3DLABS,
+               .device = PCI_ANY_ID,
+               .subvendor = PCI_VENDOR_ID_3DLABS,
+               .subdevice = 0x0108,
+       },
+       {       .vendor = PCI_VENDOR_ID_3DLABS,
+               .device = PCI_ANY_ID,
+               .subvendor = PCI_VENDOR_ID_3DLABS,
+               .subdevice = 0x0140,
+       },
+       {       .vendor = PCI_VENDOR_ID_3DLABS,
+               .device = PCI_ANY_ID,
+               .subvendor = PCI_VENDOR_ID_3DLABS,
+               .subdevice = 0x1024,
+       },
+       { 0, }
+};
+
+static struct pci_driver e3d_driver = {
+       .name           = "e3d",
+       .id_table       = e3d_pci_table,
+       .probe          = e3d_pci_register,
+       .remove         = __devexit_p(e3d_pci_unregister),
+};
+
+static int __init e3d_init(void)
+{
+       if (fb_get_options("e3d", NULL))
+               return -ENODEV;
+
+       return pci_register_driver(&e3d_driver);
+}
+
+static void __exit e3d_exit(void)
+{
+       pci_unregister_driver(&e3d_driver);
+}
+
+module_init(e3d_init);
+module_exit(e3d_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for Sun XVR-500 graphics");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
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 f3d3d81..74c6440 100644 (file)
@@ -26,7 +26,7 @@ config BINFMT_ELF
 config BINFMT_ELF_FDPIC
        bool "Kernel support for FDPIC ELF binaries"
        default y
-       depends on FRV
+       depends on (FRV || BLACKFIN)
        help
          ELF FDPIC binaries are based on ELF, but allow the individual load
          segments of a binary to be located in memory independently of each
index 2e5f2c8..30c2965 100644 (file)
@@ -232,8 +232,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index c3986a1..beff7d2 100644 (file)
@@ -87,8 +87,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct affs_inode_info *ei = (struct affs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                init_MUTEX(&ei->i_link_lock);
                init_MUTEX(&ei->i_ext_lock);
                inode_init_once(&ei->vfs_inode);
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 dac5b99..0c1e902 100644 (file)
@@ -194,10 +194,7 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
 
        page = read_mapping_page(dir->i_mapping, index, &file);
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
                kmap(page);
-               if (!PageUptodate(page))
-                       goto fail;
                if (!PageChecked(page))
                        afs_dir_check_page(dir, page);
                if (PageError(page))
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;
 
index b905ae3..034fcfd 100644 (file)
@@ -68,13 +68,11 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
        }
 
        ret = -EIO;
-       wait_on_page_locked(page);
-       buf = kmap(page);
-       if (!PageUptodate(page))
-               goto out_free;
        if (PageError(page))
                goto out_free;
 
+       buf = kmap(page);
+
        /* examine the symlink's contents */
        size = vnode->status.size;
        _debug("symlink to %*.*s", (int) size, (int) size, buf);
@@ -91,8 +89,8 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
 
        ret = 0;
 
-out_free:
        kunmap(page);
+out_free:
        page_cache_release(page);
 out:
        _leave(" = %d", ret);
@@ -171,8 +169,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
        }
 
        ret = -EIO;
-       wait_on_page_locked(page);
-       if (!PageUptodate(page) || PageError(page))
+       if (PageError(page))
                goto error;
 
        buf = kmap(page);
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..7030d76 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;
@@ -467,8 +453,7 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
 {
        struct afs_vnode *vnode = _vnode;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                memset(vnode, 0, sizeof(*vnode));
                inode_init_once(&vnode->vfs_inode);
                init_waitqueue_head(&vnode->update_waitq);
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 e4598d6..b97ab80 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -68,10 +68,8 @@ static void aio_queue_work(struct kioctx *);
  */
 static int __init aio_setup(void)
 {
-       kiocb_cachep = kmem_cache_create("kiocb", sizeof(struct kiocb),
-                               0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
-       kioctx_cachep = kmem_cache_create("kioctx", sizeof(struct kioctx),
-                               0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
+       kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        aio_wq = create_workqueue("aio");
 
index cc6cc8e..fe96108 100644 (file)
@@ -293,8 +293,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
         struct befs_inode_info *bi = (struct befs_inode_info *) foo;
        
-               if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-                           SLAB_CTOR_CONSTRUCTOR) {
+               if (flags & SLAB_CTOR_CONSTRUCTOR) {
                        inode_init_once(&bi->vfs_inode);
                }
 }
index 93d6219..edc08d8 100644 (file)
@@ -248,8 +248,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct bfs_inode_info *bi = foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&bi->vfs_inode);
 }
  
index 693940d..093345f 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1193,8 +1193,7 @@ static void __init biovec_init_slabs(void)
 
 static int __init init_bio(void)
 {
-       bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
-                               SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       bio_slab = KMEM_CACHE(bio, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        biovec_init_slabs();
 
index 575076c..f02b7bd 100644 (file)
@@ -55,10 +55,12 @@ static sector_t max_block(struct block_device *bdev)
        return retval;
 }
 
-/* Kill _all_ buffers, dirty or not.. */
+/* Kill _all_ buffers and pagecache , dirty or not.. */
 static void kill_bdev(struct block_device *bdev)
 {
-       invalidate_bdev(bdev, 1);
+       if (bdev->bd_inode->i_mapping->nrpages == 0)
+               return;
+       invalidate_bh_lrus();
        truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
 }      
 
@@ -455,9 +457,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
        struct bdev_inode *ei = (struct bdev_inode *) foo;
        struct block_device *bdev = &ei->bdev;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
-       {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                memset(bdev, 0, sizeof(*bdev));
                mutex_init(&bdev->bd_mutex);
                sema_init(&bdev->bd_mount_sem, 1);
@@ -1478,7 +1478,7 @@ int __invalidate_device(struct block_device *bdev)
                res = invalidate_inodes(sb);
                drop_super(sb);
        }
-       invalidate_bdev(bdev, 0);
+       invalidate_bdev(bdev);
        return res;
 }
 EXPORT_SYMBOL(__invalidate_device);
index 1d0852f..7db24b9 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/bit_spinlock.h>
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
-static void invalidate_bh_lrus(void);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
 
@@ -333,7 +332,7 @@ out:
    we think the disk contains more recent information than the buffercache.
    The update == 1 pass marks the buffers we need to update, the update == 2
    pass does the actual I/O. */
-void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
+void invalidate_bdev(struct block_device *bdev)
 {
        struct address_space *mapping = bdev->bd_inode->i_mapping;
 
@@ -341,11 +340,6 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
                return;
 
        invalidate_bh_lrus();
-       /*
-        * FIXME: what about destroy_dirty_buffers?
-        * We really want to use invalidate_inode_pages2() for
-        * that, but not until that's cleaned up.
-        */
        invalidate_mapping_pages(mapping, 0, -1);
 }
 
@@ -1408,7 +1402,7 @@ static void invalidate_bh_lru(void *arg)
        put_cpu_var(bh_lrus);
 }
        
-static void invalidate_bh_lrus(void)
+void invalidate_bh_lrus(void)
 {
        on_each_cpu(invalidate_bh_lru, NULL, 1, 1);
 }
@@ -1700,17 +1694,8 @@ done:
                 * clean.  Someone wrote them back by hand with
                 * ll_rw_block/submit_bh.  A rare case.
                 */
-               int uptodate = 1;
-               do {
-                       if (!buffer_uptodate(bh)) {
-                               uptodate = 0;
-                               break;
-                       }
-                       bh = bh->b_this_page;
-               } while (bh != head);
-               if (uptodate)
-                       SetPageUptodate(page);
                end_page_writeback(page);
+
                /*
                 * The page and buffer_heads can be released at any time from
                 * here on.
@@ -2968,8 +2953,7 @@ EXPORT_SYMBOL(free_buffer_head);
 static void
 init_buffer_head(void *data, struct kmem_cache *cachep, unsigned long flags)
 {
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-                           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                struct buffer_head * bh = (struct buffer_head *)data;
 
                memset(bh, 0, sizeof(*bh));
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..8568e10 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)
@@ -694,8 +701,7 @@ cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags)
 {
        struct cifsInodeInfo *cifsi = inode;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&cifsi->vfs_inode);
                INIT_LIST_HEAD(&cifsi->lockList);
        }
@@ -724,7 +730,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 +747,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 +757,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 +778,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 +788,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 +818,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 +856,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 +877,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 +894,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 +928,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 +977,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 614175a..0aaff36 100644 (file)
@@ -62,8 +62,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct coda_inode_info *ei = (struct coda_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
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 facd0c8..3d194a2 100644 (file)
@@ -180,7 +180,8 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
                struct page *page = NULL;
 
                if (blocknr + i < devsize) {
-                       page = read_mapping_page(mapping, blocknr + i, NULL);
+                       page = read_mapping_page_async(mapping, blocknr + i,
+                                                                       NULL);
                        /* synchronous error? */
                        if (IS_ERR(page))
                                page = NULL;
index d68631f..d1bf5d8 100644 (file)
@@ -2052,12 +2052,8 @@ static void __init dcache_init(unsigned long mempages)
         * but it is probably not worth it because of the cache nature
         * of the dcache. 
         */
-       dentry_cache = kmem_cache_create("dentry_cache",
-                                        sizeof(struct dentry),
-                                        0,
-                                        (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
-                                        SLAB_MEM_SPREAD),
-                                        NULL, NULL);
+       dentry_cache = KMEM_CACHE(dentry,
+               SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
        
        set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
 
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 6fa7b0d..69a9469 100644 (file)
@@ -3,36 +3,19 @@ menu "Distributed Lock Manager"
 
 config DLM
        tristate "Distributed Lock Manager (DLM)"
-       depends on SYSFS && (IPV6 || IPV6=n)
+       depends on IPV6 || IPV6=n
        select CONFIGFS_FS
-       select IP_SCTP if DLM_SCTP
+       select IP_SCTP
        help
-         A general purpose distributed lock manager for kernel or userspace
-         applications.
-
-choice
-       prompt "Select DLM communications protocol"
-       depends on DLM
-       default DLM_TCP
-       help
-         The DLM Can use TCP or SCTP for it's network communications.
-         SCTP supports multi-homed operations whereas TCP doesn't.
-         However, SCTP seems to have stability problems at the moment.
-
-config DLM_TCP
-       bool "TCP/IP"
-
-config DLM_SCTP
-       bool "SCTP"
-
-endchoice
+       A general purpose distributed lock manager for kernel or userspace
+       applications.
 
 config DLM_DEBUG
        bool "DLM debugging"
        depends on DLM
        help
-         Under the debugfs mount point, the name of each lockspace will
-         appear as a file in the "dlm" directory.  The output is the
-         list of resource and locks the local node knows about.
+       Under the debugfs mount point, the name of each lockspace will
+       appear as a file in the "dlm" directory.  The output is the
+       list of resource and locks the local node knows about.
 
 endmenu
index 6538894..604cf7d 100644 (file)
@@ -8,14 +8,12 @@ dlm-y :=                      ast.o \
                                member.o \
                                memory.o \
                                midcomms.o \
+                               lowcomms.o \
                                rcom.o \
                                recover.o \
                                recoverd.o \
                                requestqueue.o \
                                user.o \
-                               util.o
+                               util.o 
 dlm-$(CONFIG_DLM_DEBUG) +=     debug_fs.o
 
-dlm-$(CONFIG_DLM_TCP)   += lowcomms-tcp.o
-
-dlm-$(CONFIG_DLM_SCTP)  += lowcomms-sctp.o
\ No newline at end of file
index f91d39c..6308122 100644 (file)
@@ -14,6 +14,7 @@
 #include "dlm_internal.h"
 #include "lock.h"
 #include "user.h"
+#include "ast.h"
 
 #define WAKE_ASTS  0
 
index 8665c88..822abdc 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -89,6 +89,7 @@ struct cluster {
        unsigned int cl_toss_secs;
        unsigned int cl_scan_secs;
        unsigned int cl_log_debug;
+       unsigned int cl_protocol;
 };
 
 enum {
@@ -101,6 +102,7 @@ enum {
        CLUSTER_ATTR_TOSS_SECS,
        CLUSTER_ATTR_SCAN_SECS,
        CLUSTER_ATTR_LOG_DEBUG,
+       CLUSTER_ATTR_PROTOCOL,
 };
 
 struct cluster_attribute {
@@ -159,6 +161,7 @@ CLUSTER_ATTR(recover_timer, 1);
 CLUSTER_ATTR(toss_secs, 1);
 CLUSTER_ATTR(scan_secs, 1);
 CLUSTER_ATTR(log_debug, 0);
+CLUSTER_ATTR(protocol, 0);
 
 static struct configfs_attribute *cluster_attrs[] = {
        [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -170,6 +173,7 @@ static struct configfs_attribute *cluster_attrs[] = {
        [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
        [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
        [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
+       [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
        NULL,
 };
 
@@ -904,6 +908,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
 #define DEFAULT_TOSS_SECS         10
 #define DEFAULT_SCAN_SECS          5
 #define DEFAULT_LOG_DEBUG          0
+#define DEFAULT_PROTOCOL           0
 
 struct dlm_config_info dlm_config = {
        .ci_tcp_port = DEFAULT_TCP_PORT,
@@ -914,6 +919,7 @@ struct dlm_config_info dlm_config = {
        .ci_recover_timer = DEFAULT_RECOVER_TIMER,
        .ci_toss_secs = DEFAULT_TOSS_SECS,
        .ci_scan_secs = DEFAULT_SCAN_SECS,
-       .ci_log_debug = DEFAULT_LOG_DEBUG
+       .ci_log_debug = DEFAULT_LOG_DEBUG,
+       .ci_protocol = DEFAULT_PROTOCOL
 };
 
index 1e97861..967cc3d 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -26,6 +26,7 @@ struct dlm_config_info {
        int ci_toss_secs;
        int ci_scan_secs;
        int ci_log_debug;
+       int ci_protocol;
 };
 
 extern struct dlm_config_info dlm_config;
index 61d9320..30994d6 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -210,6 +210,9 @@ struct dlm_args {
 #define DLM_IFL_MSTCPY         0x00010000
 #define DLM_IFL_RESEND         0x00020000
 #define DLM_IFL_DEAD           0x00040000
+#define DLM_IFL_OVERLAP_UNLOCK  0x00080000
+#define DLM_IFL_OVERLAP_CANCEL  0x00100000
+#define DLM_IFL_ENDOFLIFE      0x00200000
 #define DLM_IFL_USER           0x00000001
 #define DLM_IFL_ORPHAN         0x00000002
 
@@ -230,8 +233,8 @@ struct dlm_lkb {
        int8_t                  lkb_grmode;     /* granted lock mode */
        int8_t                  lkb_bastmode;   /* requested mode */
        int8_t                  lkb_highbast;   /* highest mode bast sent for */
-
        int8_t                  lkb_wait_type;  /* type of reply waiting for */
+       int8_t                  lkb_wait_count;
        int8_t                  lkb_ast_type;   /* type of ast queued for */
 
        struct list_head        lkb_idtbl_list; /* lockspace lkbtbl */
@@ -339,6 +342,7 @@ struct dlm_header {
 #define DLM_MSG_LOOKUP         11
 #define DLM_MSG_REMOVE         12
 #define DLM_MSG_LOOKUP_REPLY   13
+#define DLM_MSG_PURGE          14
 
 struct dlm_message {
        struct dlm_header       m_header;
@@ -440,6 +444,9 @@ struct dlm_ls {
        struct mutex            ls_waiters_mutex;
        struct list_head        ls_waiters;     /* lkbs needing a reply */
 
+       struct mutex            ls_orphans_mutex;
+       struct list_head        ls_orphans;
+
        struct list_head        ls_nodes;       /* current nodes in ls */
        struct list_head        ls_nodes_gone;  /* dead node list, recovery */
        int                     ls_num_nodes;   /* number of nodes in ls */
index e725005..d8d6e72 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -85,6 +85,7 @@ static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
 static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
                                    struct dlm_message *ms);
 static int receive_extralen(struct dlm_message *ms);
+static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
 
 /*
  * Lock compatibilty matrix - thanks Steve
@@ -223,6 +224,16 @@ static inline int is_demoted(struct dlm_lkb *lkb)
        return (lkb->lkb_sbflags & DLM_SBF_DEMOTED);
 }
 
+static inline int is_altmode(struct dlm_lkb *lkb)
+{
+       return (lkb->lkb_sbflags & DLM_SBF_ALTMODE);
+}
+
+static inline int is_granted(struct dlm_lkb *lkb)
+{
+       return (lkb->lkb_status == DLM_LKSTS_GRANTED);
+}
+
 static inline int is_remote(struct dlm_rsb *r)
 {
        DLM_ASSERT(r->res_nodeid >= 0, dlm_print_rsb(r););
@@ -254,6 +265,22 @@ static inline int down_conversion(struct dlm_lkb *lkb)
        return (!middle_conversion(lkb) && lkb->lkb_rqmode < lkb->lkb_grmode);
 }
 
+static inline int is_overlap_unlock(struct dlm_lkb *lkb)
+{
+       return lkb->lkb_flags & DLM_IFL_OVERLAP_UNLOCK;
+}
+
+static inline int is_overlap_cancel(struct dlm_lkb *lkb)
+{
+       return lkb->lkb_flags & DLM_IFL_OVERLAP_CANCEL;
+}
+
+static inline int is_overlap(struct dlm_lkb *lkb)
+{
+       return (lkb->lkb_flags & (DLM_IFL_OVERLAP_UNLOCK |
+                                 DLM_IFL_OVERLAP_CANCEL));
+}
+
 static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
 {
        if (is_master_copy(lkb))
@@ -267,6 +294,12 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
        dlm_add_ast(lkb, AST_COMP);
 }
 
+static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
+{
+       queue_cast(r, lkb,
+                  is_overlap_unlock(lkb) ? -DLM_EUNLOCK : -DLM_ECANCEL);
+}
+
 static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
 {
        if (is_master_copy(lkb))
@@ -547,6 +580,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
        lkb->lkb_grmode = DLM_LOCK_IV;
        kref_init(&lkb->lkb_ref);
        INIT_LIST_HEAD(&lkb->lkb_ownqueue);
+       INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
 
        get_random_bytes(&bucket, sizeof(bucket));
        bucket &= (ls->ls_lkbtbl_size - 1);
@@ -556,7 +590,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
        /* counter can roll over so we must verify lkid is not in use */
 
        while (lkid == 0) {
-               lkid = bucket | (ls->ls_lkbtbl[bucket].counter++ << 16);
+               lkid = (bucket << 16) | ls->ls_lkbtbl[bucket].counter++;
 
                list_for_each_entry(tmp, &ls->ls_lkbtbl[bucket].list,
                                    lkb_idtbl_list) {
@@ -577,8 +611,8 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
 
 static struct dlm_lkb *__find_lkb(struct dlm_ls *ls, uint32_t lkid)
 {
-       uint16_t bucket = lkid & 0xFFFF;
        struct dlm_lkb *lkb;
+       uint16_t bucket = (lkid >> 16);
 
        list_for_each_entry(lkb, &ls->ls_lkbtbl[bucket].list, lkb_idtbl_list) {
                if (lkb->lkb_id == lkid)
@@ -590,7 +624,7 @@ static struct dlm_lkb *__find_lkb(struct dlm_ls *ls, uint32_t lkid)
 static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
 {
        struct dlm_lkb *lkb;
-       uint16_t bucket = lkid & 0xFFFF;
+       uint16_t bucket = (lkid >> 16);
 
        if (bucket >= ls->ls_lkbtbl_size)
                return -EBADSLT;
@@ -620,7 +654,7 @@ static void kill_lkb(struct kref *kref)
 
 static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
 {
-       uint16_t bucket = lkb->lkb_id & 0xFFFF;
+       uint16_t bucket = (lkb->lkb_id >> 16);
 
        write_lock(&ls->ls_lkbtbl[bucket].lock);
        if (kref_put(&lkb->lkb_ref, kill_lkb)) {
@@ -735,23 +769,75 @@ static void move_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int sts)
        unhold_lkb(lkb);
 }
 
+static int msg_reply_type(int mstype)
+{
+       switch (mstype) {
+       case DLM_MSG_REQUEST:
+               return DLM_MSG_REQUEST_REPLY;
+       case DLM_MSG_CONVERT:
+               return DLM_MSG_CONVERT_REPLY;
+       case DLM_MSG_UNLOCK:
+               return DLM_MSG_UNLOCK_REPLY;
+       case DLM_MSG_CANCEL:
+               return DLM_MSG_CANCEL_REPLY;
+       case DLM_MSG_LOOKUP:
+               return DLM_MSG_LOOKUP_REPLY;
+       }
+       return -1;
+}
+
 /* add/remove lkb from global waiters list of lkb's waiting for
    a reply from a remote node */
 
-static void add_to_waiters(struct dlm_lkb *lkb, int mstype)
+static int add_to_waiters(struct dlm_lkb *lkb, int mstype)
 {
        struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+       int error = 0;
 
        mutex_lock(&ls->ls_waiters_mutex);
-       if (lkb->lkb_wait_type) {
-               log_print("add_to_waiters error %d", lkb->lkb_wait_type);
+
+       if (is_overlap_unlock(lkb) ||
+           (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL))) {
+               error = -EINVAL;
+               goto out;
+       }
+
+       if (lkb->lkb_wait_type || is_overlap_cancel(lkb)) {
+               switch (mstype) {
+               case DLM_MSG_UNLOCK:
+                       lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
+                       break;
+               case DLM_MSG_CANCEL:
+                       lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
+                       break;
+               default:
+                       error = -EBUSY;
+                       goto out;
+               }
+               lkb->lkb_wait_count++;
+               hold_lkb(lkb);
+
+               log_debug(ls, "add overlap %x cur %d new %d count %d flags %x",
+                         lkb->lkb_id, lkb->lkb_wait_type, mstype,
+                         lkb->lkb_wait_count, lkb->lkb_flags);
                goto out;
        }
+
+       DLM_ASSERT(!lkb->lkb_wait_count,
+                  dlm_print_lkb(lkb);
+                  printk("wait_count %d\n", lkb->lkb_wait_count););
+
+       lkb->lkb_wait_count++;
        lkb->lkb_wait_type = mstype;
-       kref_get(&lkb->lkb_ref);
+       hold_lkb(lkb);
        list_add(&lkb->lkb_wait_reply, &ls->ls_waiters);
  out:
+       if (error)
+               log_error(ls, "add_to_waiters %x error %d flags %x %d %d %s",
+                         lkb->lkb_id, error, lkb->lkb_flags, mstype,
+                         lkb->lkb_wait_type, lkb->lkb_resource->res_name);
        mutex_unlock(&ls->ls_waiters_mutex);
+       return error;
 }
 
 /* We clear the RESEND flag because we might be taking an lkb off the waiters
@@ -759,34 +845,85 @@ static void add_to_waiters(struct dlm_lkb *lkb, int mstype)
    request reply on the requestqueue) between dlm_recover_waiters_pre() which
    set RESEND and dlm_recover_waiters_post() */
 
-static int _remove_from_waiters(struct dlm_lkb *lkb)
+static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype)
 {
-       int error = 0;
+       struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+       int overlap_done = 0;
 
-       if (!lkb->lkb_wait_type) {
-               log_print("remove_from_waiters error");
-               error = -EINVAL;
-               goto out;
+       if (is_overlap_unlock(lkb) && (mstype == DLM_MSG_UNLOCK_REPLY)) {
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
+               overlap_done = 1;
+               goto out_del;
+       }
+
+       if (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL_REPLY)) {
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
+               overlap_done = 1;
+               goto out_del;
+       }
+
+       /* N.B. type of reply may not always correspond to type of original
+          msg due to lookup->request optimization, verify others? */
+
+       if (lkb->lkb_wait_type) {
+               lkb->lkb_wait_type = 0;
+               goto out_del;
+       }
+
+       log_error(ls, "remove_from_waiters lkid %x flags %x types %d %d",
+                 lkb->lkb_id, lkb->lkb_flags, mstype, lkb->lkb_wait_type);
+       return -1;
+
+ out_del:
+       /* the force-unlock/cancel has completed and we haven't recvd a reply
+          to the op that was in progress prior to the unlock/cancel; we
+          give up on any reply to the earlier op.  FIXME: not sure when/how
+          this would happen */
+
+       if (overlap_done && lkb->lkb_wait_type) {
+               log_error(ls, "remove_from_waiters %x reply %d give up on %d",
+                         lkb->lkb_id, mstype, lkb->lkb_wait_type);
+               lkb->lkb_wait_count--;
+               lkb->lkb_wait_type = 0;
        }
-       lkb->lkb_wait_type = 0;
+
+       DLM_ASSERT(lkb->lkb_wait_count, dlm_print_lkb(lkb););
+
        lkb->lkb_flags &= ~DLM_IFL_RESEND;
-       list_del(&lkb->lkb_wait_reply);
+       lkb->lkb_wait_count--;
+       if (!lkb->lkb_wait_count)
+               list_del_init(&lkb->lkb_wait_reply);
        unhold_lkb(lkb);
- out:
-       return error;
+       return 0;
 }
 
-static int remove_from_waiters(struct dlm_lkb *lkb)
+static int remove_from_waiters(struct dlm_lkb *lkb, int mstype)
 {
        struct dlm_ls *ls = lkb->lkb_resource->res_ls;
        int error;
 
        mutex_lock(&ls->ls_waiters_mutex);
-       error = _remove_from_waiters(lkb);
+       error = _remove_from_waiters(lkb, mstype);
        mutex_unlock(&ls->ls_waiters_mutex);
        return error;
 }
 
+/* Handles situations where we might be processing a "fake" or "stub" reply in
+   which we can't try to take waiters_mutex again. */
+
+static int remove_from_waiters_ms(struct dlm_lkb *lkb, struct dlm_message *ms)
+{
+       struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+       int error;
+
+       if (ms != &ls->ls_stub_ms)
+               mutex_lock(&ls->ls_waiters_mutex);
+       error = _remove_from_waiters(lkb, ms->m_type);
+       if (ms != &ls->ls_stub_ms)
+               mutex_unlock(&ls->ls_waiters_mutex);
+       return error;
+}
+
 static void dir_remove(struct dlm_rsb *r)
 {
        int to_nodeid;
@@ -988,8 +1125,14 @@ static void remove_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb)
        _remove_lock(r, lkb);
 }
 
-static void revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
+/* returns: 0 did nothing
+           1 moved lock to granted
+          -1 removed lock */
+
+static int revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
+       int rv = 0;
+
        lkb->lkb_rqmode = DLM_LOCK_IV;
 
        switch (lkb->lkb_status) {
@@ -997,6 +1140,7 @@ static void revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
                break;
        case DLM_LKSTS_CONVERT:
                move_lkb(r, lkb, DLM_LKSTS_GRANTED);
+               rv = 1;
                break;
        case DLM_LKSTS_WAITING:
                del_lkb(r, lkb);
@@ -1004,15 +1148,17 @@ static void revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
                /* this unhold undoes the original ref from create_lkb()
                   so this leads to the lkb being freed */
                unhold_lkb(lkb);
+               rv = -1;
                break;
        default:
                log_print("invalid status for revert %d", lkb->lkb_status);
        }
+       return rv;
 }
 
-static void revert_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb)
+static int revert_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
-       revert_lock(r, lkb);
+       return revert_lock(r, lkb);
 }
 
 static void _grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -1055,6 +1201,50 @@ static void grant_lock_pending(struct dlm_rsb *r, struct dlm_lkb *lkb)
                queue_cast(r, lkb, 0);
 }
 
+/* The special CONVDEADLK, ALTPR and ALTCW flags allow the master to
+   change the granted/requested modes.  We're munging things accordingly in
+   the process copy.
+   CONVDEADLK: our grmode may have been forced down to NL to resolve a
+   conversion deadlock
+   ALTPR/ALTCW: our rqmode may have been changed to PR or CW to become
+   compatible with other granted locks */
+
+static void munge_demoted(struct dlm_lkb *lkb, struct dlm_message *ms)
+{
+       if (ms->m_type != DLM_MSG_CONVERT_REPLY) {
+               log_print("munge_demoted %x invalid reply type %d",
+                         lkb->lkb_id, ms->m_type);
+               return;
+       }
+
+       if (lkb->lkb_rqmode == DLM_LOCK_IV || lkb->lkb_grmode == DLM_LOCK_IV) {
+               log_print("munge_demoted %x invalid modes gr %d rq %d",
+                         lkb->lkb_id, lkb->lkb_grmode, lkb->lkb_rqmode);
+               return;
+       }
+
+       lkb->lkb_grmode = DLM_LOCK_NL;
+}
+
+static void munge_altmode(struct dlm_lkb *lkb, struct dlm_message *ms)
+{
+       if (ms->m_type != DLM_MSG_REQUEST_REPLY &&
+           ms->m_type != DLM_MSG_GRANT) {
+               log_print("munge_altmode %x invalid reply type %d",
+                         lkb->lkb_id, ms->m_type);
+               return;
+       }
+
+       if (lkb->lkb_exflags & DLM_LKF_ALTPR)
+               lkb->lkb_rqmode = DLM_LOCK_PR;
+       else if (lkb->lkb_exflags & DLM_LKF_ALTCW)
+               lkb->lkb_rqmode = DLM_LOCK_CW;
+       else {
+               log_print("munge_altmode invalid exflags %x", lkb->lkb_exflags);
+               dlm_print_lkb(lkb);
+       }
+}
+
 static inline int first_in_list(struct dlm_lkb *lkb, struct list_head *head)
 {
        struct dlm_lkb *first = list_entry(head->next, struct dlm_lkb,
@@ -1499,7 +1689,7 @@ static void process_lookup_list(struct dlm_rsb *r)
        struct dlm_lkb *lkb, *safe;
 
        list_for_each_entry_safe(lkb, safe, &r->res_lookup, lkb_rsb_lookup) {
-               list_del(&lkb->lkb_rsb_lookup);
+               list_del_init(&lkb->lkb_rsb_lookup);
                _request_lock(r, lkb);
                schedule();
        }
@@ -1530,7 +1720,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
                if (!list_empty(&r->res_lookup)) {
                        lkb = list_entry(r->res_lookup.next, struct dlm_lkb,
                                         lkb_rsb_lookup);
-                       list_del(&lkb->lkb_rsb_lookup);
+                       list_del_init(&lkb->lkb_rsb_lookup);
                        r->res_first_lkid = lkb->lkb_id;
                        _request_lock(r, lkb);
                } else
@@ -1614,6 +1804,9 @@ static int set_unlock_args(uint32_t flags, void *astarg, struct dlm_args *args)
                      DLM_LKF_FORCEUNLOCK))
                return -EINVAL;
 
+       if (flags & DLM_LKF_CANCEL && flags & DLM_LKF_FORCEUNLOCK)
+               return -EINVAL;
+
        args->flags = flags;
        args->astparam = (long) astarg;
        return 0;
@@ -1638,6 +1831,9 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 
                if (lkb->lkb_wait_type)
                        goto out;
+
+               if (is_overlap(lkb))
+                       goto out;
        }
 
        lkb->lkb_exflags = args->flags;
@@ -1654,35 +1850,126 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
        return rv;
 }
 
+/* when dlm_unlock() sees -EBUSY with CANCEL/FORCEUNLOCK it returns 0
+   for success */
+
+/* note: it's valid for lkb_nodeid/res_nodeid to be -1 when we get here
+   because there may be a lookup in progress and it's valid to do
+   cancel/unlockf on it */
+
 static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
 {
+       struct dlm_ls *ls = lkb->lkb_resource->res_ls;
        int rv = -EINVAL;
 
-       if (lkb->lkb_flags & DLM_IFL_MSTCPY)
+       if (lkb->lkb_flags & DLM_IFL_MSTCPY) {
+               log_error(ls, "unlock on MSTCPY %x", lkb->lkb_id);
+               dlm_print_lkb(lkb);
                goto out;
+       }
 
-       if (args->flags & DLM_LKF_FORCEUNLOCK)
-               goto out_ok;
+       /* an lkb may still exist even though the lock is EOL'ed due to a
+          cancel, unlock or failed noqueue request; an app can't use these
+          locks; return same error as if the lkid had not been found at all */
 
-       if (args->flags & DLM_LKF_CANCEL &&
-           lkb->lkb_status == DLM_LKSTS_GRANTED)
+       if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) {
+               log_debug(ls, "unlock on ENDOFLIFE %x", lkb->lkb_id);
+               rv = -ENOENT;
                goto out;
+       }
 
-       if (!(args->flags & DLM_LKF_CANCEL) &&
-           lkb->lkb_status != DLM_LKSTS_GRANTED)
-               goto out;
+       /* an lkb may be waiting for an rsb lookup to complete where the
+          lookup was initiated by another lock */
+
+       if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) {
+               if (!list_empty(&lkb->lkb_rsb_lookup)) {
+                       log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id);
+                       list_del_init(&lkb->lkb_rsb_lookup);
+                       queue_cast(lkb->lkb_resource, lkb,
+                                  args->flags & DLM_LKF_CANCEL ?
+                                  -DLM_ECANCEL : -DLM_EUNLOCK);
+                       unhold_lkb(lkb); /* undoes create_lkb() */
+                       rv = -EBUSY;
+                       goto out;
+               }
+       }
+
+       /* cancel not allowed with another cancel/unlock in progress */
+
+       if (args->flags & DLM_LKF_CANCEL) {
+               if (lkb->lkb_exflags & DLM_LKF_CANCEL)
+                       goto out;
+
+               if (is_overlap(lkb))
+                       goto out;
+
+               if (lkb->lkb_flags & DLM_IFL_RESEND) {
+                       lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
+                       rv = -EBUSY;
+                       goto out;
+               }
+
+               switch (lkb->lkb_wait_type) {
+               case DLM_MSG_LOOKUP:
+               case DLM_MSG_REQUEST:
+                       lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
+                       rv = -EBUSY;
+                       goto out;
+               case DLM_MSG_UNLOCK:
+               case DLM_MSG_CANCEL:
+                       goto out;
+               }
+               /* add_to_waiters() will set OVERLAP_CANCEL */
+               goto out_ok;
+       }
+
+       /* do we need to allow a force-unlock if there's a normal unlock
+          already in progress?  in what conditions could the normal unlock
+          fail such that we'd want to send a force-unlock to be sure? */
+
+       if (args->flags & DLM_LKF_FORCEUNLOCK) {
+               if (lkb->lkb_exflags & DLM_LKF_FORCEUNLOCK)
+                       goto out;
+
+               if (is_overlap_unlock(lkb))
+                       goto out;
 
+               if (lkb->lkb_flags & DLM_IFL_RESEND) {
+                       lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
+                       rv = -EBUSY;
+                       goto out;
+               }
+
+               switch (lkb->lkb_wait_type) {
+               case DLM_MSG_LOOKUP:
+               case DLM_MSG_REQUEST:
+                       lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
+                       rv = -EBUSY;
+                       goto out;
+               case DLM_MSG_UNLOCK:
+                       goto out;
+               }
+               /* add_to_waiters() will set OVERLAP_UNLOCK */
+               goto out_ok;
+       }
+
+       /* normal unlock not allowed if there's any op in progress */
        rv = -EBUSY;
-       if (lkb->lkb_wait_type)
+       if (lkb->lkb_wait_type || lkb->lkb_wait_count)
                goto out;
 
  out_ok:
-       lkb->lkb_exflags = args->flags;
+       /* an overlapping op shouldn't blow away exflags from other op */
+       lkb->lkb_exflags |= args->flags;
        lkb->lkb_sbflags = 0;
        lkb->lkb_astparam = args->astparam;
-
        rv = 0;
  out:
+       if (rv)
+               log_debug(ls, "validate_unlock_args %d %x %x %x %x %d %s", rv,
+                         lkb->lkb_id, lkb->lkb_flags, lkb->lkb_exflags,
+                         args->flags, lkb->lkb_wait_type,
+                         lkb->lkb_resource->res_name);
        return rv;
 }
 
@@ -1732,9 +2019,24 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
                goto out;
        }
 
-       if (can_be_queued(lkb)) {
-               if (is_demoted(lkb))
+       /* is_demoted() means the can_be_granted() above set the grmode
+          to NL, and left us on the granted queue.  This auto-demotion
+          (due to CONVDEADLK) might mean other locks, and/or this lock, are
+          now grantable.  We have to try to grant other converting locks
+          before we try again to grant this one. */
+
+       if (is_demoted(lkb)) {
+               grant_pending_convert(r, DLM_LOCK_IV);
+               if (_can_be_granted(r, lkb, 1)) {
+                       grant_lock(r, lkb);
+                       queue_cast(r, lkb, 0);
                        grant_pending_locks(r);
+                       goto out;
+               }
+               /* else fall through and move to convert queue */
+       }
+
+       if (can_be_queued(lkb)) {
                error = -EINPROGRESS;
                del_lkb(r, lkb);
                add_lkb(r, lkb, DLM_LKSTS_CONVERT);
@@ -1759,17 +2061,19 @@ static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
        return -DLM_EUNLOCK;
 }
 
-/* FIXME: if revert_lock() finds that the lkb is granted, we should
-   skip the queue_cast(ECANCEL).  It indicates that the request/convert
-   completed (and queued a normal ast) just before the cancel; we don't
-   want to clobber the sb_result for the normal ast with ECANCEL. */
+/* returns: 0 did nothing, -DLM_ECANCEL canceled lock */
  
 static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
-       revert_lock(r, lkb);
-       queue_cast(r, lkb, -DLM_ECANCEL);
-       grant_pending_locks(r);
-       return -DLM_ECANCEL;
+       int error;
+
+       error = revert_lock(r, lkb);
+       if (error) {
+               queue_cast(r, lkb, -DLM_ECANCEL);
+               grant_pending_locks(r);
+               return -DLM_ECANCEL;
+       }
+       return 0;
 }
 
 /*
@@ -2035,6 +2339,8 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
 
        if (error == -DLM_EUNLOCK || error == -DLM_ECANCEL)
                error = 0;
+       if (error == -EBUSY && (flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)))
+               error = 0;
  out_put:
        dlm_put_lkb(lkb);
  out:
@@ -2065,31 +2371,14 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
  * receive_lookup_reply                send_lookup_reply
  */
 
-static int create_message(struct dlm_rsb *r, struct dlm_lkb *lkb,
-                         int to_nodeid, int mstype,
-                         struct dlm_message **ms_ret,
-                         struct dlm_mhandle **mh_ret)
+static int _create_message(struct dlm_ls *ls, int mb_len,
+                          int to_nodeid, int mstype,
+                          struct dlm_message **ms_ret,
+                          struct dlm_mhandle **mh_ret)
 {
        struct dlm_message *ms;
        struct dlm_mhandle *mh;
        char *mb;
-       int mb_len = sizeof(struct dlm_message);
-
-       switch (mstype) {
-       case DLM_MSG_REQUEST:
-       case DLM_MSG_LOOKUP:
-       case DLM_MSG_REMOVE:
-               mb_len += r->res_length;
-               break;
-       case DLM_MSG_CONVERT:
-       case DLM_MSG_UNLOCK:
-       case DLM_MSG_REQUEST_REPLY:
-       case DLM_MSG_CONVERT_REPLY:
-       case DLM_MSG_GRANT:
-               if (lkb && lkb->lkb_lvbptr)
-                       mb_len += r->res_ls->ls_lvblen;
-               break;
-       }
 
        /* get_buffer gives us a message handle (mh) that we need to
           pass into lowcomms_commit and a message buffer (mb) that we
@@ -2104,7 +2393,7 @@ static int create_message(struct dlm_rsb *r, struct dlm_lkb *lkb,
        ms = (struct dlm_message *) mb;
 
        ms->m_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
-       ms->m_header.h_lockspace = r->res_ls->ls_global_id;
+       ms->m_header.h_lockspace = ls->ls_global_id;
        ms->m_header.h_nodeid = dlm_our_nodeid();
        ms->m_header.h_length = mb_len;
        ms->m_header.h_cmd = DLM_MSG;
@@ -2116,6 +2405,33 @@ static int create_message(struct dlm_rsb *r, struct dlm_lkb *lkb,
        return 0;
 }
 
+static int create_message(struct dlm_rsb *r, struct dlm_lkb *lkb,
+                         int to_nodeid, int mstype,
+                         struct dlm_message **ms_ret,
+                         struct dlm_mhandle **mh_ret)
+{
+       int mb_len = sizeof(struct dlm_message);
+
+       switch (mstype) {
+       case DLM_MSG_REQUEST:
+       case DLM_MSG_LOOKUP:
+       case DLM_MSG_REMOVE:
+               mb_len += r->res_length;
+               break;
+       case DLM_MSG_CONVERT:
+       case DLM_MSG_UNLOCK:
+       case DLM_MSG_REQUEST_REPLY:
+       case DLM_MSG_CONVERT_REPLY:
+       case DLM_MSG_GRANT:
+               if (lkb && lkb->lkb_lvbptr)
+                       mb_len += r->res_ls->ls_lvblen;
+               break;
+       }
+
+       return _create_message(r->res_ls, mb_len, to_nodeid, mstype,
+                              ms_ret, mh_ret);
+}
+
 /* further lowcomms enhancements or alternate implementations may make
    the return value from this function useful at some point */
 
@@ -2176,7 +2492,9 @@ static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype)
        struct dlm_mhandle *mh;
        int to_nodeid, error;
 
-       add_to_waiters(lkb, mstype);
+       error = add_to_waiters(lkb, mstype);
+       if (error)
+               return error;
 
        to_nodeid = r->res_nodeid;
 
@@ -2192,7 +2510,7 @@ static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype)
        return 0;
 
  fail:
-       remove_from_waiters(lkb);
+       remove_from_waiters(lkb, msg_reply_type(mstype));
        return error;
 }
 
@@ -2209,7 +2527,8 @@ static int send_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
 
        /* down conversions go without a reply from the master */
        if (!error && down_conversion(lkb)) {
-               remove_from_waiters(lkb);
+               remove_from_waiters(lkb, DLM_MSG_CONVERT_REPLY);
+               r->res_ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY;
                r->res_ls->ls_stub_ms.m_result = 0;
                r->res_ls->ls_stub_ms.m_flags = lkb->lkb_flags;
                __receive_convert_reply(r, lkb, &r->res_ls->ls_stub_ms);
@@ -2280,7 +2599,9 @@ static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb)
        struct dlm_mhandle *mh;
        int to_nodeid, error;
 
-       add_to_waiters(lkb, DLM_MSG_LOOKUP);
+       error = add_to_waiters(lkb, DLM_MSG_LOOKUP);
+       if (error)
+               return error;
 
        to_nodeid = dlm_dir_nodeid(r);
 
@@ -2296,7 +2617,7 @@ static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb)
        return 0;
 
  fail:
-       remove_from_waiters(lkb);
+       remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY);
        return error;
 }
 
@@ -2656,6 +2977,8 @@ static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms)
        lock_rsb(r);
 
        receive_flags_reply(lkb, ms);
+       if (is_altmode(lkb))
+               munge_altmode(lkb, ms);
        grant_lock_pc(r, lkb, ms);
        queue_cast(r, lkb, 0);
 
@@ -2736,11 +3059,16 @@ static void receive_remove(struct dlm_ls *ls, struct dlm_message *ms)
        dlm_dir_remove_entry(ls, from_nodeid, ms->m_extra, len);
 }
 
+static void receive_purge(struct dlm_ls *ls, struct dlm_message *ms)
+{
+       do_purge(ls, ms->m_nodeid, ms->m_pid);
+}
+
 static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
 {
        struct dlm_lkb *lkb;
        struct dlm_rsb *r;
-       int error, mstype;
+       int error, mstype, result;
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
@@ -2749,20 +3077,15 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
        }
        DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
-       mstype = lkb->lkb_wait_type;
-       error = remove_from_waiters(lkb);
-       if (error) {
-               log_error(ls, "receive_request_reply not on waiters");
-               goto out;
-       }
-
-       /* this is the value returned from do_request() on the master */
-       error = ms->m_result;
-
        r = lkb->lkb_resource;
        hold_rsb(r);
        lock_rsb(r);
 
+       mstype = lkb->lkb_wait_type;
+       error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY);
+       if (error)
+               goto out;
+
        /* Optimization: the dir node was also the master, so it took our
           lookup as a request and sent request reply instead of lookup reply */
        if (mstype == DLM_MSG_LOOKUP) {
@@ -2770,14 +3093,15 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
                lkb->lkb_nodeid = r->res_nodeid;
        }
 
-       switch (error) {
+       /* this is the value returned from do_request() on the master */
+       result = ms->m_result;
+
+       switch (result) {
        case -EAGAIN:
-               /* request would block (be queued) on remote master;
-                  the unhold undoes the original ref from create_lkb()
-                  so it leads to the lkb being freed */
+               /* request would block (be queued) on remote master */
                queue_cast(r, lkb, -EAGAIN);
                confirm_master(r, -EAGAIN);
-               unhold_lkb(lkb);
+               unhold_lkb(lkb); /* undoes create_lkb() */
                break;
 
        case -EINPROGRESS:
@@ -2785,41 +3109,64 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
                /* request was queued or granted on remote master */
                receive_flags_reply(lkb, ms);
                lkb->lkb_remid = ms->m_lkid;
-               if (error)
+               if (is_altmode(lkb))
+                       munge_altmode(lkb, ms);
+               if (result)
                        add_lkb(r, lkb, DLM_LKSTS_WAITING);
                else {
                        grant_lock_pc(r, lkb, ms);
                        queue_cast(r, lkb, 0);
                }
-               confirm_master(r, error);
+               confirm_master(r, result);
                break;
 
        case -EBADR:
        case -ENOTBLK:
                /* find_rsb failed to find rsb or rsb wasn't master */
+               log_debug(ls, "receive_request_reply %x %x master diff %d %d",
+                         lkb->lkb_id, lkb->lkb_flags, r->res_nodeid, result);
                r->res_nodeid = -1;
                lkb->lkb_nodeid = -1;
-               _request_lock(r, lkb);
+
+               if (is_overlap(lkb)) {
+                       /* we'll ignore error in cancel/unlock reply */
+                       queue_cast_overlap(r, lkb);
+                       unhold_lkb(lkb); /* undoes create_lkb() */
+               } else
+                       _request_lock(r, lkb);
                break;
 
        default:
-               log_error(ls, "receive_request_reply error %d", error);
+               log_error(ls, "receive_request_reply %x error %d",
+                         lkb->lkb_id, result);
        }
 
+       if (is_overlap_unlock(lkb) && (result == 0 || result == -EINPROGRESS)) {
+               log_debug(ls, "receive_request_reply %x result %d unlock",
+                         lkb->lkb_id, result);
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
+               send_unlock(r, lkb);
+       } else if (is_overlap_cancel(lkb) && (result == -EINPROGRESS)) {
+               log_debug(ls, "receive_request_reply %x cancel", lkb->lkb_id);
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
+               send_cancel(r, lkb);
+       } else {
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
+       }
+ out:
        unlock_rsb(r);
        put_rsb(r);
- out:
        dlm_put_lkb(lkb);
 }
 
 static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
                                    struct dlm_message *ms)
 {
-       int error = ms->m_result;
-
        /* this is the value returned from do_convert() on the master */
-
-       switch (error) {
+       switch (ms->m_result) {
        case -EAGAIN:
                /* convert would block (be queued) on remote master */
                queue_cast(r, lkb, -EAGAIN);
@@ -2827,6 +3174,9 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
 
        case -EINPROGRESS:
                /* convert was queued on remote master */
+               receive_flags_reply(lkb, ms);
+               if (is_demoted(lkb))
+                       munge_demoted(lkb, ms);
                del_lkb(r, lkb);
                add_lkb(r, lkb, DLM_LKSTS_CONVERT);
                break;
@@ -2834,24 +3184,33 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
        case 0:
                /* convert was granted on remote master */
                receive_flags_reply(lkb, ms);
+               if (is_demoted(lkb))
+                       munge_demoted(lkb, ms);
                grant_lock_pc(r, lkb, ms);
                queue_cast(r, lkb, 0);
                break;
 
        default:
-               log_error(r->res_ls, "receive_convert_reply error %d", error);
+               log_error(r->res_ls, "receive_convert_reply %x error %d",
+                         lkb->lkb_id, ms->m_result);
        }
 }
 
 static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
 {
        struct dlm_rsb *r = lkb->lkb_resource;
+       int error;
 
        hold_rsb(r);
        lock_rsb(r);
 
-       __receive_convert_reply(r, lkb, ms);
+       /* stub reply can happen with waiters_mutex held */
+       error = remove_from_waiters_ms(lkb, ms);
+       if (error)
+               goto out;
 
+       __receive_convert_reply(r, lkb, ms);
+ out:
        unlock_rsb(r);
        put_rsb(r);
 }
@@ -2868,37 +3227,38 @@ static void receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms)
        }
        DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
-       error = remove_from_waiters(lkb);
-       if (error) {
-               log_error(ls, "receive_convert_reply not on waiters");
-               goto out;
-       }
-
        _receive_convert_reply(lkb, ms);
- out:
        dlm_put_lkb(lkb);
 }
 
 static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
 {
        struct dlm_rsb *r = lkb->lkb_resource;
-       int error = ms->m_result;
+       int error;
 
        hold_rsb(r);
        lock_rsb(r);
 
+       /* stub reply can happen with waiters_mutex held */
+       error = remove_from_waiters_ms(lkb, ms);
+       if (error)
+               goto out;
+
        /* this is the value returned from do_unlock() on the master */
 
-       switch (error) {
+       switch (ms->m_result) {
        case -DLM_EUNLOCK:
                receive_flags_reply(lkb, ms);
                remove_lock_pc(r, lkb);
                queue_cast(r, lkb, -DLM_EUNLOCK);
                break;
+       case -ENOENT:
+               break;
        default:
-               log_error(r->res_ls, "receive_unlock_reply error %d", error);
+               log_error(r->res_ls, "receive_unlock_reply %x error %d",
+                         lkb->lkb_id, ms->m_result);
        }
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
 }
@@ -2915,37 +3275,39 @@ static void receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms)
        }
        DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
-       error = remove_from_waiters(lkb);
-       if (error) {
-               log_error(ls, "receive_unlock_reply not on waiters");
-               goto out;
-       }
-
        _receive_unlock_reply(lkb, ms);
- out:
        dlm_put_lkb(lkb);
 }
 
 static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
 {
        struct dlm_rsb *r = lkb->lkb_resource;
-       int error = ms->m_result;
+       int error;
 
        hold_rsb(r);
        lock_rsb(r);
 
+       /* stub reply can happen with waiters_mutex held */
+       error = remove_from_waiters_ms(lkb, ms);
+       if (error)
+               goto out;
+
        /* this is the value returned from do_cancel() on the master */
 
-       switch (error) {
+       switch (ms->m_result) {
        case -DLM_ECANCEL:
                receive_flags_reply(lkb, ms);
                revert_lock_pc(r, lkb);
-               queue_cast(r, lkb, -DLM_ECANCEL);
+               if (ms->m_result)
+                       queue_cast(r, lkb, -DLM_ECANCEL);
+               break;
+       case 0:
                break;
        default:
-               log_error(r->res_ls, "receive_cancel_reply error %d", error);
+               log_error(r->res_ls, "receive_cancel_reply %x error %d",
+                         lkb->lkb_id, ms->m_result);
        }
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
 }
@@ -2962,14 +3324,7 @@ static void receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms)
        }
        DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
-       error = remove_from_waiters(lkb);
-       if (error) {
-               log_error(ls, "receive_cancel_reply not on waiters");
-               goto out;
-       }
-
        _receive_cancel_reply(lkb, ms);
- out:
        dlm_put_lkb(lkb);
 }
 
@@ -2985,20 +3340,17 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
                return;
        }
 
-       error = remove_from_waiters(lkb);
-       if (error) {
-               log_error(ls, "receive_lookup_reply not on waiters");
-               goto out;
-       }
-
-       /* this is the value returned by dlm_dir_lookup on dir node
+       /* ms->m_result is the value returned by dlm_dir_lookup on dir node
           FIXME: will a non-zero error ever be returned? */
-       error = ms->m_result;
 
        r = lkb->lkb_resource;
        hold_rsb(r);
        lock_rsb(r);
 
+       error = remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY);
+       if (error)
+               goto out;
+
        ret_nodeid = ms->m_nodeid;
        if (ret_nodeid == dlm_our_nodeid()) {
                r->res_nodeid = 0;
@@ -3009,14 +3361,22 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
                r->res_nodeid = ret_nodeid;
        }
 
+       if (is_overlap(lkb)) {
+               log_debug(ls, "receive_lookup_reply %x unlock %x",
+                         lkb->lkb_id, lkb->lkb_flags);
+               queue_cast_overlap(r, lkb);
+               unhold_lkb(lkb); /* undoes create_lkb() */
+               goto out_list;
+       }
+
        _request_lock(r, lkb);
 
+ out_list:
        if (!ret_nodeid)
                process_lookup_list(r);
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
- out:
        dlm_put_lkb(lkb);
 }
 
@@ -3133,6 +3493,12 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
                receive_lookup_reply(ls, ms);
                break;
 
+       /* other messages */
+
+       case DLM_MSG_PURGE:
+               receive_purge(ls, ms);
+               break;
+
        default:
                log_error(ls, "unknown message type %d", ms->m_type);
        }
@@ -3153,9 +3519,9 @@ static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb)
 {
        if (middle_conversion(lkb)) {
                hold_lkb(lkb);
+               ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY;
                ls->ls_stub_ms.m_result = -EINPROGRESS;
                ls->ls_stub_ms.m_flags = lkb->lkb_flags;
-               _remove_from_waiters(lkb);
                _receive_convert_reply(lkb, &ls->ls_stub_ms);
 
                /* Same special case as in receive_rcom_lock_args() */
@@ -3227,18 +3593,18 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
 
                case DLM_MSG_UNLOCK:
                        hold_lkb(lkb);
+                       ls->ls_stub_ms.m_type = DLM_MSG_UNLOCK_REPLY;
                        ls->ls_stub_ms.m_result = -DLM_EUNLOCK;
                        ls->ls_stub_ms.m_flags = lkb->lkb_flags;
-                       _remove_from_waiters(lkb);
                        _receive_unlock_reply(lkb, &ls->ls_stub_ms);
                        dlm_put_lkb(lkb);
                        break;
 
                case DLM_MSG_CANCEL:
                        hold_lkb(lkb);
+                       ls->ls_stub_ms.m_type = DLM_MSG_CANCEL_REPLY;
                        ls->ls_stub_ms.m_result = -DLM_ECANCEL;
                        ls->ls_stub_ms.m_flags = lkb->lkb_flags;
-                       _remove_from_waiters(lkb);
                        _receive_cancel_reply(lkb, &ls->ls_stub_ms);
                        dlm_put_lkb(lkb);
                        break;
@@ -3252,37 +3618,47 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
        mutex_unlock(&ls->ls_waiters_mutex);
 }
 
-static int remove_resend_waiter(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
+static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls)
 {
        struct dlm_lkb *lkb;
-       int rv = 0;
+       int found = 0;
 
        mutex_lock(&ls->ls_waiters_mutex);
        list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
                if (lkb->lkb_flags & DLM_IFL_RESEND) {
-                       rv = lkb->lkb_wait_type;
-                       _remove_from_waiters(lkb);
-                       lkb->lkb_flags &= ~DLM_IFL_RESEND;
+                       hold_lkb(lkb);
+                       found = 1;
                        break;
                }
        }
        mutex_unlock(&ls->ls_waiters_mutex);
 
-       if (!rv)
+       if (!found)
                lkb = NULL;
-       *lkb_ret = lkb;
-       return rv;
+       return lkb;
 }
 
 /* Deal with lookups and lkb's marked RESEND from _pre.  We may now be the
    master or dir-node for r.  Processing the lkb may result in it being placed
    back on waiters. */
 
+/* We do this after normal locking has been enabled and any saved messages
+   (in requestqueue) have been processed.  We should be confident that at
+   this point we won't get or process a reply to any of these waiting
+   operations.  But, new ops may be coming in on the rsbs/locks here from
+   userspace or remotely. */
+
+/* there may have been an overlap unlock/cancel prior to recovery or after
+   recovery.  if before, the lkb may still have a pos wait_count; if after, the
+   overlap flag would just have been set and nothing new sent.  we can be
+   confident here than any replies to either the initial op or overlap ops
+   prior to recovery have been received. */
+
 int dlm_recover_waiters_post(struct dlm_ls *ls)
 {
        struct dlm_lkb *lkb;
        struct dlm_rsb *r;
-       int error = 0, mstype;
+       int error = 0, mstype, err, oc, ou;
 
        while (1) {
                if (dlm_locking_stopped(ls)) {
@@ -3291,48 +3667,78 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
                        break;
                }
 
-               mstype = remove_resend_waiter(ls, &lkb);
-               if (!mstype)
+               lkb = find_resend_waiter(ls);
+               if (!lkb)
                        break;
 
                r = lkb->lkb_resource;
+               hold_rsb(r);
+               lock_rsb(r);
+
+               mstype = lkb->lkb_wait_type;
+               oc = is_overlap_cancel(lkb);
+               ou = is_overlap_unlock(lkb);
+               err = 0;
 
                log_debug(ls, "recover_waiters_post %x type %d flags %x %s",
                          lkb->lkb_id, mstype, lkb->lkb_flags, r->res_name);
 
-               switch (mstype) {
-
-               case DLM_MSG_LOOKUP:
-                       hold_rsb(r);
-                       lock_rsb(r);
-                       _request_lock(r, lkb);
-                       if (is_master(r))
-                               confirm_master(r, 0);
-                       unlock_rsb(r);
-                       put_rsb(r);
-                       break;
-
-               case DLM_MSG_REQUEST:
-                       hold_rsb(r);
-                       lock_rsb(r);
-                       _request_lock(r, lkb);
-                       if (is_master(r))
-                               confirm_master(r, 0);
-                       unlock_rsb(r);
-                       put_rsb(r);
-                       break;
-
-               case DLM_MSG_CONVERT:
-                       hold_rsb(r);
-                       lock_rsb(r);
-                       _convert_lock(r, lkb);
-                       unlock_rsb(r);
-                       put_rsb(r);
-                       break;
-
-               default:
-                       log_error(ls, "recover_waiters_post type %d", mstype);
+               /* At this point we assume that we won't get a reply to any
+                  previous op or overlap op on this lock.  First, do a big
+                  remove_from_waiters() for all previous ops. */
+
+               lkb->lkb_flags &= ~DLM_IFL_RESEND;
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
+               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
+               lkb->lkb_wait_type = 0;
+               lkb->lkb_wait_count = 0;
+               mutex_lock(&ls->ls_waiters_mutex);
+               list_del_init(&lkb->lkb_wait_reply);
+               mutex_unlock(&ls->ls_waiters_mutex);
+               unhold_lkb(lkb); /* for waiters list */
+
+               if (oc || ou) {
+                       /* do an unlock or cancel instead of resending */
+                       switch (mstype) {
+                       case DLM_MSG_LOOKUP:
+                       case DLM_MSG_REQUEST:
+                               queue_cast(r, lkb, ou ? -DLM_EUNLOCK :
+                                                       -DLM_ECANCEL);
+                               unhold_lkb(lkb); /* undoes create_lkb() */
+                               break;
+                       case DLM_MSG_CONVERT:
+                               if (oc) {
+                                       queue_cast(r, lkb, -DLM_ECANCEL);
+                               } else {
+                                       lkb->lkb_exflags |= DLM_LKF_FORCEUNLOCK;
+                                       _unlock_lock(r, lkb);
+                               }
+                               break;
+                       default:
+                               err = 1;
+                       }
+               } else {
+                       switch (mstype) {
+                       case DLM_MSG_LOOKUP:
+                       case DLM_MSG_REQUEST:
+                               _request_lock(r, lkb);
+                               if (is_master(r))
+                                       confirm_master(r, 0);
+                               break;
+                       case DLM_MSG_CONVERT:
+                               _convert_lock(r, lkb);
+                               break;
+                       default:
+                               err = 1;
+                       }
                }
+
+               if (err)
+                       log_error(ls, "recover_waiters_post %x %d %x %d %d",
+                                 lkb->lkb_id, mstype, lkb->lkb_flags, oc, ou);
+               unlock_rsb(r);
+               put_rsb(r);
+               dlm_put_lkb(lkb);
        }
 
        return error;
@@ -3684,7 +4090,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
 
        /* add this new lkb to the per-process list of locks */
        spin_lock(&ua->proc->locks_spin);
-       kref_get(&lkb->lkb_ref);
+       hold_lkb(lkb);
        list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
        spin_unlock(&ua->proc->locks_spin);
  out:
@@ -3774,6 +4180,9 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 
        if (error == -DLM_EUNLOCK)
                error = 0;
+       /* from validate_unlock_args() */
+       if (error == -EBUSY && (flags & DLM_LKF_FORCEUNLOCK))
+               error = 0;
        if (error)
                goto out_put;
 
@@ -3786,6 +4195,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
        dlm_put_lkb(lkb);
  out:
        unlock_recovery(ls);
+       kfree(ua_tmp);
        return error;
 }
 
@@ -3815,33 +4225,37 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 
        if (error == -DLM_ECANCEL)
                error = 0;
-       if (error)
-               goto out_put;
-
-       /* this lkb was removed from the WAITING queue */
-       if (lkb->lkb_grmode == DLM_LOCK_IV) {
-               spin_lock(&ua->proc->locks_spin);
-               list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking);
-               spin_unlock(&ua->proc->locks_spin);
-       }
+       /* from validate_unlock_args() */
+       if (error == -EBUSY)
+               error = 0;
  out_put:
        dlm_put_lkb(lkb);
  out:
        unlock_recovery(ls);
+       kfree(ua_tmp);
        return error;
 }
 
+/* lkb's that are removed from the waiters list by revert are just left on the
+   orphans list with the granted orphan locks, to be freed by purge */
+
 static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
 {
        struct dlm_user_args *ua = (struct dlm_user_args *)lkb->lkb_astparam;
+       struct dlm_args args;
+       int error;
 
-       if (ua->lksb.sb_lvbptr)
-               kfree(ua->lksb.sb_lvbptr);
-       kfree(ua);
-       lkb->lkb_astparam = (long)NULL;
+       hold_lkb(lkb);
+       mutex_lock(&ls->ls_orphans_mutex);
+       list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans);
+       mutex_unlock(&ls->ls_orphans_mutex);
 
-       /* TODO: propogate to master if needed */
-       return 0;
+       set_unlock_args(0, ua, &args);
+
+       error = cancel_lock(ls, lkb, &args);
+       if (error == -DLM_ECANCEL)
+               error = 0;
+       return error;
 }
 
 /* The force flag allows the unlock to go ahead even if the lkb isn't granted.
@@ -3853,10 +4267,6 @@ static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
        struct dlm_args args;
        int error;
 
-       /* FIXME: we need to handle the case where the lkb is in limbo
-          while the rsb is being looked up, currently we assert in
-          _unlock_lock/is_remote because rsb nodeid is -1. */
-
        set_unlock_args(DLM_LKF_FORCEUNLOCK, ua, &args);
 
        error = unlock_lock(ls, lkb, &args);
@@ -3865,6 +4275,31 @@ static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
        return error;
 }
 
+/* We have to release clear_proc_locks mutex before calling unlock_proc_lock()
+   (which does lock_rsb) due to deadlock with receiving a message that does
+   lock_rsb followed by dlm_user_add_ast() */
+
+static struct dlm_lkb *del_proc_lock(struct dlm_ls *ls,
+                                    struct dlm_user_proc *proc)
+{
+       struct dlm_lkb *lkb = NULL;
+
+       mutex_lock(&ls->ls_clear_proc_locks);
+       if (list_empty(&proc->locks))
+               goto out;
+
+       lkb = list_entry(proc->locks.next, struct dlm_lkb, lkb_ownqueue);
+       list_del_init(&lkb->lkb_ownqueue);
+
+       if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
+               lkb->lkb_flags |= DLM_IFL_ORPHAN;
+       else
+               lkb->lkb_flags |= DLM_IFL_DEAD;
+ out:
+       mutex_unlock(&ls->ls_clear_proc_locks);
+       return lkb;
+}
+
 /* The ls_clear_proc_locks mutex protects against dlm_user_add_asts() which
    1) references lkb->ua which we free here and 2) adds lkbs to proc->asts,
    which we clear here. */
@@ -3880,18 +4315,15 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
        struct dlm_lkb *lkb, *safe;
 
        lock_recovery(ls);
-       mutex_lock(&ls->ls_clear_proc_locks);
 
-       list_for_each_entry_safe(lkb, safe, &proc->locks, lkb_ownqueue) {
-               list_del_init(&lkb->lkb_ownqueue);
-
-               if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) {
-                       lkb->lkb_flags |= DLM_IFL_ORPHAN;
+       while (1) {
+               lkb = del_proc_lock(ls, proc);
+               if (!lkb)
+                       break;
+               if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
                        orphan_proc_lock(ls, lkb);
-               } else {
-                       lkb->lkb_flags |= DLM_IFL_DEAD;
+               else
                        unlock_proc_lock(ls, lkb);
-               }
 
                /* this removes the reference for the proc->locks list
                   added by dlm_user_request, it may result in the lkb
@@ -3900,6 +4332,8 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
                dlm_put_lkb(lkb);
        }
 
+       mutex_lock(&ls->ls_clear_proc_locks);
+
        /* in-progress unlocks */
        list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) {
                list_del_init(&lkb->lkb_ownqueue);
@@ -3916,3 +4350,92 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
        unlock_recovery(ls);
 }
 
+static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
+{
+       struct dlm_lkb *lkb, *safe;
+
+       while (1) {
+               lkb = NULL;
+               spin_lock(&proc->locks_spin);
+               if (!list_empty(&proc->locks)) {
+                       lkb = list_entry(proc->locks.next, struct dlm_lkb,
+                                        lkb_ownqueue);
+                       list_del_init(&lkb->lkb_ownqueue);
+               }
+               spin_unlock(&proc->locks_spin);
+
+               if (!lkb)
+                       break;
+
+               lkb->lkb_flags |= DLM_IFL_DEAD;
+               unlock_proc_lock(ls, lkb);
+               dlm_put_lkb(lkb); /* ref from proc->locks list */
+       }
+
+       spin_lock(&proc->locks_spin);
+       list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) {
+               list_del_init(&lkb->lkb_ownqueue);
+               lkb->lkb_flags |= DLM_IFL_DEAD;
+               dlm_put_lkb(lkb);
+       }
+       spin_unlock(&proc->locks_spin);
+
+       spin_lock(&proc->asts_spin);
+       list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
+               list_del(&lkb->lkb_astqueue);
+               dlm_put_lkb(lkb);
+       }
+       spin_unlock(&proc->asts_spin);
+}
+
+/* pid of 0 means purge all orphans */
+
+static void do_purge(struct dlm_ls *ls, int nodeid, int pid)
+{
+       struct dlm_lkb *lkb, *safe;
+
+       mutex_lock(&ls->ls_orphans_mutex);
+       list_for_each_entry_safe(lkb, safe, &ls->ls_orphans, lkb_ownqueue) {
+               if (pid && lkb->lkb_ownpid != pid)
+                       continue;
+               unlock_proc_lock(ls, lkb);
+               list_del_init(&lkb->lkb_ownqueue);
+               dlm_put_lkb(lkb);
+       }
+       mutex_unlock(&ls->ls_orphans_mutex);
+}
+
+static int send_purge(struct dlm_ls *ls, int nodeid, int pid)
+{
+       struct dlm_message *ms;
+       struct dlm_mhandle *mh;
+       int error;
+
+       error = _create_message(ls, sizeof(struct dlm_message), nodeid,
+                               DLM_MSG_PURGE, &ms, &mh);
+       if (error)
+               return error;
+       ms->m_nodeid = nodeid;
+       ms->m_pid = pid;
+
+       return send_message(mh, ms);
+}
+
+int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
+                  int nodeid, int pid)
+{
+       int error = 0;
+
+       if (nodeid != dlm_our_nodeid()) {
+               error = send_purge(ls, nodeid, pid);
+       } else {
+               lock_recovery(ls);
+               if (pid == current->pid)
+                       purge_proc_locks(ls, proc);
+               else
+                       do_purge(ls, nodeid, pid);
+               unlock_recovery(ls);
+       }
+       return error;
+}
+
index 0843a30..64fc4ec 100644 (file)
@@ -41,6 +41,8 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
        uint32_t flags, uint32_t lkid, char *lvb_in);
 int dlm_user_cancel(struct dlm_ls *ls,  struct dlm_user_args *ua_tmp,
        uint32_t flags, uint32_t lkid);
+int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
+       int nodeid, int pid);
 void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
 
 static inline int is_master(struct dlm_rsb *r)
index f40817b..a677b2a 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -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);
@@ -459,6 +459,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
 
        INIT_LIST_HEAD(&ls->ls_waiters);
        mutex_init(&ls->ls_waiters_mutex);
+       INIT_LIST_HEAD(&ls->ls_orphans);
+       mutex_init(&ls->ls_orphans_mutex);
 
        INIT_LIST_HEAD(&ls->ls_nodes);
        INIT_LIST_HEAD(&ls->ls_nodes_gone);
diff --git a/fs/dlm/lowcomms-sctp.c b/fs/dlm/lowcomms-sctp.c
deleted file mode 100644 (file)
index dc83a9d..0000000
+++ /dev/null
@@ -1,1210 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
-**
-**  This copyrighted material is made available to anyone wishing to use,
-**  modify, copy, or redistribute it subject to the terms and conditions
-**  of the GNU General Public License v.2.
-**
-*******************************************************************************
-******************************************************************************/
-
-/*
- * lowcomms.c
- *
- * This is the "low-level" comms layer.
- *
- * It is responsible for sending/receiving messages
- * from other nodes in the cluster.
- *
- * Cluster nodes are referred to by their nodeids. nodeids are
- * simply 32 bit numbers to the locking module - if they need to
- * be expanded for the cluster infrastructure then that is it's
- * responsibility. It is this layer's
- * responsibility to resolve these into IP address or
- * whatever it needs for inter-node communication.
- *
- * The comms level is two kernel threads that deal mainly with
- * the receiving of messages from other nodes and passing them
- * up to the mid-level comms layer (which understands the
- * message format) for execution by the locking core, and
- * a send thread which does all the setting up of connections
- * to remote nodes and the sending of data. Threads are not allowed
- * to send their own data because it may cause them to wait in times
- * of high load. Also, this way, the sending thread can collect together
- * messages bound for one node and send them in one block.
- *
- * I don't see any problem with the recv thread executing the locking
- * code on behalf of remote processes as the locking code is
- * short, efficient and never (well, hardly ever) waits.
- *
- */
-
-#include <asm/ioctls.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-#include <net/sctp/user.h>
-#include <linux/pagemap.h>
-#include <linux/socket.h>
-#include <linux/idr.h>
-
-#include "dlm_internal.h"
-#include "lowcomms.h"
-#include "config.h"
-#include "midcomms.h"
-
-static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
-static int                     dlm_local_count;
-static int                     dlm_local_nodeid;
-
-/* One of these per connected node */
-
-#define NI_INIT_PENDING 1
-#define NI_WRITE_PENDING 2
-
-struct nodeinfo {
-       spinlock_t              lock;
-       sctp_assoc_t            assoc_id;
-       unsigned long           flags;
-       struct list_head        write_list; /* nodes with pending writes */
-       struct list_head        writequeue; /* outgoing writequeue_entries */
-       spinlock_t              writequeue_lock;
-       int                     nodeid;
-       struct work_struct      swork; /* Send workqueue */
-       struct work_struct      lwork; /* Locking workqueue */
-};
-
-static DEFINE_IDR(nodeinfo_idr);
-static DECLARE_RWSEM(nodeinfo_lock);
-static int max_nodeid;
-
-struct cbuf {
-       unsigned int base;
-       unsigned int len;
-       unsigned int mask;
-};
-
-/* Just the one of these, now. But this struct keeps
-   the connection-specific variables together */
-
-#define CF_READ_PENDING 1
-
-struct connection {
-       struct socket           *sock;
-       unsigned long           flags;
-       struct page             *rx_page;
-       atomic_t                waiting_requests;
-       struct cbuf             cb;
-       int                     eagain_flag;
-       struct work_struct      work; /* Send workqueue */
-};
-
-/* An entry waiting to be sent */
-
-struct writequeue_entry {
-       struct list_head        list;
-       struct page             *page;
-       int                     offset;
-       int                     len;
-       int                     end;
-       int                     users;
-       struct nodeinfo         *ni;
-};
-
-static void cbuf_add(struct cbuf *cb, int n)
-{
-       cb->len += n;
-}
-
-static int cbuf_data(struct cbuf *cb)
-{
-       return ((cb->base + cb->len) & cb->mask);
-}
-
-static void cbuf_init(struct cbuf *cb, int size)
-{
-       cb->base = cb->len = 0;
-       cb->mask = size-1;
-}
-
-static void cbuf_eat(struct cbuf *cb, int n)
-{
-       cb->len  -= n;
-       cb->base += n;
-       cb->base &= cb->mask;
-}
-
-/* List of nodes which have writes pending */
-static LIST_HEAD(write_nodes);
-static DEFINE_SPINLOCK(write_nodes_lock);
-
-
-/* Maximum number of incoming messages to process before
- * doing a schedule()
- */
-#define MAX_RX_MSG_COUNT 25
-
-/* Work queues */
-static struct workqueue_struct *recv_workqueue;
-static struct workqueue_struct *send_workqueue;
-static struct workqueue_struct *lock_workqueue;
-
-/* The SCTP connection */
-static struct connection sctp_con;
-
-static void process_send_sockets(struct work_struct *work);
-static void process_recv_sockets(struct work_struct *work);
-static void process_lock_request(struct work_struct *work);
-
-static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
-{
-       struct sockaddr_storage addr;
-       int error;
-
-       if (!dlm_local_count)
-               return -1;
-
-       error = dlm_nodeid_to_addr(nodeid, &addr);
-       if (error)
-               return error;
-
-       if (dlm_local_addr[0]->ss_family == AF_INET) {
-               struct sockaddr_in *in4  = (struct sockaddr_in *) &addr;
-               struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr;
-               ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
-       } else {
-               struct sockaddr_in6 *in6  = (struct sockaddr_in6 *) &addr;
-               struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr;
-               memcpy(&ret6->sin6_addr, &in6->sin6_addr,
-                      sizeof(in6->sin6_addr));
-       }
-
-       return 0;
-}
-
-/* If alloc is 0 here we will not attempt to allocate a new
-   nodeinfo struct */
-static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc)
-{
-       struct nodeinfo *ni;
-       int r;
-       int n;
-
-       down_read(&nodeinfo_lock);
-       ni = idr_find(&nodeinfo_idr, nodeid);
-       up_read(&nodeinfo_lock);
-
-       if (ni || !alloc)
-               return ni;
-
-       down_write(&nodeinfo_lock);
-
-       ni = idr_find(&nodeinfo_idr, nodeid);
-       if (ni)
-               goto out_up;
-
-       r = idr_pre_get(&nodeinfo_idr, alloc);
-       if (!r)
-               goto out_up;
-
-       ni = kmalloc(sizeof(struct nodeinfo), alloc);
-       if (!ni)
-               goto out_up;
-
-       r = idr_get_new_above(&nodeinfo_idr, ni, nodeid, &n);
-       if (r) {
-               kfree(ni);
-               ni = NULL;
-               goto out_up;
-       }
-       if (n != nodeid) {
-               idr_remove(&nodeinfo_idr, n);
-               kfree(ni);
-               ni = NULL;
-               goto out_up;
-       }
-       memset(ni, 0, sizeof(struct nodeinfo));
-       spin_lock_init(&ni->lock);
-       INIT_LIST_HEAD(&ni->writequeue);
-       spin_lock_init(&ni->writequeue_lock);
-       INIT_WORK(&ni->lwork, process_lock_request);
-       INIT_WORK(&ni->swork, process_send_sockets);
-       ni->nodeid = nodeid;
-
-       if (nodeid > max_nodeid)
-               max_nodeid = nodeid;
-out_up:
-       up_write(&nodeinfo_lock);
-
-       return ni;
-}
-
-/* Don't call this too often... */
-static struct nodeinfo *assoc2nodeinfo(sctp_assoc_t assoc)
-{
-       int i;
-       struct nodeinfo *ni;
-
-       for (i=1; i<=max_nodeid; i++) {
-               ni = nodeid2nodeinfo(i, 0);
-               if (ni && ni->assoc_id == assoc)
-                       return ni;
-       }
-       return NULL;
-}
-
-/* Data or notification available on socket */
-static void lowcomms_data_ready(struct sock *sk, int count_unused)
-{
-       if (test_and_set_bit(CF_READ_PENDING, &sctp_con.flags))
-               queue_work(recv_workqueue, &sctp_con.work);
-}
-
-
-/* Add the port number to an IP6 or 4 sockaddr and return the address length.
-   Also padd out the struct with zeros to make comparisons meaningful */
-
-static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
-                         int *addr_len)
-{
-       struct sockaddr_in *local4_addr;
-       struct sockaddr_in6 *local6_addr;
-
-       if (!dlm_local_count)
-               return;
-
-       if (!port) {
-               if (dlm_local_addr[0]->ss_family == AF_INET) {
-                       local4_addr = (struct sockaddr_in *)dlm_local_addr[0];
-                       port = be16_to_cpu(local4_addr->sin_port);
-               } else {
-                       local6_addr = (struct sockaddr_in6 *)dlm_local_addr[0];
-                       port = be16_to_cpu(local6_addr->sin6_port);
-               }
-       }
-
-       saddr->ss_family = dlm_local_addr[0]->ss_family;
-       if (dlm_local_addr[0]->ss_family == AF_INET) {
-               struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
-               in4_addr->sin_port = cpu_to_be16(port);
-               memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero));
-               memset(in4_addr+1, 0, sizeof(struct sockaddr_storage) -
-                      sizeof(struct sockaddr_in));
-               *addr_len = sizeof(struct sockaddr_in);
-       } else {
-               struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr;
-               in6_addr->sin6_port = cpu_to_be16(port);
-               memset(in6_addr+1, 0, sizeof(struct sockaddr_storage) -
-                      sizeof(struct sockaddr_in6));
-               *addr_len = sizeof(struct sockaddr_in6);
-       }
-}
-
-/* Close the connection and tidy up */
-static void close_connection(void)
-{
-       if (sctp_con.sock) {
-               sock_release(sctp_con.sock);
-               sctp_con.sock = NULL;
-       }
-
-       if (sctp_con.rx_page) {
-               __free_page(sctp_con.rx_page);
-               sctp_con.rx_page = NULL;
-       }
-}
-
-/* We only send shutdown messages to nodes that are not part of the cluster */
-static void send_shutdown(sctp_assoc_t associd)
-{
-       static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
-       struct msghdr outmessage;
-       struct cmsghdr *cmsg;
-       struct sctp_sndrcvinfo *sinfo;
-       int ret;
-
-       outmessage.msg_name = NULL;
-       outmessage.msg_namelen = 0;
-       outmessage.msg_control = outcmsg;
-       outmessage.msg_controllen = sizeof(outcmsg);
-       outmessage.msg_flags = MSG_EOR;
-
-       cmsg = CMSG_FIRSTHDR(&outmessage);
-       cmsg->cmsg_level = IPPROTO_SCTP;
-       cmsg->cmsg_type = SCTP_SNDRCV;
-       cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-       outmessage.msg_controllen = cmsg->cmsg_len;
-       sinfo = CMSG_DATA(cmsg);
-       memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
-
-       sinfo->sinfo_flags |= MSG_EOF;
-       sinfo->sinfo_assoc_id = associd;
-
-       ret = kernel_sendmsg(sctp_con.sock, &outmessage, NULL, 0, 0);
-
-       if (ret != 0)
-               log_print("send EOF to node failed: %d", ret);
-}
-
-
-/* INIT failed but we don't know which node...
-   restart INIT on all pending nodes */
-static void init_failed(void)
-{
-       int i;
-       struct nodeinfo *ni;
-
-       for (i=1; i<=max_nodeid; i++) {
-               ni = nodeid2nodeinfo(i, 0);
-               if (!ni)
-                       continue;
-
-               if (test_and_clear_bit(NI_INIT_PENDING, &ni->flags)) {
-                       ni->assoc_id = 0;
-                       if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) {
-                               spin_lock_bh(&write_nodes_lock);
-                               list_add_tail(&ni->write_list, &write_nodes);
-                               spin_unlock_bh(&write_nodes_lock);
-                               queue_work(send_workqueue, &ni->swork);
-                       }
-               }
-       }
-}
-
-/* Something happened to an association */
-static void process_sctp_notification(struct msghdr *msg, char *buf)
-{
-       union sctp_notification *sn = (union sctp_notification *)buf;
-
-       if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
-               switch (sn->sn_assoc_change.sac_state) {
-
-               case SCTP_COMM_UP:
-               case SCTP_RESTART:
-               {
-                       /* Check that the new node is in the lockspace */
-                       struct sctp_prim prim;
-                       mm_segment_t fs;
-                       int nodeid;
-                       int prim_len, ret;
-                       int addr_len;
-                       struct nodeinfo *ni;
-
-                       /* This seems to happen when we received a connection
-                        * too early... or something...  anyway, it happens but
-                        * we always seem to get a real message too, see
-                        * receive_from_sock */
-
-                       if ((int)sn->sn_assoc_change.sac_assoc_id <= 0) {
-                               log_print("COMM_UP for invalid assoc ID %d",
-                                         (int)sn->sn_assoc_change.sac_assoc_id);
-                               init_failed();
-                               return;
-                       }
-                       memset(&prim, 0, sizeof(struct sctp_prim));
-                       prim_len = sizeof(struct sctp_prim);
-                       prim.ssp_assoc_id = sn->sn_assoc_change.sac_assoc_id;
-
-                       fs = get_fs();
-                       set_fs(get_ds());
-                       ret = sctp_con.sock->ops->getsockopt(sctp_con.sock,
-                                                            IPPROTO_SCTP,
-                                                            SCTP_PRIMARY_ADDR,
-                                                            (char*)&prim,
-                                                            &prim_len);
-                       set_fs(fs);
-                       if (ret < 0) {
-                               struct nodeinfo *ni;
-
-                               log_print("getsockopt/sctp_primary_addr on "
-                                         "new assoc %d failed : %d",
-                                         (int)sn->sn_assoc_change.sac_assoc_id,
-                                         ret);
-
-                               /* Retry INIT later */
-                               ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id);
-                               if (ni)
-                                       clear_bit(NI_INIT_PENDING, &ni->flags);
-                               return;
-                       }
-                       make_sockaddr(&prim.ssp_addr, 0, &addr_len);
-                       if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) {
-                               log_print("reject connect from unknown addr");
-                               send_shutdown(prim.ssp_assoc_id);
-                               return;
-                       }
-
-                       ni = nodeid2nodeinfo(nodeid, GFP_KERNEL);
-                       if (!ni)
-                               return;
-
-                       /* Save the assoc ID */
-                       ni->assoc_id = sn->sn_assoc_change.sac_assoc_id;
-
-                       log_print("got new/restarted association %d nodeid %d",
-                                 (int)sn->sn_assoc_change.sac_assoc_id, nodeid);
-
-                       /* Send any pending writes */
-                       clear_bit(NI_INIT_PENDING, &ni->flags);
-                       if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) {
-                               spin_lock_bh(&write_nodes_lock);
-                               list_add_tail(&ni->write_list, &write_nodes);
-                               spin_unlock_bh(&write_nodes_lock);
-                               queue_work(send_workqueue, &ni->swork);
-                       }
-               }
-               break;
-
-               case SCTP_COMM_LOST:
-               case SCTP_SHUTDOWN_COMP:
-               {
-                       struct nodeinfo *ni;
-
-                       ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id);
-                       if (ni) {
-                               spin_lock(&ni->lock);
-                               ni->assoc_id = 0;
-                               spin_unlock(&ni->lock);
-                       }
-               }
-               break;
-
-               /* We don't know which INIT failed, so clear the PENDING flags
-                * on them all.  if assoc_id is zero then it will then try
-                * again */
-
-               case SCTP_CANT_STR_ASSOC:
-               {
-                       log_print("Can't start SCTP association - retrying");
-                       init_failed();
-               }
-               break;
-
-               default:
-                       log_print("unexpected SCTP assoc change id=%d state=%d",
-                                 (int)sn->sn_assoc_change.sac_assoc_id,
-                                 sn->sn_assoc_change.sac_state);
-               }
-       }
-}
-
-/* Data received from remote end */
-static int receive_from_sock(void)
-{
-       int ret = 0;
-       struct msghdr msg;
-       struct kvec iov[2];
-       unsigned len;
-       int r;
-       struct sctp_sndrcvinfo *sinfo;
-       struct cmsghdr *cmsg;
-       struct nodeinfo *ni;
-
-       /* These two are marginally too big for stack allocation, but this
-        * function is (currently) only called by dlm_recvd so static should be
-        * OK.
-        */
-       static struct sockaddr_storage msgname;
-       static char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
-
-       if (sctp_con.sock == NULL)
-               goto out;
-
-       if (sctp_con.rx_page == NULL) {
-               /*
-                * This doesn't need to be atomic, but I think it should
-                * improve performance if it is.
-                */
-               sctp_con.rx_page = alloc_page(GFP_ATOMIC);
-               if (sctp_con.rx_page == NULL)
-                       goto out_resched;
-               cbuf_init(&sctp_con.cb, PAGE_CACHE_SIZE);
-       }
-
-       memset(&incmsg, 0, sizeof(incmsg));
-       memset(&msgname, 0, sizeof(msgname));
-
-       msg.msg_name = &msgname;
-       msg.msg_namelen = sizeof(msgname);
-       msg.msg_flags = 0;
-       msg.msg_control = incmsg;
-       msg.msg_controllen = sizeof(incmsg);
-       msg.msg_iovlen = 1;
-
-       /* I don't see why this circular buffer stuff is necessary for SCTP
-        * which is a packet-based protocol, but the whole thing breaks under
-        * load without it! The overhead is minimal (and is in the TCP lowcomms
-        * anyway, of course) so I'll leave it in until I can figure out what's
-        * really happening.
-        */
-
-       /*
-        * iov[0] is the bit of the circular buffer between the current end
-        * point (cb.base + cb.len) and the end of the buffer.
-        */
-       iov[0].iov_len = sctp_con.cb.base - cbuf_data(&sctp_con.cb);
-       iov[0].iov_base = page_address(sctp_con.rx_page) +
-               cbuf_data(&sctp_con.cb);
-       iov[1].iov_len = 0;
-
-       /*
-        * iov[1] is the bit of the circular buffer between the start of the
-        * buffer and the start of the currently used section (cb.base)
-        */
-       if (cbuf_data(&sctp_con.cb) >= sctp_con.cb.base) {
-               iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&sctp_con.cb);
-               iov[1].iov_len = sctp_con.cb.base;
-               iov[1].iov_base = page_address(sctp_con.rx_page);
-               msg.msg_iovlen = 2;
-       }
-       len = iov[0].iov_len + iov[1].iov_len;
-
-       r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, msg.msg_iovlen, len,
-                                MSG_NOSIGNAL | MSG_DONTWAIT);
-       if (ret <= 0)
-               goto out_close;
-
-       msg.msg_control = incmsg;
-       msg.msg_controllen = sizeof(incmsg);
-       cmsg = CMSG_FIRSTHDR(&msg);
-       sinfo = CMSG_DATA(cmsg);
-
-       if (msg.msg_flags & MSG_NOTIFICATION) {
-               process_sctp_notification(&msg, page_address(sctp_con.rx_page));
-               return 0;
-       }
-
-       /* Is this a new association ? */
-       ni = nodeid2nodeinfo(le32_to_cpu(sinfo->sinfo_ppid), GFP_KERNEL);
-       if (ni) {
-               ni->assoc_id = sinfo->sinfo_assoc_id;
-               if (test_and_clear_bit(NI_INIT_PENDING, &ni->flags)) {
-
-                       if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) {
-                               spin_lock_bh(&write_nodes_lock);
-                               list_add_tail(&ni->write_list, &write_nodes);
-                               spin_unlock_bh(&write_nodes_lock);
-                               queue_work(send_workqueue, &ni->swork);
-                       }
-               }
-       }
-
-       /* INIT sends a message with length of 1 - ignore it */
-       if (r == 1)
-               return 0;
-
-       cbuf_add(&sctp_con.cb, ret);
-       // PJC: TODO: Add to node's workqueue....can we ??
-       ret = dlm_process_incoming_buffer(cpu_to_le32(sinfo->sinfo_ppid),
-                                         page_address(sctp_con.rx_page),
-                                         sctp_con.cb.base, sctp_con.cb.len,
-                                         PAGE_CACHE_SIZE);
-       if (ret < 0)
-               goto out_close;
-       cbuf_eat(&sctp_con.cb, ret);
-
-out:
-       ret = 0;
-       goto out_ret;
-
-out_resched:
-       lowcomms_data_ready(sctp_con.sock->sk, 0);
-       ret = 0;
-       cond_resched();
-       goto out_ret;
-
-out_close:
-       if (ret != -EAGAIN)
-               log_print("error reading from sctp socket: %d", ret);
-out_ret:
-       return ret;
-}
-
-/* Bind to an IP address. SCTP allows multiple address so it can do multi-homing */
-static int add_bind_addr(struct sockaddr_storage *addr, int addr_len, int num)
-{
-       mm_segment_t fs;
-       int result = 0;
-
-       fs = get_fs();
-       set_fs(get_ds());
-       if (num == 1)
-               result = sctp_con.sock->ops->bind(sctp_con.sock,
-                                                 (struct sockaddr *) addr,
-                                                 addr_len);
-       else
-               result = sctp_con.sock->ops->setsockopt(sctp_con.sock, SOL_SCTP,
-                                                       SCTP_SOCKOPT_BINDX_ADD,
-                                                       (char *)addr, addr_len);
-       set_fs(fs);
-
-       if (result < 0)
-               log_print("Can't bind to port %d addr number %d",
-                         dlm_config.ci_tcp_port, num);
-
-       return result;
-}
-
-static void init_local(void)
-{
-       struct sockaddr_storage sas, *addr;
-       int i;
-
-       dlm_local_nodeid = dlm_our_nodeid();
-
-       for (i = 0; i < DLM_MAX_ADDR_COUNT - 1; i++) {
-               if (dlm_our_addr(&sas, i))
-                       break;
-
-               addr = kmalloc(sizeof(*addr), GFP_KERNEL);
-               if (!addr)
-                       break;
-               memcpy(addr, &sas, sizeof(*addr));
-               dlm_local_addr[dlm_local_count++] = addr;
-       }
-}
-
-/* Initialise SCTP socket and bind to all interfaces */
-static int init_sock(void)
-{
-       mm_segment_t fs;
-       struct socket *sock = NULL;
-       struct sockaddr_storage localaddr;
-       struct sctp_event_subscribe subscribe;
-       int result = -EINVAL, num = 1, i, addr_len;
-
-       if (!dlm_local_count) {
-               init_local();
-               if (!dlm_local_count) {
-                       log_print("no local IP address has been set");
-                       goto out;
-               }
-       }
-
-       result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_SEQPACKET,
-                                 IPPROTO_SCTP, &sock);
-       if (result < 0) {
-               log_print("Can't create comms socket, check SCTP is loaded");
-               goto out;
-       }
-
-       /* Listen for events */
-       memset(&subscribe, 0, sizeof(subscribe));
-       subscribe.sctp_data_io_event = 1;
-       subscribe.sctp_association_event = 1;
-       subscribe.sctp_send_failure_event = 1;
-       subscribe.sctp_shutdown_event = 1;
-       subscribe.sctp_partial_delivery_event = 1;
-
-       fs = get_fs();
-       set_fs(get_ds());
-       result = sock->ops->setsockopt(sock, SOL_SCTP, SCTP_EVENTS,
-                                      (char *)&subscribe, sizeof(subscribe));
-       set_fs(fs);
-
-       if (result < 0) {
-               log_print("Failed to set SCTP_EVENTS on socket: result=%d",
-                         result);
-               goto create_delsock;
-       }
-
-       /* Init con struct */
-       sock->sk->sk_user_data = &sctp_con;
-       sctp_con.sock = sock;
-       sctp_con.sock->sk->sk_data_ready = lowcomms_data_ready;
-
-       /* Bind to all interfaces. */
-       for (i = 0; i < dlm_local_count; i++) {
-               memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr));
-               make_sockaddr(&localaddr, dlm_config.ci_tcp_port, &addr_len);
-
-               result = add_bind_addr(&localaddr, addr_len, num);
-               if (result)
-                       goto create_delsock;
-               ++num;
-       }
-
-       result = sock->ops->listen(sock, 5);
-       if (result < 0) {
-               log_print("Can't set socket listening");
-               goto create_delsock;
-       }
-
-       return 0;
-
-create_delsock:
-       sock_release(sock);
-       sctp_con.sock = NULL;
-out:
-       return result;
-}
-
-
-static struct writequeue_entry *new_writequeue_entry(gfp_t allocation)
-{
-       struct writequeue_entry *entry;
-
-       entry = kmalloc(sizeof(struct writequeue_entry), allocation);
-       if (!entry)
-               return NULL;
-
-       entry->page = alloc_page(allocation);
-       if (!entry->page) {
-               kfree(entry);
-               return NULL;
-       }
-
-       entry->offset = 0;
-       entry->len = 0;
-       entry->end = 0;
-       entry->users = 0;
-
-       return entry;
-}
-
-void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
-{
-       struct writequeue_entry *e;
-       int offset = 0;
-       int users = 0;
-       struct nodeinfo *ni;
-
-       ni = nodeid2nodeinfo(nodeid, allocation);
-       if (!ni)
-               return NULL;
-
-       spin_lock(&ni->writequeue_lock);
-       e = list_entry(ni->writequeue.prev, struct writequeue_entry, list);
-       if ((&e->list == &ni->writequeue) ||
-           (PAGE_CACHE_SIZE - e->end < len)) {
-               e = NULL;
-       } else {
-               offset = e->end;
-               e->end += len;
-               users = e->users++;
-       }
-       spin_unlock(&ni->writequeue_lock);
-
-       if (e) {
-       got_one:
-               if (users == 0)
-                       kmap(e->page);
-               *ppc = page_address(e->page) + offset;
-               return e;
-       }
-
-       e = new_writequeue_entry(allocation);
-       if (e) {
-               spin_lock(&ni->writequeue_lock);
-               offset = e->end;
-               e->end += len;
-               e->ni = ni;
-               users = e->users++;
-               list_add_tail(&e->list, &ni->writequeue);
-               spin_unlock(&ni->writequeue_lock);
-               goto got_one;
-       }
-       return NULL;
-}
-
-void dlm_lowcomms_commit_buffer(void *arg)
-{
-       struct writequeue_entry *e = (struct writequeue_entry *) arg;
-       int users;
-       struct nodeinfo *ni = e->ni;
-
-       spin_lock(&ni->writequeue_lock);
-       users = --e->users;
-       if (users)
-               goto out;
-       e->len = e->end - e->offset;
-       kunmap(e->page);
-       spin_unlock(&ni->writequeue_lock);
-
-       if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) {
-               spin_lock_bh(&write_nodes_lock);
-               list_add_tail(&ni->write_list, &write_nodes);
-               spin_unlock_bh(&write_nodes_lock);
-
-               queue_work(send_workqueue, &ni->swork);
-       }
-       return;
-
-out:
-       spin_unlock(&ni->writequeue_lock);
-       return;
-}
-
-static void free_entry(struct writequeue_entry *e)
-{
-       __free_page(e->page);
-       kfree(e);
-}
-
-/* Initiate an SCTP association. In theory we could just use sendmsg() on
-   the first IP address and it should work, but this allows us to set up the
-   association before sending any valuable data that we can't afford to lose.
-   It also keeps the send path clean as it can now always use the association ID */
-static void initiate_association(int nodeid)
-{
-       struct sockaddr_storage rem_addr;
-       static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
-       struct msghdr outmessage;
-       struct cmsghdr *cmsg;
-       struct sctp_sndrcvinfo *sinfo;
-       int ret;
-       int addrlen;
-       char buf[1];
-       struct kvec iov[1];
-       struct nodeinfo *ni;
-
-       log_print("Initiating association with node %d", nodeid);
-
-       ni = nodeid2nodeinfo(nodeid, GFP_KERNEL);
-       if (!ni)
-               return;
-
-       if (nodeid_to_addr(nodeid, (struct sockaddr *)&rem_addr)) {
-               log_print("no address for nodeid %d", nodeid);
-               return;
-       }
-
-       make_sockaddr(&rem_addr, dlm_config.ci_tcp_port, &addrlen);
-
-       outmessage.msg_name = &rem_addr;
-       outmessage.msg_namelen = addrlen;
-       outmessage.msg_control = outcmsg;
-       outmessage.msg_controllen = sizeof(outcmsg);
-       outmessage.msg_flags = MSG_EOR;
-
-       iov[0].iov_base = buf;
-       iov[0].iov_len = 1;
-
-       /* Real INIT messages seem to cause trouble. Just send a 1 byte message
-          we can afford to lose */
-       cmsg = CMSG_FIRSTHDR(&outmessage);
-       cmsg->cmsg_level = IPPROTO_SCTP;
-       cmsg->cmsg_type = SCTP_SNDRCV;
-       cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-       sinfo = CMSG_DATA(cmsg);
-       memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
-       sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid);
-
-       outmessage.msg_controllen = cmsg->cmsg_len;
-       ret = kernel_sendmsg(sctp_con.sock, &outmessage, iov, 1, 1);
-       if (ret < 0) {
-               log_print("send INIT to node failed: %d", ret);
-               /* Try again later */
-               clear_bit(NI_INIT_PENDING, &ni->flags);
-       }
-}
-
-/* Send a message */
-static void send_to_sock(struct nodeinfo *ni)
-{
-       int ret = 0;
-       struct writequeue_entry *e;
-       int len, offset;
-       struct msghdr outmsg;
-       static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
-       struct cmsghdr *cmsg;
-       struct sctp_sndrcvinfo *sinfo;
-       struct kvec iov;
-
-       /* See if we need to init an association before we start
-          sending precious messages */
-       spin_lock(&ni->lock);
-       if (!ni->assoc_id && !test_and_set_bit(NI_INIT_PENDING, &ni->flags)) {
-               spin_unlock(&ni->lock);
-               initiate_association(ni->nodeid);
-               return;
-       }
-       spin_unlock(&ni->lock);
-
-       outmsg.msg_name = NULL; /* We use assoc_id */
-       outmsg.msg_namelen = 0;
-       outmsg.msg_control = outcmsg;
-       outmsg.msg_controllen = sizeof(outcmsg);
-       outmsg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL | MSG_EOR;
-
-       cmsg = CMSG_FIRSTHDR(&outmsg);
-       cmsg->cmsg_level = IPPROTO_SCTP;
-       cmsg->cmsg_type = SCTP_SNDRCV;
-       cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-       sinfo = CMSG_DATA(cmsg);
-       memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
-       sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid);
-       sinfo->sinfo_assoc_id = ni->assoc_id;
-       outmsg.msg_controllen = cmsg->cmsg_len;
-
-       spin_lock(&ni->writequeue_lock);
-       for (;;) {
-               if (list_empty(&ni->writequeue))
-                       break;
-               e = list_entry(ni->writequeue.next, struct writequeue_entry,
-                              list);
-               len = e->len;
-               offset = e->offset;
-               BUG_ON(len == 0 && e->users == 0);
-               spin_unlock(&ni->writequeue_lock);
-               kmap(e->page);
-
-               ret = 0;
-               if (len) {
-                       iov.iov_base = page_address(e->page)+offset;
-                       iov.iov_len = len;
-
-                       ret = kernel_sendmsg(sctp_con.sock, &outmsg, &iov, 1,
-                                            len);
-                       if (ret == -EAGAIN) {
-                               sctp_con.eagain_flag = 1;
-                               goto out;
-                       } else if (ret < 0)
-                               goto send_error;
-               } else {
-                       /* Don't starve people filling buffers */
-                       cond_resched();
-               }
-
-               spin_lock(&ni->writequeue_lock);
-               e->offset += ret;
-               e->len -= ret;
-
-               if (e->len == 0 && e->users == 0) {
-                       list_del(&e->list);
-                       kunmap(e->page);
-                       free_entry(e);
-                       continue;
-               }
-       }
-       spin_unlock(&ni->writequeue_lock);
-out:
-       return;
-
-send_error:
-       log_print("Error sending to node %d %d", ni->nodeid, ret);
-       spin_lock(&ni->lock);
-       if (!test_and_set_bit(NI_INIT_PENDING, &ni->flags)) {
-               ni->assoc_id = 0;
-               spin_unlock(&ni->lock);
-               initiate_association(ni->nodeid);
-       } else
-               spin_unlock(&ni->lock);
-
-       return;
-}
-
-/* Try to send any messages that are pending */
-static void process_output_queue(void)
-{
-       struct list_head *list;
-       struct list_head *temp;
-
-       spin_lock_bh(&write_nodes_lock);
-       list_for_each_safe(list, temp, &write_nodes) {
-               struct nodeinfo *ni =
-                       list_entry(list, struct nodeinfo, write_list);
-               clear_bit(NI_WRITE_PENDING, &ni->flags);
-               list_del(&ni->write_list);
-
-               spin_unlock_bh(&write_nodes_lock);
-
-               send_to_sock(ni);
-               spin_lock_bh(&write_nodes_lock);
-       }
-       spin_unlock_bh(&write_nodes_lock);
-}
-
-/* Called after we've had -EAGAIN and been woken up */
-static void refill_write_queue(void)
-{
-       int i;
-
-       for (i=1; i<=max_nodeid; i++) {
-               struct nodeinfo *ni = nodeid2nodeinfo(i, 0);
-
-               if (ni) {
-                       if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) {
-                               spin_lock_bh(&write_nodes_lock);
-                               list_add_tail(&ni->write_list, &write_nodes);
-                               spin_unlock_bh(&write_nodes_lock);
-                       }
-               }
-       }
-}
-
-static void clean_one_writequeue(struct nodeinfo *ni)
-{
-       struct list_head *list;
-       struct list_head *temp;
-
-       spin_lock(&ni->writequeue_lock);
-       list_for_each_safe(list, temp, &ni->writequeue) {
-               struct writequeue_entry *e =
-                       list_entry(list, struct writequeue_entry, list);
-               list_del(&e->list);
-               free_entry(e);
-       }
-       spin_unlock(&ni->writequeue_lock);
-}
-
-static void clean_writequeues(void)
-{
-       int i;
-
-       for (i=1; i<=max_nodeid; i++) {
-               struct nodeinfo *ni = nodeid2nodeinfo(i, 0);
-               if (ni)
-                       clean_one_writequeue(ni);
-       }
-}
-
-
-static void dealloc_nodeinfo(void)
-{
-       int i;
-
-       for (i=1; i<=max_nodeid; i++) {
-               struct nodeinfo *ni = nodeid2nodeinfo(i, 0);
-               if (ni) {
-                       idr_remove(&nodeinfo_idr, i);
-                       kfree(ni);
-               }
-       }
-}
-
-int dlm_lowcomms_close(int nodeid)
-{
-       struct nodeinfo *ni;
-
-       ni = nodeid2nodeinfo(nodeid, 0);
-       if (!ni)
-               return -1;
-
-       spin_lock(&ni->lock);
-       if (ni->assoc_id) {
-               ni->assoc_id = 0;
-               /* Don't send shutdown here, sctp will just queue it
-                  till the node comes back up! */
-       }
-       spin_unlock(&ni->lock);
-
-       clean_one_writequeue(ni);
-       clear_bit(NI_INIT_PENDING, &ni->flags);
-       return 0;
-}
-
-// PJC: The work queue function for receiving.
-static void process_recv_sockets(struct work_struct *work)
-{
-       if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) {
-               int ret;
-               int count = 0;
-
-               do {
-                       ret = receive_from_sock();
-
-                       /* Don't starve out everyone else */
-                       if (++count >= MAX_RX_MSG_COUNT) {
-                               cond_resched();
-                               count = 0;
-                       }
-               } while (!kthread_should_stop() && ret >=0);
-       }
-       cond_resched();
-}
-
-// PJC: the work queue function for sending
-static void process_send_sockets(struct work_struct *work)
-{
-       if (sctp_con.eagain_flag) {
-               sctp_con.eagain_flag = 0;
-               refill_write_queue();
-       }
-       process_output_queue();
-}
-
-// PJC: Process lock requests from a particular node.
-// TODO: can we optimise this out on UP ??
-static void process_lock_request(struct work_struct *work)
-{
-}
-
-static void daemons_stop(void)
-{
-       destroy_workqueue(recv_workqueue);
-       destroy_workqueue(send_workqueue);
-       destroy_workqueue(lock_workqueue);
-}
-
-static int daemons_start(void)
-{
-       int error;
-       recv_workqueue = create_workqueue("dlm_recv");
-       error = IS_ERR(recv_workqueue);
-       if (error) {
-               log_print("can't start dlm_recv %d", error);
-               return error;
-       }
-
-       send_workqueue = create_singlethread_workqueue("dlm_send");
-       error = IS_ERR(send_workqueue);
-       if (error) {
-               log_print("can't start dlm_send %d", error);
-               destroy_workqueue(recv_workqueue);
-               return error;
-       }
-
-       lock_workqueue = create_workqueue("dlm_rlock");
-       error = IS_ERR(lock_workqueue);
-       if (error) {
-               log_print("can't start dlm_rlock %d", error);
-               destroy_workqueue(send_workqueue);
-               destroy_workqueue(recv_workqueue);
-               return error;
-       }
-
-       return 0;
-}
-
-/*
- * This is quite likely to sleep...
- */
-int dlm_lowcomms_start(void)
-{
-       int error;
-
-       INIT_WORK(&sctp_con.work, process_recv_sockets);
-
-       error = init_sock();
-       if (error)
-               goto fail_sock;
-       error = daemons_start();
-       if (error)
-               goto fail_sock;
-       return 0;
-
-fail_sock:
-       close_connection();
-       return error;
-}
-
-void dlm_lowcomms_stop(void)
-{
-       int i;
-
-       sctp_con.flags = 0x7;
-       daemons_stop();
-       clean_writequeues();
-       close_connection();
-       dealloc_nodeinfo();
-       max_nodeid = 0;
-
-       dlm_local_count = 0;
-       dlm_local_nodeid = 0;
-
-       for (i = 0; i < dlm_local_count; i++)
-               kfree(dlm_local_addr[i]);
-}
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c
deleted file mode 100644 (file)
index 07e0a12..0000000
+++ /dev/null
@@ -1,1007 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
-**
-**  This copyrighted material is made available to anyone wishing to use,
-**  modify, copy, or redistribute it subject to the terms and conditions
-**  of the GNU General Public License v.2.
-**
-*******************************************************************************
-******************************************************************************/
-
-/*
- * lowcomms.c
- *
- * This is the "low-level" comms layer.
- *
- * It is responsible for sending/receiving messages
- * from other nodes in the cluster.
- *
- * Cluster nodes are referred to by their nodeids. nodeids are
- * simply 32 bit numbers to the locking module - if they need to
- * be expanded for the cluster infrastructure then that is it's
- * responsibility. It is this layer's
- * responsibility to resolve these into IP address or
- * whatever it needs for inter-node communication.
- *
- * The comms level is two kernel threads that deal mainly with
- * the receiving of messages from other nodes and passing them
- * up to the mid-level comms layer (which understands the
- * message format) for execution by the locking core, and
- * a send thread which does all the setting up of connections
- * to remote nodes and the sending of data. Threads are not allowed
- * to send their own data because it may cause them to wait in times
- * of high load. Also, this way, the sending thread can collect together
- * messages bound for one node and send them in one block.
- *
- * I don't see any problem with the recv thread executing the locking
- * code on behalf of remote processes as the locking code is
- * short, efficient and never waits.
- *
- */
-
-
-#include <asm/ioctls.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-#include <linux/pagemap.h>
-
-#include "dlm_internal.h"
-#include "lowcomms.h"
-#include "midcomms.h"
-#include "config.h"
-
-struct cbuf {
-       unsigned int base;
-       unsigned int len;
-       unsigned int mask;
-};
-
-#define NODE_INCREMENT 32
-static void cbuf_add(struct cbuf *cb, int n)
-{
-       cb->len += n;
-}
-
-static int cbuf_data(struct cbuf *cb)
-{
-       return ((cb->base + cb->len) & cb->mask);
-}
-
-static void cbuf_init(struct cbuf *cb, int size)
-{
-       cb->base = cb->len = 0;
-       cb->mask = size-1;
-}
-
-static void cbuf_eat(struct cbuf *cb, int n)
-{
-       cb->len  -= n;
-       cb->base += n;
-       cb->base &= cb->mask;
-}
-
-static bool cbuf_empty(struct cbuf *cb)
-{
-       return cb->len == 0;
-}
-
-/* Maximum number of incoming messages to process before
-   doing a cond_resched()
-*/
-#define MAX_RX_MSG_COUNT 25
-
-struct connection {
-       struct socket *sock;    /* NULL if not connected */
-       uint32_t nodeid;        /* So we know who we are in the list */
-       struct mutex sock_mutex;
-       unsigned long flags;    /* bit 1,2 = We are on the read/write lists */
-#define CF_READ_PENDING 1
-#define CF_WRITE_PENDING 2
-#define CF_CONNECT_PENDING 3
-#define CF_IS_OTHERCON 4
-       struct list_head writequeue;  /* List of outgoing writequeue_entries */
-       struct list_head listenlist;  /* List of allocated listening sockets */
-       spinlock_t writequeue_lock;
-       int (*rx_action) (struct connection *); /* What to do when active */
-       struct page *rx_page;
-       struct cbuf cb;
-       int retries;
-#define MAX_CONNECT_RETRIES 3
-       struct connection *othercon;
-       struct work_struct rwork; /* Receive workqueue */
-       struct work_struct swork; /* Send workqueue */
-};
-#define sock2con(x) ((struct connection *)(x)->sk_user_data)
-
-/* An entry waiting to be sent */
-struct writequeue_entry {
-       struct list_head list;
-       struct page *page;
-       int offset;
-       int len;
-       int end;
-       int users;
-       struct connection *con;
-};
-
-static struct sockaddr_storage dlm_local_addr;
-
-/* Work queues */
-static struct workqueue_struct *recv_workqueue;
-static struct workqueue_struct *send_workqueue;
-
-/* An array of pointers to connections, indexed by NODEID */
-static struct connection **connections;
-static DECLARE_MUTEX(connections_lock);
-static struct kmem_cache *con_cache;
-static int conn_array_size;
-
-static void process_recv_sockets(struct work_struct *work);
-static void process_send_sockets(struct work_struct *work);
-
-static struct connection *nodeid2con(int nodeid, gfp_t allocation)
-{
-       struct connection *con = NULL;
-
-       down(&connections_lock);
-       if (nodeid >= conn_array_size) {
-               int new_size = nodeid + NODE_INCREMENT;
-               struct connection **new_conns;
-
-               new_conns = kzalloc(sizeof(struct connection *) *
-                                   new_size, allocation);
-               if (!new_conns)
-                       goto finish;
-
-               memcpy(new_conns, connections,  sizeof(struct connection *) * conn_array_size);
-               conn_array_size = new_size;
-               kfree(connections);
-               connections = new_conns;
-
-       }
-
-       con = connections[nodeid];
-       if (con == NULL && allocation) {
-               con = kmem_cache_zalloc(con_cache, allocation);
-               if (!con)
-                       goto finish;
-
-               con->nodeid = nodeid;
-               mutex_init(&con->sock_mutex);
-               INIT_LIST_HEAD(&con->writequeue);
-               spin_lock_init(&con->writequeue_lock);
-               INIT_WORK(&con->swork, process_send_sockets);
-               INIT_WORK(&con->rwork, process_recv_sockets);
-
-               connections[nodeid] = con;
-       }
-
-finish:
-       up(&connections_lock);
-       return con;
-}
-
-/* Data available on socket or listen socket received a connect */
-static void lowcomms_data_ready(struct sock *sk, int count_unused)
-{
-       struct connection *con = sock2con(sk);
-
-       if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
-               queue_work(recv_workqueue, &con->rwork);
-}
-
-static void lowcomms_write_space(struct sock *sk)
-{
-       struct connection *con = sock2con(sk);
-
-       if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
-               queue_work(send_workqueue, &con->swork);
-}
-
-static inline void lowcomms_connect_sock(struct connection *con)
-{
-       if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags))
-               queue_work(send_workqueue, &con->swork);
-}
-
-static void lowcomms_state_change(struct sock *sk)
-{
-       if (sk->sk_state == TCP_ESTABLISHED)
-               lowcomms_write_space(sk);
-}
-
-/* Make a socket active */
-static int add_sock(struct socket *sock, struct connection *con)
-{
-       con->sock = sock;
-
-       /* Install a data_ready callback */
-       con->sock->sk->sk_data_ready = lowcomms_data_ready;
-       con->sock->sk->sk_write_space = lowcomms_write_space;
-       con->sock->sk->sk_state_change = lowcomms_state_change;
-
-       return 0;
-}
-
-/* Add the port number to an IP6 or 4 sockaddr and return the address
-   length */
-static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
-                         int *addr_len)
-{
-       saddr->ss_family =  dlm_local_addr.ss_family;
-       if (saddr->ss_family == AF_INET) {
-               struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
-               in4_addr->sin_port = cpu_to_be16(port);
-               *addr_len = sizeof(struct sockaddr_in);
-       } else {
-               struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr;
-               in6_addr->sin6_port = cpu_to_be16(port);
-               *addr_len = sizeof(struct sockaddr_in6);
-       }
-}
-
-/* Close a remote connection and tidy up */
-static void close_connection(struct connection *con, bool and_other)
-{
-       mutex_lock(&con->sock_mutex);
-
-       if (con->sock) {
-               sock_release(con->sock);
-               con->sock = NULL;
-       }
-       if (con->othercon && and_other) {
-               /* Will only re-enter once. */
-               close_connection(con->othercon, false);
-       }
-       if (con->rx_page) {
-               __free_page(con->rx_page);
-               con->rx_page = NULL;
-       }
-       con->retries = 0;
-       mutex_unlock(&con->sock_mutex);
-}
-
-/* Data received from remote end */
-static int receive_from_sock(struct connection *con)
-{
-       int ret = 0;
-       struct msghdr msg = {};
-       struct kvec iov[2];
-       unsigned len;
-       int r;
-       int call_again_soon = 0;
-       int nvec;
-
-       mutex_lock(&con->sock_mutex);
-
-       if (con->sock == NULL) {
-               ret = -EAGAIN;
-               goto out_close;
-       }
-
-       if (con->rx_page == NULL) {
-               /*
-                * This doesn't need to be atomic, but I think it should
-                * improve performance if it is.
-                */
-               con->rx_page = alloc_page(GFP_ATOMIC);
-               if (con->rx_page == NULL)
-                       goto out_resched;
-               cbuf_init(&con->cb, PAGE_CACHE_SIZE);
-       }
-
-       /*
-        * iov[0] is the bit of the circular buffer between the current end
-        * point (cb.base + cb.len) and the end of the buffer.
-        */
-       iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
-       iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
-       nvec = 1;
-
-       /*
-        * iov[1] is the bit of the circular buffer between the start of the
-        * buffer and the start of the currently used section (cb.base)
-        */
-       if (cbuf_data(&con->cb) >= con->cb.base) {
-               iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
-               iov[1].iov_len = con->cb.base;
-               iov[1].iov_base = page_address(con->rx_page);
-               nvec = 2;
-       }
-       len = iov[0].iov_len + iov[1].iov_len;
-
-       r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len,
-                              MSG_DONTWAIT | MSG_NOSIGNAL);
-
-       if (ret <= 0)
-               goto out_close;
-       if (ret == -EAGAIN)
-               goto out_resched;
-
-       if (ret == len)
-               call_again_soon = 1;
-       cbuf_add(&con->cb, ret);
-       ret = dlm_process_incoming_buffer(con->nodeid,
-                                         page_address(con->rx_page),
-                                         con->cb.base, con->cb.len,
-                                         PAGE_CACHE_SIZE);
-       if (ret == -EBADMSG) {
-               printk(KERN_INFO "dlm: lowcomms: addr=%p, base=%u, len=%u, "
-                      "iov_len=%u, iov_base[0]=%p, read=%d\n",
-                      page_address(con->rx_page), con->cb.base, con->cb.len,
-                      len, iov[0].iov_base, r);
-       }
-       if (ret < 0)
-               goto out_close;
-       cbuf_eat(&con->cb, ret);
-
-       if (cbuf_empty(&con->cb) && !call_again_soon) {
-               __free_page(con->rx_page);
-               con->rx_page = NULL;
-       }
-
-       if (call_again_soon)
-               goto out_resched;
-       mutex_unlock(&con->sock_mutex);
-       return 0;
-
-out_resched:
-       if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
-               queue_work(recv_workqueue, &con->rwork);
-       mutex_unlock(&con->sock_mutex);
-       return -EAGAIN;
-
-out_close:
-       mutex_unlock(&con->sock_mutex);
-       if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
-               close_connection(con, false);
-               /* Reconnect when there is something to send */
-       }
-       /* Don't return success if we really got EOF */
-       if (ret == 0)
-               ret = -EAGAIN;
-
-       return ret;
-}
-
-/* Listening socket is busy, accept a connection */
-static int accept_from_sock(struct connection *con)
-{
-       int result;
-       struct sockaddr_storage peeraddr;
-       struct socket *newsock;
-       int len;
-       int nodeid;
-       struct connection *newcon;
-       struct connection *addcon;
-
-       memset(&peeraddr, 0, sizeof(peeraddr));
-       result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM,
-                                 IPPROTO_TCP, &newsock);
-       if (result < 0)
-               return -ENOMEM;
-
-       mutex_lock_nested(&con->sock_mutex, 0);
-
-       result = -ENOTCONN;
-       if (con->sock == NULL)
-               goto accept_err;
-
-       newsock->type = con->sock->type;
-       newsock->ops = con->sock->ops;
-
-       result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK);
-       if (result < 0)
-               goto accept_err;
-
-       /* Get the connected socket's peer */
-       memset(&peeraddr, 0, sizeof(peeraddr));
-       if (newsock->ops->getname(newsock, (struct sockaddr *)&peeraddr,
-                                 &len, 2)) {
-               result = -ECONNABORTED;
-               goto accept_err;
-       }
-
-       /* Get the new node's NODEID */
-       make_sockaddr(&peeraddr, 0, &len);
-       if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
-               printk("dlm: connect from non cluster node\n");
-               sock_release(newsock);
-               mutex_unlock(&con->sock_mutex);
-               return -1;
-       }
-
-       log_print("got connection from %d", nodeid);
-
-       /*  Check to see if we already have a connection to this node. This
-        *  could happen if the two nodes initiate a connection at roughly
-        *  the same time and the connections cross on the wire.
-        * TEMPORARY FIX:
-        *  In this case we store the incoming one in "othercon"
-        */
-       newcon = nodeid2con(nodeid, GFP_KERNEL);
-       if (!newcon) {
-               result = -ENOMEM;
-               goto accept_err;
-       }
-       mutex_lock_nested(&newcon->sock_mutex, 1);
-       if (newcon->sock) {
-               struct connection *othercon = newcon->othercon;
-
-               if (!othercon) {
-                       othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
-                       if (!othercon) {
-                               printk("dlm: failed to allocate incoming socket\n");
-                               mutex_unlock(&newcon->sock_mutex);
-                               result = -ENOMEM;
-                               goto accept_err;
-                       }
-                       othercon->nodeid = nodeid;
-                       othercon->rx_action = receive_from_sock;
-                       mutex_init(&othercon->sock_mutex);
-                       INIT_WORK(&othercon->swork, process_send_sockets);
-                       INIT_WORK(&othercon->rwork, process_recv_sockets);
-                       set_bit(CF_IS_OTHERCON, &othercon->flags);
-                       newcon->othercon = othercon;
-               }
-               othercon->sock = newsock;
-               newsock->sk->sk_user_data = othercon;
-               add_sock(newsock, othercon);
-               addcon = othercon;
-       }
-       else {
-               newsock->sk->sk_user_data = newcon;
-               newcon->rx_action = receive_from_sock;
-               add_sock(newsock, newcon);
-               addcon = newcon;
-       }
-
-       mutex_unlock(&newcon->sock_mutex);
-
-       /*
-        * Add it to the active queue in case we got data
-        * beween processing the accept adding the socket
-        * to the read_sockets list
-        */
-       if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
-               queue_work(recv_workqueue, &addcon->rwork);
-       mutex_unlock(&con->sock_mutex);
-
-       return 0;
-
-accept_err:
-       mutex_unlock(&con->sock_mutex);
-       sock_release(newsock);
-
-       if (result != -EAGAIN)
-               printk("dlm: error accepting connection from node: %d\n", result);
-       return result;
-}
-
-/* Connect a new socket to its peer */
-static void connect_to_sock(struct connection *con)
-{
-       int result = -EHOSTUNREACH;
-       struct sockaddr_storage saddr;
-       int addr_len;
-       struct socket *sock;
-
-       if (con->nodeid == 0) {
-               log_print("attempt to connect sock 0 foiled");
-               return;
-       }
-
-       mutex_lock(&con->sock_mutex);
-       if (con->retries++ > MAX_CONNECT_RETRIES)
-               goto out;
-
-       /* Some odd races can cause double-connects, ignore them */
-       if (con->sock) {
-               result = 0;
-               goto out;
-       }
-
-       /* Create a socket to communicate with */
-       result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM,
-                                 IPPROTO_TCP, &sock);
-       if (result < 0)
-               goto out_err;
-
-       memset(&saddr, 0, sizeof(saddr));
-       if (dlm_nodeid_to_addr(con->nodeid, &saddr))
-               goto out_err;
-
-       sock->sk->sk_user_data = con;
-       con->rx_action = receive_from_sock;
-
-       make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len);
-
-       add_sock(sock, con);
-
-       log_print("connecting to %d", con->nodeid);
-       result =
-               sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
-                                  O_NONBLOCK);
-       if (result == -EINPROGRESS)
-               result = 0;
-       if (result == 0)
-               goto out;
-
-out_err:
-       if (con->sock) {
-               sock_release(con->sock);
-               con->sock = NULL;
-       }
-       /*
-        * Some errors are fatal and this list might need adjusting. For other
-        * errors we try again until the max number of retries is reached.
-        */
-       if (result != -EHOSTUNREACH && result != -ENETUNREACH &&
-           result != -ENETDOWN && result != EINVAL
-           && result != -EPROTONOSUPPORT) {
-               lowcomms_connect_sock(con);
-               result = 0;
-       }
-out:
-       mutex_unlock(&con->sock_mutex);
-       return;
-}
-
-static struct socket *create_listen_sock(struct connection *con,
-                                        struct sockaddr_storage *saddr)
-{
-       struct socket *sock = NULL;
-       mm_segment_t fs;
-       int result = 0;
-       int one = 1;
-       int addr_len;
-
-       if (dlm_local_addr.ss_family == AF_INET)
-               addr_len = sizeof(struct sockaddr_in);
-       else
-               addr_len = sizeof(struct sockaddr_in6);
-
-       /* Create a socket to communicate with */
-       result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM, IPPROTO_TCP, &sock);
-       if (result < 0) {
-               printk("dlm: Can't create listening comms socket\n");
-               goto create_out;
-       }
-
-       fs = get_fs();
-       set_fs(get_ds());
-       result = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-                                (char *)&one, sizeof(one));
-       set_fs(fs);
-       if (result < 0) {
-               printk("dlm: Failed to set SO_REUSEADDR on socket: result=%d\n",
-                      result);
-       }
-       sock->sk->sk_user_data = con;
-       con->rx_action = accept_from_sock;
-       con->sock = sock;
-
-       /* Bind to our port */
-       make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
-       result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
-       if (result < 0) {
-               printk("dlm: Can't bind to port %d\n", dlm_config.ci_tcp_port);
-               sock_release(sock);
-               sock = NULL;
-               con->sock = NULL;
-               goto create_out;
-       }
-
-       fs = get_fs();
-       set_fs(get_ds());
-
-       result = sock_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
-                                (char *)&one, sizeof(one));
-       set_fs(fs);
-       if (result < 0) {
-               printk("dlm: Set keepalive failed: %d\n", result);
-       }
-
-       result = sock->ops->listen(sock, 5);
-       if (result < 0) {
-               printk("dlm: Can't listen on port %d\n", dlm_config.ci_tcp_port);
-               sock_release(sock);
-               sock = NULL;
-               goto create_out;
-       }
-
-create_out:
-       return sock;
-}
-
-
-/* Listen on all interfaces */
-static int listen_for_all(void)
-{
-       struct socket *sock = NULL;
-       struct connection *con = nodeid2con(0, GFP_KERNEL);
-       int result = -EINVAL;
-
-       /* We don't support multi-homed hosts */
-       set_bit(CF_IS_OTHERCON, &con->flags);
-
-       sock = create_listen_sock(con, &dlm_local_addr);
-       if (sock) {
-               add_sock(sock, con);
-               result = 0;
-       }
-       else {
-               result = -EADDRINUSE;
-       }
-
-       return result;
-}
-
-
-
-static struct writequeue_entry *new_writequeue_entry(struct connection *con,
-                                                    gfp_t allocation)
-{
-       struct writequeue_entry *entry;
-
-       entry = kmalloc(sizeof(struct writequeue_entry), allocation);
-       if (!entry)
-               return NULL;
-
-       entry->page = alloc_page(allocation);
-       if (!entry->page) {
-               kfree(entry);
-               return NULL;
-       }
-
-       entry->offset = 0;
-       entry->len = 0;
-       entry->end = 0;
-       entry->users = 0;
-       entry->con = con;
-
-       return entry;
-}
-
-void *dlm_lowcomms_get_buffer(int nodeid, int len,
-                             gfp_t allocation, char **ppc)
-{
-       struct connection *con;
-       struct writequeue_entry *e;
-       int offset = 0;
-       int users = 0;
-
-       con = nodeid2con(nodeid, allocation);
-       if (!con)
-               return NULL;
-
-       spin_lock(&con->writequeue_lock);
-       e = list_entry(con->writequeue.prev, struct writequeue_entry, list);
-       if ((&e->list == &con->writequeue) ||
-           (PAGE_CACHE_SIZE - e->end < len)) {
-               e = NULL;
-       } else {
-               offset = e->end;
-               e->end += len;
-               users = e->users++;
-       }
-       spin_unlock(&con->writequeue_lock);
-
-       if (e) {
-       got_one:
-               if (users == 0)
-                       kmap(e->page);
-               *ppc = page_address(e->page) + offset;
-               return e;
-       }
-
-       e = new_writequeue_entry(con, allocation);
-       if (e) {
-               spin_lock(&con->writequeue_lock);
-               offset = e->end;
-               e->end += len;
-               users = e->users++;
-               list_add_tail(&e->list, &con->writequeue);
-               spin_unlock(&con->writequeue_lock);
-               goto got_one;
-       }
-       return NULL;
-}
-
-void dlm_lowcomms_commit_buffer(void *mh)
-{
-       struct writequeue_entry *e = (struct writequeue_entry *)mh;
-       struct connection *con = e->con;
-       int users;
-
-       spin_lock(&con->writequeue_lock);
-       users = --e->users;
-       if (users)
-               goto out;
-       e->len = e->end - e->offset;
-       kunmap(e->page);
-       spin_unlock(&con->writequeue_lock);
-
-       if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
-               queue_work(send_workqueue, &con->swork);
-       }
-       return;
-
-out:
-       spin_unlock(&con->writequeue_lock);
-       return;
-}
-
-static void free_entry(struct writequeue_entry *e)
-{
-       __free_page(e->page);
-       kfree(e);
-}
-
-/* Send a message */
-static void send_to_sock(struct connection *con)
-{
-       int ret = 0;
-       ssize_t(*sendpage) (struct socket *, struct page *, int, size_t, int);
-       const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
-       struct writequeue_entry *e;
-       int len, offset;
-
-       mutex_lock(&con->sock_mutex);
-       if (con->sock == NULL)
-               goto out_connect;
-
-       sendpage = con->sock->ops->sendpage;
-
-       spin_lock(&con->writequeue_lock);
-       for (;;) {
-               e = list_entry(con->writequeue.next, struct writequeue_entry,
-                              list);
-               if ((struct list_head *) e == &con->writequeue)
-                       break;
-
-               len = e->len;
-               offset = e->offset;
-               BUG_ON(len == 0 && e->users == 0);
-               spin_unlock(&con->writequeue_lock);
-               kmap(e->page);
-
-               ret = 0;
-               if (len) {
-                       ret = sendpage(con->sock, e->page, offset, len,
-                                      msg_flags);
-                       if (ret == -EAGAIN || ret == 0)
-                               goto out;
-                       if (ret <= 0)
-                               goto send_error;
-               }
-               else {
-                       /* Don't starve people filling buffers */
-                       cond_resched();
-               }
-
-               spin_lock(&con->writequeue_lock);
-               e->offset += ret;
-               e->len -= ret;
-
-               if (e->len == 0 && e->users == 0) {
-                       list_del(&e->list);
-                       kunmap(e->page);
-                       free_entry(e);
-                       continue;
-               }
-       }
-       spin_unlock(&con->writequeue_lock);
-out:
-       mutex_unlock(&con->sock_mutex);
-       return;
-
-send_error:
-       mutex_unlock(&con->sock_mutex);
-       close_connection(con, false);
-       lowcomms_connect_sock(con);
-       return;
-
-out_connect:
-       mutex_unlock(&con->sock_mutex);
-       connect_to_sock(con);
-       return;
-}
-
-static void clean_one_writequeue(struct connection *con)
-{
-       struct list_head *list;
-       struct list_head *temp;
-
-       spin_lock(&con->writequeue_lock);
-       list_for_each_safe(list, temp, &con->writequeue) {
-               struct writequeue_entry *e =
-                       list_entry(list, struct writequeue_entry, list);
-               list_del(&e->list);
-               free_entry(e);
-       }
-       spin_unlock(&con->writequeue_lock);
-}
-
-/* Called from recovery when it knows that a node has
-   left the cluster */
-int dlm_lowcomms_close(int nodeid)
-{
-       struct connection *con;
-
-       if (!connections)
-               goto out;
-
-       log_print("closing connection to node %d", nodeid);
-       con = nodeid2con(nodeid, 0);
-       if (con) {
-               clean_one_writequeue(con);
-               close_connection(con, true);
-       }
-       return 0;
-
-out:
-       return -1;
-}
-
-/* Look for activity on active sockets */
-static void process_recv_sockets(struct work_struct *work)
-{
-       struct connection *con = container_of(work, struct connection, rwork);
-       int err;
-
-       clear_bit(CF_READ_PENDING, &con->flags);
-       do {
-               err = con->rx_action(con);
-       } while (!err);
-}
-
-
-static void process_send_sockets(struct work_struct *work)
-{
-       struct connection *con = container_of(work, struct connection, swork);
-
-       if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
-               connect_to_sock(con);
-       }
-
-       clear_bit(CF_WRITE_PENDING, &con->flags);
-       send_to_sock(con);
-}
-
-
-/* Discard all entries on the write queues */
-static void clean_writequeues(void)
-{
-       int nodeid;
-
-       for (nodeid = 1; nodeid < conn_array_size; nodeid++) {
-               struct connection *con = nodeid2con(nodeid, 0);
-
-               if (con)
-                       clean_one_writequeue(con);
-       }
-}
-
-static void work_stop(void)
-{
-       destroy_workqueue(recv_workqueue);
-       destroy_workqueue(send_workqueue);
-}
-
-static int work_start(void)
-{
-       int error;
-       recv_workqueue = create_workqueue("dlm_recv");
-       error = IS_ERR(recv_workqueue);
-       if (error) {
-               log_print("can't start dlm_recv %d", error);
-               return error;
-       }
-
-       send_workqueue = create_singlethread_workqueue("dlm_send");
-       error = IS_ERR(send_workqueue);
-       if (error) {
-               log_print("can't start dlm_send %d", error);
-               destroy_workqueue(recv_workqueue);
-               return error;
-       }
-
-       return 0;
-}
-
-void dlm_lowcomms_stop(void)
-{
-       int i;
-
-       /* Set all the flags to prevent any
-          socket activity.
-       */
-       for (i = 0; i < conn_array_size; i++) {
-               if (connections[i])
-                       connections[i]->flags |= 0xFF;
-       }
-
-       work_stop();
-       clean_writequeues();
-
-       for (i = 0; i < conn_array_size; i++) {
-               if (connections[i]) {
-                       close_connection(connections[i], true);
-                       if (connections[i]->othercon)
-                               kmem_cache_free(con_cache, connections[i]->othercon);
-                       kmem_cache_free(con_cache, connections[i]);
-               }
-       }
-
-       kfree(connections);
-       connections = NULL;
-
-       kmem_cache_destroy(con_cache);
-}
-
-/* This is quite likely to sleep... */
-int dlm_lowcomms_start(void)
-{
-       int error = 0;
-
-       error = -ENOMEM;
-       connections = kzalloc(sizeof(struct connection *) *
-                             NODE_INCREMENT, GFP_KERNEL);
-       if (!connections)
-               goto out;
-
-       conn_array_size = NODE_INCREMENT;
-
-       if (dlm_our_addr(&dlm_local_addr, 0)) {
-               log_print("no local IP address has been set");
-               goto fail_free_conn;
-       }
-       if (!dlm_our_addr(&dlm_local_addr, 1)) {
-               log_print("This dlm comms module does not support multi-homed clustering");
-               goto fail_free_conn;
-       }
-
-       con_cache = kmem_cache_create("dlm_conn", sizeof(struct connection),
-                                     __alignof__(struct connection), 0,
-                                     NULL, NULL);
-       if (!con_cache)
-               goto fail_free_conn;
-
-
-       /* Start listening */
-       error = listen_for_all();
-       if (error)
-               goto fail_unlisten;
-
-       error = work_start();
-       if (error)
-               goto fail_unlisten;
-
-       return 0;
-
-fail_unlisten:
-       close_connection(connections[0], false);
-       kmem_cache_free(con_cache, connections[0]);
-       kmem_cache_destroy(con_cache);
-
-fail_free_conn:
-       kfree(connections);
-
-out:
-       return error;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
new file mode 100644 (file)
index 0000000..27970a5
--- /dev/null
@@ -0,0 +1,1475 @@
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
+**
+**  This copyrighted material is made available to anyone wishing to use,
+**  modify, copy, or redistribute it subject to the terms and conditions
+**  of the GNU General Public License v.2.
+**
+*******************************************************************************
+******************************************************************************/
+
+/*
+ * lowcomms.c
+ *
+ * This is the "low-level" comms layer.
+ *
+ * It is responsible for sending/receiving messages
+ * from other nodes in the cluster.
+ *
+ * Cluster nodes are referred to by their nodeids. nodeids are
+ * simply 32 bit numbers to the locking module - if they need to
+ * be expanded for the cluster infrastructure then that is it's
+ * responsibility. It is this layer's
+ * responsibility to resolve these into IP address or
+ * whatever it needs for inter-node communication.
+ *
+ * The comms level is two kernel threads that deal mainly with
+ * the receiving of messages from other nodes and passing them
+ * up to the mid-level comms layer (which understands the
+ * message format) for execution by the locking core, and
+ * a send thread which does all the setting up of connections
+ * to remote nodes and the sending of data. Threads are not allowed
+ * to send their own data because it may cause them to wait in times
+ * of high load. Also, this way, the sending thread can collect together
+ * messages bound for one node and send them in one block.
+ *
+ * lowcomms will choose to use wither TCP or SCTP as its transport layer
+ * depending on the configuration variable 'protocol'. This should be set
+ * to 0 (default) for TCP or 1 for SCTP. It shouldbe configured using a
+ * cluster-wide mechanism as it must be the same on all nodes of the cluster
+ * for the DLM to function.
+ *
+ */
+
+#include <asm/ioctls.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+#include <linux/pagemap.h>
+#include <linux/idr.h>
+#include <linux/file.h>
+#include <linux/sctp.h>
+#include <net/sctp/user.h>
+
+#include "dlm_internal.h"
+#include "lowcomms.h"
+#include "midcomms.h"
+#include "config.h"
+
+#define NEEDED_RMEM (4*1024*1024)
+
+struct cbuf {
+       unsigned int base;
+       unsigned int len;
+       unsigned int mask;
+};
+
+static void cbuf_add(struct cbuf *cb, int n)
+{
+       cb->len += n;
+}
+
+static int cbuf_data(struct cbuf *cb)
+{
+       return ((cb->base + cb->len) & cb->mask);
+}
+
+static void cbuf_init(struct cbuf *cb, int size)
+{
+       cb->base = cb->len = 0;
+       cb->mask = size-1;
+}
+
+static void cbuf_eat(struct cbuf *cb, int n)
+{
+       cb->len  -= n;
+       cb->base += n;
+       cb->base &= cb->mask;
+}
+
+static bool cbuf_empty(struct cbuf *cb)
+{
+       return cb->len == 0;
+}
+
+struct connection {
+       struct socket *sock;    /* NULL if not connected */
+       uint32_t nodeid;        /* So we know who we are in the list */
+       struct mutex sock_mutex;
+       unsigned long flags;
+#define CF_READ_PENDING 1
+#define CF_WRITE_PENDING 2
+#define CF_CONNECT_PENDING 3
+#define CF_INIT_PENDING 4
+#define CF_IS_OTHERCON 5
+       struct list_head writequeue;  /* List of outgoing writequeue_entries */
+       spinlock_t writequeue_lock;
+       int (*rx_action) (struct connection *); /* What to do when active */
+       void (*connect_action) (struct connection *);   /* What to do to connect */
+       struct page *rx_page;
+       struct cbuf cb;
+       int retries;
+#define MAX_CONNECT_RETRIES 3
+       int sctp_assoc;
+       struct connection *othercon;
+       struct work_struct rwork; /* Receive workqueue */
+       struct work_struct swork; /* Send workqueue */
+};
+#define sock2con(x) ((struct connection *)(x)->sk_user_data)
+
+/* An entry waiting to be sent */
+struct writequeue_entry {
+       struct list_head list;
+       struct page *page;
+       int offset;
+       int len;
+       int end;
+       int users;
+       struct connection *con;
+};
+
+static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
+static int dlm_local_count;
+
+/* Work queues */
+static struct workqueue_struct *recv_workqueue;
+static struct workqueue_struct *send_workqueue;
+
+static DEFINE_IDR(connections_idr);
+static DECLARE_MUTEX(connections_lock);
+static int max_nodeid;
+static struct kmem_cache *con_cache;
+
+static void process_recv_sockets(struct work_struct *work);
+static void process_send_sockets(struct work_struct *work);
+
+/*
+ * If 'allocation' is zero then we don't attempt to create a new
+ * connection structure for this node.
+ */
+static struct connection *__nodeid2con(int nodeid, gfp_t alloc)
+{
+       struct connection *con = NULL;
+       int r;
+       int n;
+
+       con = idr_find(&connections_idr, nodeid);
+       if (con || !alloc)
+               return con;
+
+       r = idr_pre_get(&connections_idr, alloc);
+       if (!r)
+               return NULL;
+
+       con = kmem_cache_zalloc(con_cache, alloc);
+       if (!con)
+               return NULL;
+
+       r = idr_get_new_above(&connections_idr, con, nodeid, &n);
+       if (r) {
+               kmem_cache_free(con_cache, con);
+               return NULL;
+       }
+
+       if (n != nodeid) {
+               idr_remove(&connections_idr, n);
+               kmem_cache_free(con_cache, con);
+               return NULL;
+       }
+
+       con->nodeid = nodeid;
+       mutex_init(&con->sock_mutex);
+       INIT_LIST_HEAD(&con->writequeue);
+       spin_lock_init(&con->writequeue_lock);
+       INIT_WORK(&con->swork, process_send_sockets);
+       INIT_WORK(&con->rwork, process_recv_sockets);
+
+       /* Setup action pointers for child sockets */
+       if (con->nodeid) {
+               struct connection *zerocon = idr_find(&connections_idr, 0);
+
+               con->connect_action = zerocon->connect_action;
+               if (!con->rx_action)
+                       con->rx_action = zerocon->rx_action;
+       }
+
+       if (nodeid > max_nodeid)
+               max_nodeid = nodeid;
+
+       return con;
+}
+
+static struct connection *nodeid2con(int nodeid, gfp_t allocation)
+{
+       struct connection *con;
+
+       down(&connections_lock);
+       con = __nodeid2con(nodeid, allocation);
+       up(&connections_lock);
+
+       return con;
+}
+
+/* This is a bit drastic, but only called when things go wrong */
+static struct connection *assoc2con(int assoc_id)
+{
+       int i;
+       struct connection *con;
+
+       down(&connections_lock);
+       for (i=0; i<=max_nodeid; i++) {
+               con = __nodeid2con(i, 0);
+               if (con && con->sctp_assoc == assoc_id) {
+                       up(&connections_lock);
+                       return con;
+               }
+       }
+       up(&connections_lock);
+       return NULL;
+}
+
+static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
+{
+       struct sockaddr_storage addr;
+       int error;
+
+       if (!dlm_local_count)
+               return -1;
+
+       error = dlm_nodeid_to_addr(nodeid, &addr);
+       if (error)
+               return error;
+
+       if (dlm_local_addr[0]->ss_family == AF_INET) {
+               struct sockaddr_in *in4  = (struct sockaddr_in *) &addr;
+               struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr;
+               ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
+       } else {
+               struct sockaddr_in6 *in6  = (struct sockaddr_in6 *) &addr;
+               struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr;
+               memcpy(&ret6->sin6_addr, &in6->sin6_addr,
+                      sizeof(in6->sin6_addr));
+       }
+
+       return 0;
+}
+
+/* Data available on socket or listen socket received a connect */
+static void lowcomms_data_ready(struct sock *sk, int count_unused)
+{
+       struct connection *con = sock2con(sk);
+       if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+               queue_work(recv_workqueue, &con->rwork);
+}
+
+static void lowcomms_write_space(struct sock *sk)
+{
+       struct connection *con = sock2con(sk);
+
+       if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+               queue_work(send_workqueue, &con->swork);
+}
+
+static inline void lowcomms_connect_sock(struct connection *con)
+{
+       if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags))
+               queue_work(send_workqueue, &con->swork);
+}
+
+static void lowcomms_state_change(struct sock *sk)
+{
+       if (sk->sk_state == TCP_ESTABLISHED)
+               lowcomms_write_space(sk);
+}
+
+/* Make a socket active */
+static int add_sock(struct socket *sock, struct connection *con)
+{
+       con->sock = sock;
+
+       /* Install a data_ready callback */
+       con->sock->sk->sk_data_ready = lowcomms_data_ready;
+       con->sock->sk->sk_write_space = lowcomms_write_space;
+       con->sock->sk->sk_state_change = lowcomms_state_change;
+       con->sock->sk->sk_user_data = con;
+       return 0;
+}
+
+/* Add the port number to an IPv6 or 4 sockaddr and return the address
+   length */
+static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
+                         int *addr_len)
+{
+       saddr->ss_family =  dlm_local_addr[0]->ss_family;
+       if (saddr->ss_family == AF_INET) {
+               struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
+               in4_addr->sin_port = cpu_to_be16(port);
+               *addr_len = sizeof(struct sockaddr_in);
+               memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero));
+       } else {
+               struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr;
+               in6_addr->sin6_port = cpu_to_be16(port);
+               *addr_len = sizeof(struct sockaddr_in6);
+       }
+}
+
+/* Close a remote connection and tidy up */
+static void close_connection(struct connection *con, bool and_other)
+{
+       mutex_lock(&con->sock_mutex);
+
+       if (con->sock) {
+               sock_release(con->sock);
+               con->sock = NULL;
+       }
+       if (con->othercon && and_other) {
+               /* Will only re-enter once. */
+               close_connection(con->othercon, false);
+       }
+       if (con->rx_page) {
+               __free_page(con->rx_page);
+               con->rx_page = NULL;
+       }
+       con->retries = 0;
+       mutex_unlock(&con->sock_mutex);
+}
+
+/* We only send shutdown messages to nodes that are not part of the cluster */
+static void sctp_send_shutdown(sctp_assoc_t associd)
+{
+       static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
+       struct msghdr outmessage;
+       struct cmsghdr *cmsg;
+       struct sctp_sndrcvinfo *sinfo;
+       int ret;
+       struct connection *con;
+
+       con = nodeid2con(0,0);
+       BUG_ON(con == NULL);
+
+       outmessage.msg_name = NULL;
+       outmessage.msg_namelen = 0;
+       outmessage.msg_control = outcmsg;
+       outmessage.msg_controllen = sizeof(outcmsg);
+       outmessage.msg_flags = MSG_EOR;
+
+       cmsg = CMSG_FIRSTHDR(&outmessage);
+       cmsg->cmsg_level = IPPROTO_SCTP;
+       cmsg->cmsg_type = SCTP_SNDRCV;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+       outmessage.msg_controllen = cmsg->cmsg_len;
+       sinfo = CMSG_DATA(cmsg);
+       memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
+
+       sinfo->sinfo_flags |= MSG_EOF;
+       sinfo->sinfo_assoc_id = associd;
+
+       ret = kernel_sendmsg(con->sock, &outmessage, NULL, 0, 0);
+
+       if (ret != 0)
+               log_print("send EOF to node failed: %d", ret);
+}
+
+/* INIT failed but we don't know which node...
+   restart INIT on all pending nodes */
+static void sctp_init_failed(void)
+{
+       int i;
+       struct connection *con;
+
+       down(&connections_lock);
+       for (i=1; i<=max_nodeid; i++) {
+               con = __nodeid2con(i, 0);
+               if (!con)
+                       continue;
+               con->sctp_assoc = 0;
+               if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
+                       if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
+                               queue_work(send_workqueue, &con->swork);
+                       }
+               }
+       }
+       up(&connections_lock);
+}
+
+/* Something happened to an association */
+static void process_sctp_notification(struct connection *con,
+                                     struct msghdr *msg, char *buf)
+{
+       union sctp_notification *sn = (union sctp_notification *)buf;
+
+       if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
+               switch (sn->sn_assoc_change.sac_state) {
+
+               case SCTP_COMM_UP:
+               case SCTP_RESTART:
+               {
+                       /* Check that the new node is in the lockspace */
+                       struct sctp_prim prim;
+                       int nodeid;
+                       int prim_len, ret;
+                       int addr_len;
+                       struct connection *new_con;
+                       struct file *file;
+                       sctp_peeloff_arg_t parg;
+                       int parglen = sizeof(parg);
+
+                       /*
+                        * We get this before any data for an association.
+                        * We verify that the node is in the cluster and
+                        * then peel off a socket for it.
+                        */
+                       if ((int)sn->sn_assoc_change.sac_assoc_id <= 0) {
+                               log_print("COMM_UP for invalid assoc ID %d",
+                                        (int)sn->sn_assoc_change.sac_assoc_id);
+                               sctp_init_failed();
+                               return;
+                       }
+                       memset(&prim, 0, sizeof(struct sctp_prim));
+                       prim_len = sizeof(struct sctp_prim);
+                       prim.ssp_assoc_id = sn->sn_assoc_change.sac_assoc_id;
+
+                       ret = kernel_getsockopt(con->sock,
+                                               IPPROTO_SCTP,
+                                               SCTP_PRIMARY_ADDR,
+                                               (char*)&prim,
+                                               &prim_len);
+                       if (ret < 0) {
+                               log_print("getsockopt/sctp_primary_addr on "
+                                         "new assoc %d failed : %d",
+                                         (int)sn->sn_assoc_change.sac_assoc_id,
+                                         ret);
+
+                               /* Retry INIT later */
+                               new_con = assoc2con(sn->sn_assoc_change.sac_assoc_id);
+                               if (new_con)
+                                       clear_bit(CF_CONNECT_PENDING, &con->flags);
+                               return;
+                       }
+                       make_sockaddr(&prim.ssp_addr, 0, &addr_len);
+                       if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) {
+                               int i;
+                               unsigned char *b=(unsigned char *)&prim.ssp_addr;
+                               log_print("reject connect from unknown addr");
+                               for (i=0; i<sizeof(struct sockaddr_storage);i++)
+                                       printk("%02x ", b[i]);
+                               printk("\n");
+                               sctp_send_shutdown(prim.ssp_assoc_id);
+                               return;
+                       }
+
+                       new_con = nodeid2con(nodeid, GFP_KERNEL);
+                       if (!new_con)
+                               return;
+
+                       /* Peel off a new sock */
+                       parg.associd = sn->sn_assoc_change.sac_assoc_id;
+                       ret = kernel_getsockopt(con->sock, IPPROTO_SCTP,
+                                               SCTP_SOCKOPT_PEELOFF,
+                                               (void *)&parg, &parglen);
+                       if (ret) {
+                               log_print("Can't peel off a socket for "
+                                         "connection %d to node %d: err=%d\n",
+                                         parg.associd, nodeid, ret);
+                       }
+                       file = fget(parg.sd);
+                       new_con->sock = SOCKET_I(file->f_dentry->d_inode);
+                       add_sock(new_con->sock, new_con);
+                       fput(file);
+                       put_unused_fd(parg.sd);
+
+                       log_print("got new/restarted association %d nodeid %d",
+                                (int)sn->sn_assoc_change.sac_assoc_id, nodeid);
+
+                       /* Send any pending writes */
+                       clear_bit(CF_CONNECT_PENDING, &new_con->flags);
+                       clear_bit(CF_INIT_PENDING, &con->flags);
+                       if (!test_and_set_bit(CF_WRITE_PENDING, &new_con->flags)) {
+                               queue_work(send_workqueue, &new_con->swork);
+                       }
+                       if (!test_and_set_bit(CF_READ_PENDING, &new_con->flags))
+                               queue_work(recv_workqueue, &new_con->rwork);
+               }
+               break;
+
+               case SCTP_COMM_LOST:
+               case SCTP_SHUTDOWN_COMP:
+               {
+                       con = assoc2con(sn->sn_assoc_change.sac_assoc_id);
+                       if (con) {
+                               con->sctp_assoc = 0;
+                       }
+               }
+               break;
+
+               /* We don't know which INIT failed, so clear the PENDING flags
+                * on them all.  if assoc_id is zero then it will then try
+                * again */
+
+               case SCTP_CANT_STR_ASSOC:
+               {
+                       log_print("Can't start SCTP association - retrying");
+                       sctp_init_failed();
+               }
+               break;
+
+               default:
+                       log_print("unexpected SCTP assoc change id=%d state=%d",
+                                 (int)sn->sn_assoc_change.sac_assoc_id,
+                                 sn->sn_assoc_change.sac_state);
+               }
+       }
+}
+
+/* Data received from remote end */
+static int receive_from_sock(struct connection *con)
+{
+       int ret = 0;
+       struct msghdr msg = {};
+       struct kvec iov[2];
+       unsigned len;
+       int r;
+       int call_again_soon = 0;
+       int nvec;
+       char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
+
+       mutex_lock(&con->sock_mutex);
+
+       if (con->sock == NULL) {
+               ret = -EAGAIN;
+               goto out_close;
+       }
+
+       if (con->rx_page == NULL) {
+               /*
+                * This doesn't need to be atomic, but I think it should
+                * improve performance if it is.
+                */
+               con->rx_page = alloc_page(GFP_ATOMIC);
+               if (con->rx_page == NULL)
+                       goto out_resched;
+               cbuf_init(&con->cb, PAGE_CACHE_SIZE);
+       }
+
+       /* Only SCTP needs these really */
+       memset(&incmsg, 0, sizeof(incmsg));
+       msg.msg_control = incmsg;
+       msg.msg_controllen = sizeof(incmsg);
+
+       /*
+        * iov[0] is the bit of the circular buffer between the current end
+        * point (cb.base + cb.len) and the end of the buffer.
+        */
+       iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
+       iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
+       iov[1].iov_len = 0;
+       nvec = 1;
+
+       /*
+        * iov[1] is the bit of the circular buffer between the start of the
+        * buffer and the start of the currently used section (cb.base)
+        */
+       if (cbuf_data(&con->cb) >= con->cb.base) {
+               iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
+               iov[1].iov_len = con->cb.base;
+               iov[1].iov_base = page_address(con->rx_page);
+               nvec = 2;
+       }
+       len = iov[0].iov_len + iov[1].iov_len;
+
+       r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len,
+                              MSG_DONTWAIT | MSG_NOSIGNAL);
+       if (ret <= 0)
+               goto out_close;
+
+       /* Process SCTP notifications */
+       if (msg.msg_flags & MSG_NOTIFICATION) {
+               msg.msg_control = incmsg;
+               msg.msg_controllen = sizeof(incmsg);
+
+               process_sctp_notification(con, &msg,
+                               page_address(con->rx_page) + con->cb.base);
+               mutex_unlock(&con->sock_mutex);
+               return 0;
+       }
+       BUG_ON(con->nodeid == 0);
+
+       if (ret == len)
+               call_again_soon = 1;
+       cbuf_add(&con->cb, ret);
+       ret = dlm_process_incoming_buffer(con->nodeid,
+                                         page_address(con->rx_page),
+                                         con->cb.base, con->cb.len,
+                                         PAGE_CACHE_SIZE);
+       if (ret == -EBADMSG) {
+               log_print("lowcomms: addr=%p, base=%u, len=%u, "
+                         "iov_len=%u, iov_base[0]=%p, read=%d",
+                         page_address(con->rx_page), con->cb.base, con->cb.len,
+                         len, iov[0].iov_base, r);
+       }
+       if (ret < 0)
+               goto out_close;
+       cbuf_eat(&con->cb, ret);
+
+       if (cbuf_empty(&con->cb) && !call_again_soon) {
+               __free_page(con->rx_page);
+               con->rx_page = NULL;
+       }
+
+       if (call_again_soon)
+               goto out_resched;
+       mutex_unlock(&con->sock_mutex);
+       return 0;
+
+out_resched:
+       if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+               queue_work(recv_workqueue, &con->rwork);
+       mutex_unlock(&con->sock_mutex);
+       return -EAGAIN;
+
+out_close:
+       mutex_unlock(&con->sock_mutex);
+       if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
+               close_connection(con, false);
+               /* Reconnect when there is something to send */
+       }
+       /* Don't return success if we really got EOF */
+       if (ret == 0)
+               ret = -EAGAIN;
+
+       return ret;
+}
+
+/* Listening socket is busy, accept a connection */
+static int tcp_accept_from_sock(struct connection *con)
+{
+       int result;
+       struct sockaddr_storage peeraddr;
+       struct socket *newsock;
+       int len;
+       int nodeid;
+       struct connection *newcon;
+       struct connection *addcon;
+
+       memset(&peeraddr, 0, sizeof(peeraddr));
+       result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
+                                 IPPROTO_TCP, &newsock);
+       if (result < 0)
+               return -ENOMEM;
+
+       mutex_lock_nested(&con->sock_mutex, 0);
+
+       result = -ENOTCONN;
+       if (con->sock == NULL)
+               goto accept_err;
+
+       newsock->type = con->sock->type;
+       newsock->ops = con->sock->ops;
+
+       result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK);
+       if (result < 0)
+               goto accept_err;
+
+       /* Get the connected socket's peer */
+       memset(&peeraddr, 0, sizeof(peeraddr));
+       if (newsock->ops->getname(newsock, (struct sockaddr *)&peeraddr,
+                                 &len, 2)) {
+               result = -ECONNABORTED;
+               goto accept_err;
+       }
+
+       /* Get the new node's NODEID */
+       make_sockaddr(&peeraddr, 0, &len);
+       if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
+               log_print("connect from non cluster node");
+               sock_release(newsock);
+               mutex_unlock(&con->sock_mutex);
+               return -1;
+       }
+
+       log_print("got connection from %d", nodeid);
+
+       /*  Check to see if we already have a connection to this node. This
+        *  could happen if the two nodes initiate a connection at roughly
+        *  the same time and the connections cross on the wire.
+        *  In this case we store the incoming one in "othercon"
+        */
+       newcon = nodeid2con(nodeid, GFP_KERNEL);
+       if (!newcon) {
+               result = -ENOMEM;
+               goto accept_err;
+       }
+       mutex_lock_nested(&newcon->sock_mutex, 1);
+       if (newcon->sock) {
+               struct connection *othercon = newcon->othercon;
+
+               if (!othercon) {
+                       othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
+                       if (!othercon) {
+                               log_print("failed to allocate incoming socket");
+                               mutex_unlock(&newcon->sock_mutex);
+                               result = -ENOMEM;
+                               goto accept_err;
+                       }
+                       othercon->nodeid = nodeid;
+                       othercon->rx_action = receive_from_sock;
+                       mutex_init(&othercon->sock_mutex);
+                       INIT_WORK(&othercon->swork, process_send_sockets);
+                       INIT_WORK(&othercon->rwork, process_recv_sockets);
+                       set_bit(CF_IS_OTHERCON, &othercon->flags);
+                       newcon->othercon = othercon;
+               }
+               othercon->sock = newsock;
+               newsock->sk->sk_user_data = othercon;
+               add_sock(newsock, othercon);
+               addcon = othercon;
+       }
+       else {
+               newsock->sk->sk_user_data = newcon;
+               newcon->rx_action = receive_from_sock;
+               add_sock(newsock, newcon);
+               addcon = newcon;
+       }
+
+       mutex_unlock(&newcon->sock_mutex);
+
+       /*
+        * Add it to the active queue in case we got data
+        * beween processing the accept adding the socket
+        * to the read_sockets list
+        */
+       if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
+               queue_work(recv_workqueue, &addcon->rwork);
+       mutex_unlock(&con->sock_mutex);
+
+       return 0;
+
+accept_err:
+       mutex_unlock(&con->sock_mutex);
+       sock_release(newsock);
+
+       if (result != -EAGAIN)
+               log_print("error accepting connection from node: %d", result);
+       return result;
+}
+
+static void free_entry(struct writequeue_entry *e)
+{
+       __free_page(e->page);
+       kfree(e);
+}
+
+/* Initiate an SCTP association.
+   This is a special case of send_to_sock() in that we don't yet have a
+   peeled-off socket for this association, so we use the listening socket
+   and add the primary IP address of the remote node.
+ */
+static void sctp_init_assoc(struct connection *con)
+{
+       struct sockaddr_storage rem_addr;
+       char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
+       struct msghdr outmessage;
+       struct cmsghdr *cmsg;
+       struct sctp_sndrcvinfo *sinfo;
+       struct connection *base_con;
+       struct writequeue_entry *e;
+       int len, offset;
+       int ret;
+       int addrlen;
+       struct kvec iov[1];
+
+       if (test_and_set_bit(CF_INIT_PENDING, &con->flags))
+               return;
+
+       if (con->retries++ > MAX_CONNECT_RETRIES)
+               return;
+
+       log_print("Initiating association with node %d", con->nodeid);
+
+       if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) {
+               log_print("no address for nodeid %d", con->nodeid);
+               return;
+       }
+       base_con = nodeid2con(0, 0);
+       BUG_ON(base_con == NULL);
+
+       make_sockaddr(&rem_addr, dlm_config.ci_tcp_port, &addrlen);
+
+       outmessage.msg_name = &rem_addr;
+       outmessage.msg_namelen = addrlen;
+       outmessage.msg_control = outcmsg;
+       outmessage.msg_controllen = sizeof(outcmsg);
+       outmessage.msg_flags = MSG_EOR;
+
+       spin_lock(&con->writequeue_lock);
+       e = list_entry(con->writequeue.next, struct writequeue_entry,
+                      list);
+
+       BUG_ON((struct list_head *) e == &con->writequeue);
+
+       len = e->len;
+       offset = e->offset;
+       spin_unlock(&con->writequeue_lock);
+       kmap(e->page);
+
+       /* Send the first block off the write queue */
+       iov[0].iov_base = page_address(e->page)+offset;
+       iov[0].iov_len = len;
+
+       cmsg = CMSG_FIRSTHDR(&outmessage);
+       cmsg->cmsg_level = IPPROTO_SCTP;
+       cmsg->cmsg_type = SCTP_SNDRCV;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+       sinfo = CMSG_DATA(cmsg);
+       memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
+       sinfo->sinfo_ppid = cpu_to_le32(dlm_our_nodeid());
+       outmessage.msg_controllen = cmsg->cmsg_len;
+
+       ret = kernel_sendmsg(base_con->sock, &outmessage, iov, 1, len);
+       if (ret < 0) {
+               log_print("Send first packet to node %d failed: %d",
+                         con->nodeid, ret);
+
+               /* Try again later */
+               clear_bit(CF_CONNECT_PENDING, &con->flags);
+               clear_bit(CF_INIT_PENDING, &con->flags);
+       }
+       else {
+               spin_lock(&con->writequeue_lock);
+               e->offset += ret;
+               e->len -= ret;
+
+               if (e->len == 0 && e->users == 0) {
+                       list_del(&e->list);
+                       kunmap(e->page);
+                       free_entry(e);
+               }
+               spin_unlock(&con->writequeue_lock);
+       }
+}
+
+/* Connect a new socket to its peer */
+static void tcp_connect_to_sock(struct connection *con)
+{
+       int result = -EHOSTUNREACH;
+       struct sockaddr_storage saddr;
+       int addr_len;
+       struct socket *sock;
+
+       if (con->nodeid == 0) {
+               log_print("attempt to connect sock 0 foiled");
+               return;
+       }
+
+       mutex_lock(&con->sock_mutex);
+       if (con->retries++ > MAX_CONNECT_RETRIES)
+               goto out;
+
+       /* Some odd races can cause double-connects, ignore them */
+       if (con->sock) {
+               result = 0;
+               goto out;
+       }
+
+       /* Create a socket to communicate with */
+       result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
+                                 IPPROTO_TCP, &sock);
+       if (result < 0)
+               goto out_err;
+
+       memset(&saddr, 0, sizeof(saddr));
+       if (dlm_nodeid_to_addr(con->nodeid, &saddr))
+               goto out_err;
+
+       sock->sk->sk_user_data = con;
+       con->rx_action = receive_from_sock;
+       con->connect_action = tcp_connect_to_sock;
+       add_sock(sock, con);
+
+       make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len);
+
+       log_print("connecting to %d", con->nodeid);
+       result =
+               sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
+                                  O_NONBLOCK);
+       if (result == -EINPROGRESS)
+               result = 0;
+       if (result == 0)
+               goto out;
+
+out_err:
+       if (con->sock) {
+               sock_release(con->sock);
+               con->sock = NULL;
+       }
+       /*
+        * Some errors are fatal and this list might need adjusting. For other
+        * errors we try again until the max number of retries is reached.
+        */
+       if (result != -EHOSTUNREACH && result != -ENETUNREACH &&
+           result != -ENETDOWN && result != EINVAL
+           && result != -EPROTONOSUPPORT) {
+               lowcomms_connect_sock(con);
+               result = 0;
+       }
+out:
+       mutex_unlock(&con->sock_mutex);
+       return;
+}
+
+static struct socket *tcp_create_listen_sock(struct connection *con,
+                                            struct sockaddr_storage *saddr)
+{
+       struct socket *sock = NULL;
+       int result = 0;
+       int one = 1;
+       int addr_len;
+
+       if (dlm_local_addr[0]->ss_family == AF_INET)
+               addr_len = sizeof(struct sockaddr_in);
+       else
+               addr_len = sizeof(struct sockaddr_in6);
+
+       /* Create a socket to communicate with */
+       result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
+                                 IPPROTO_TCP, &sock);
+       if (result < 0) {
+               log_print("Can't create listening comms socket");
+               goto create_out;
+       }
+
+       result = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+                                  (char *)&one, sizeof(one));
+
+       if (result < 0) {
+               log_print("Failed to set SO_REUSEADDR on socket: %d", result);
+       }
+       sock->sk->sk_user_data = con;
+       con->rx_action = tcp_accept_from_sock;
+       con->connect_action = tcp_connect_to_sock;
+       con->sock = sock;
+
+       /* Bind to our port */
+       make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
+       result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
+       if (result < 0) {
+               log_print("Can't bind to port %d", dlm_config.ci_tcp_port);
+               sock_release(sock);
+               sock = NULL;
+               con->sock = NULL;
+               goto create_out;
+       }
+       result = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+                                (char *)&one, sizeof(one));
+       if (result < 0) {
+               log_print("Set keepalive failed: %d", result);
+       }
+
+       result = sock->ops->listen(sock, 5);
+       if (result < 0) {
+               log_print("Can't listen on port %d", dlm_config.ci_tcp_port);
+               sock_release(sock);
+               sock = NULL;
+               goto create_out;
+       }
+
+create_out:
+       return sock;
+}
+
+/* Get local addresses */
+static void init_local(void)
+{
+       struct sockaddr_storage sas, *addr;
+       int i;
+
+       dlm_local_count = 0;
+       for (i = 0; i < DLM_MAX_ADDR_COUNT - 1; i++) {
+               if (dlm_our_addr(&sas, i))
+                       break;
+
+               addr = kmalloc(sizeof(*addr), GFP_KERNEL);
+               if (!addr)
+                       break;
+               memcpy(addr, &sas, sizeof(*addr));
+               dlm_local_addr[dlm_local_count++] = addr;
+       }
+}
+
+/* Bind to an IP address. SCTP allows multiple address so it can do
+   multi-homing */
+static int add_sctp_bind_addr(struct connection *sctp_con,
+                             struct sockaddr_storage *addr,
+                             int addr_len, int num)
+{
+       int result = 0;
+
+       if (num == 1)
+               result = kernel_bind(sctp_con->sock,
+                                    (struct sockaddr *) addr,
+                                    addr_len);
+       else
+               result = kernel_setsockopt(sctp_con->sock, SOL_SCTP,
+                                          SCTP_SOCKOPT_BINDX_ADD,
+                                          (char *)addr, addr_len);
+
+       if (result < 0)
+               log_print("Can't bind to port %d addr number %d",
+                         dlm_config.ci_tcp_port, num);
+
+       return result;
+}
+
+/* Initialise SCTP socket and bind to all interfaces */
+static int sctp_listen_for_all(void)
+{
+       struct socket *sock = NULL;
+       struct sockaddr_storage localaddr;
+       struct sctp_event_subscribe subscribe;
+       int result = -EINVAL, num = 1, i, addr_len;
+       struct connection *con = nodeid2con(0, GFP_KERNEL);
+       int bufsize = NEEDED_RMEM;
+
+       if (!con)
+               return -ENOMEM;
+
+       log_print("Using SCTP for communications");
+
+       result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_SEQPACKET,
+                                 IPPROTO_SCTP, &sock);
+       if (result < 0) {
+               log_print("Can't create comms socket, check SCTP is loaded");
+               goto out;
+       }
+
+       /* Listen for events */
+       memset(&subscribe, 0, sizeof(subscribe));
+       subscribe.sctp_data_io_event = 1;
+       subscribe.sctp_association_event = 1;
+       subscribe.sctp_send_failure_event = 1;
+       subscribe.sctp_shutdown_event = 1;
+       subscribe.sctp_partial_delivery_event = 1;
+
+       result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+                                (char *)&bufsize, sizeof(bufsize));
+       if (result)
+               log_print("Error increasing buffer space on socket %d", result);
+
+       result = kernel_setsockopt(sock, SOL_SCTP, SCTP_EVENTS,
+                                  (char *)&subscribe, sizeof(subscribe));
+       if (result < 0) {
+               log_print("Failed to set SCTP_EVENTS on socket: result=%d",
+                         result);
+               goto create_delsock;
+       }
+
+       /* Init con struct */
+       sock->sk->sk_user_data = con;
+       con->sock = sock;
+       con->sock->sk->sk_data_ready = lowcomms_data_ready;
+       con->rx_action = receive_from_sock;
+       con->connect_action = sctp_init_assoc;
+
+       /* Bind to all interfaces. */
+       for (i = 0; i < dlm_local_count; i++) {
+               memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr));
+               make_sockaddr(&localaddr, dlm_config.ci_tcp_port, &addr_len);
+
+               result = add_sctp_bind_addr(con, &localaddr, addr_len, num);
+               if (result)
+                       goto create_delsock;
+               ++num;
+       }
+
+       result = sock->ops->listen(sock, 5);
+       if (result < 0) {
+               log_print("Can't set socket listening");
+               goto create_delsock;
+       }
+
+       return 0;
+
+create_delsock:
+       sock_release(sock);
+       con->sock = NULL;
+out:
+       return result;
+}
+
+static int tcp_listen_for_all(void)
+{
+       struct socket *sock = NULL;
+       struct connection *con = nodeid2con(0, GFP_KERNEL);
+       int result = -EINVAL;
+
+       if (!con)
+               return -ENOMEM;
+
+       /* We don't support multi-homed hosts */
+       if (dlm_local_addr[1] != NULL) {
+               log_print("TCP protocol can't handle multi-homed hosts, "
+                         "try SCTP");
+               return -EINVAL;
+       }
+
+       log_print("Using TCP for communications");
+
+       set_bit(CF_IS_OTHERCON, &con->flags);
+
+       sock = tcp_create_listen_sock(con, dlm_local_addr[0]);
+       if (sock) {
+               add_sock(sock, con);
+               result = 0;
+       }
+       else {
+               result = -EADDRINUSE;
+       }
+
+       return result;
+}
+
+
+
+static struct writequeue_entry *new_writequeue_entry(struct connection *con,
+                                                    gfp_t allocation)
+{
+       struct writequeue_entry *entry;
+
+       entry = kmalloc(sizeof(struct writequeue_entry), allocation);
+       if (!entry)
+               return NULL;
+
+       entry->page = alloc_page(allocation);
+       if (!entry->page) {
+               kfree(entry);
+               return NULL;
+       }
+
+       entry->offset = 0;
+       entry->len = 0;
+       entry->end = 0;
+       entry->users = 0;
+       entry->con = con;
+
+       return entry;
+}
+
+void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
+{
+       struct connection *con;
+       struct writequeue_entry *e;
+       int offset = 0;
+       int users = 0;
+
+       con = nodeid2con(nodeid, allocation);
+       if (!con)
+               return NULL;
+
+       spin_lock(&con->writequeue_lock);
+       e = list_entry(con->writequeue.prev, struct writequeue_entry, list);
+       if ((&e->list == &con->writequeue) ||
+           (PAGE_CACHE_SIZE - e->end < len)) {
+               e = NULL;
+       } else {
+               offset = e->end;
+               e->end += len;
+               users = e->users++;
+       }
+       spin_unlock(&con->writequeue_lock);
+
+       if (e) {
+       got_one:
+               if (users == 0)
+                       kmap(e->page);
+               *ppc = page_address(e->page) + offset;
+               return e;
+       }
+
+       e = new_writequeue_entry(con, allocation);
+       if (e) {
+               spin_lock(&con->writequeue_lock);
+               offset = e->end;
+               e->end += len;
+               users = e->users++;
+               list_add_tail(&e->list, &con->writequeue);
+               spin_unlock(&con->writequeue_lock);
+               goto got_one;
+       }
+       return NULL;
+}
+
+void dlm_lowcomms_commit_buffer(void *mh)
+{
+       struct writequeue_entry *e = (struct writequeue_entry *)mh;
+       struct connection *con = e->con;
+       int users;
+
+       spin_lock(&con->writequeue_lock);
+       users = --e->users;
+       if (users)
+               goto out;
+       e->len = e->end - e->offset;
+       kunmap(e->page);
+       spin_unlock(&con->writequeue_lock);
+
+       if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
+               queue_work(send_workqueue, &con->swork);
+       }
+       return;
+
+out:
+       spin_unlock(&con->writequeue_lock);
+       return;
+}
+
+/* Send a message */
+static void send_to_sock(struct connection *con)
+{
+       int ret = 0;
+       ssize_t(*sendpage) (struct socket *, struct page *, int, size_t, int);
+       const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+       struct writequeue_entry *e;
+       int len, offset;
+
+       mutex_lock(&con->sock_mutex);
+       if (con->sock == NULL)
+               goto out_connect;
+
+       sendpage = con->sock->ops->sendpage;
+
+       spin_lock(&con->writequeue_lock);
+       for (;;) {
+               e = list_entry(con->writequeue.next, struct writequeue_entry,
+                              list);
+               if ((struct list_head *) e == &con->writequeue)
+                       break;
+
+               len = e->len;
+               offset = e->offset;
+               BUG_ON(len == 0 && e->users == 0);
+               spin_unlock(&con->writequeue_lock);
+               kmap(e->page);
+
+               ret = 0;
+               if (len) {
+                       ret = sendpage(con->sock, e->page, offset, len,
+                                      msg_flags);
+                       if (ret == -EAGAIN || ret == 0)
+                               goto out;
+                       if (ret <= 0)
+                               goto send_error;
+               } else {
+                       /* Don't starve people filling buffers */
+                       cond_resched();
+               }
+
+               spin_lock(&con->writequeue_lock);
+               e->offset += ret;
+               e->len -= ret;
+
+               if (e->len == 0 && e->users == 0) {
+                       list_del(&e->list);
+                       kunmap(e->page);
+                       free_entry(e);
+                       continue;
+               }
+       }
+       spin_unlock(&con->writequeue_lock);
+out:
+       mutex_unlock(&con->sock_mutex);
+       return;
+
+send_error:
+       mutex_unlock(&con->sock_mutex);
+       close_connection(con, false);
+       lowcomms_connect_sock(con);
+       return;
+
+out_connect:
+       mutex_unlock(&con->sock_mutex);
+       if (!test_bit(CF_INIT_PENDING, &con->flags))
+               lowcomms_connect_sock(con);
+       return;
+}
+
+static void clean_one_writequeue(struct connection *con)
+{
+       struct list_head *list;
+       struct list_head *temp;
+
+       spin_lock(&con->writequeue_lock);
+       list_for_each_safe(list, temp, &con->writequeue) {
+               struct writequeue_entry *e =
+                       list_entry(list, struct writequeue_entry, list);
+               list_del(&e->list);
+               free_entry(e);
+       }
+       spin_unlock(&con->writequeue_lock);
+}
+
+/* Called from recovery when it knows that a node has
+   left the cluster */
+int dlm_lowcomms_close(int nodeid)
+{
+       struct connection *con;
+
+       log_print("closing connection to node %d", nodeid);
+       con = nodeid2con(nodeid, 0);
+       if (con) {
+               clean_one_writequeue(con);
+               close_connection(con, true);
+       }
+       return 0;
+}
+
+/* Receive workqueue function */
+static void process_recv_sockets(struct work_struct *work)
+{
+       struct connection *con = container_of(work, struct connection, rwork);
+       int err;
+
+       clear_bit(CF_READ_PENDING, &con->flags);
+       do {
+               err = con->rx_action(con);
+       } while (!err);
+}
+
+/* Send workqueue function */
+static void process_send_sockets(struct work_struct *work)
+{
+       struct connection *con = container_of(work, struct connection, swork);
+
+       if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
+               con->connect_action(con);
+       }
+       clear_bit(CF_WRITE_PENDING, &con->flags);
+       send_to_sock(con);
+}
+
+
+/* Discard all entries on the write queues */
+static void clean_writequeues(void)
+{
+       int nodeid;
+
+       for (nodeid = 1; nodeid <= max_nodeid; nodeid++) {
+               struct connection *con = __nodeid2con(nodeid, 0);
+
+               if (con)
+                       clean_one_writequeue(con);
+       }
+}
+
+static void work_stop(void)
+{
+       destroy_workqueue(recv_workqueue);
+       destroy_workqueue(send_workqueue);
+}
+
+static int work_start(void)
+{
+       int error;
+       recv_workqueue = create_workqueue("dlm_recv");
+       error = IS_ERR(recv_workqueue);
+       if (error) {
+               log_print("can't start dlm_recv %d", error);
+               return error;
+       }
+
+       send_workqueue = create_singlethread_workqueue("dlm_send");
+       error = IS_ERR(send_workqueue);
+       if (error) {
+               log_print("can't start dlm_send %d", error);
+               destroy_workqueue(recv_workqueue);
+               return error;
+       }
+
+       return 0;
+}
+
+void dlm_lowcomms_stop(void)
+{
+       int i;
+       struct connection *con;
+
+       /* Set all the flags to prevent any
+          socket activity.
+       */
+       down(&connections_lock);
+       for (i = 0; i <= max_nodeid; i++) {
+               con = __nodeid2con(i, 0);
+               if (con)
+                       con->flags |= 0xFF;
+       }
+       up(&connections_lock);
+
+       work_stop();
+
+       down(&connections_lock);
+       clean_writequeues();
+
+       for (i = 0; i <= max_nodeid; i++) {
+               con = __nodeid2con(i, 0);
+               if (con) {
+                       close_connection(con, true);
+                       if (con->othercon)
+                               kmem_cache_free(con_cache, con->othercon);
+                       kmem_cache_free(con_cache, con);
+               }
+       }
+       max_nodeid = 0;
+       up(&connections_lock);
+       kmem_cache_destroy(con_cache);
+       idr_init(&connections_idr);
+}
+
+int dlm_lowcomms_start(void)
+{
+       int error = -EINVAL;
+       struct connection *con;
+
+       init_local();
+       if (!dlm_local_count) {
+               error = -ENOTCONN;
+               log_print("no local IP address has been set");
+               goto out;
+       }
+
+       error = -ENOMEM;
+       con_cache = kmem_cache_create("dlm_conn", sizeof(struct connection),
+                                     __alignof__(struct connection), 0,
+                                     NULL, NULL);
+       if (!con_cache)
+               goto out;
+
+       /* Set some sysctl minima */
+       if (sysctl_rmem_max < NEEDED_RMEM)
+               sysctl_rmem_max = NEEDED_RMEM;
+
+       /* Start listening */
+       if (dlm_config.ci_protocol == 0)
+               error = tcp_listen_for_all();
+       else
+               error = sctp_listen_for_all();
+       if (error)
+               goto fail_unlisten;
+
+       error = work_start();
+       if (error)
+               goto fail_unlisten;
+
+       return 0;
+
+fail_unlisten:
+       con = nodeid2con(0,0);
+       if (con) {
+               close_connection(con, false);
+               kmem_cache_free(con_cache, con);
+       }
+       kmem_cache_destroy(con_cache);
+
+out:
+       return error;
+}
index 3870150..b0201ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2006-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -56,6 +56,7 @@ struct dlm_write_request32 {
        union  {
                struct dlm_lock_params32 lock;
                struct dlm_lspace_params lspace;
+               struct dlm_purge_params purge;
        } i;
 };
 
@@ -92,6 +93,9 @@ static void compat_input(struct dlm_write_request *kb,
                kb->i.lspace.flags = kb32->i.lspace.flags;
                kb->i.lspace.minor = kb32->i.lspace.minor;
                strcpy(kb->i.lspace.name, kb32->i.lspace.name);
+       } else if (kb->cmd == DLM_USER_PURGE) {
+               kb->i.purge.nodeid = kb32->i.purge.nodeid;
+               kb->i.purge.pid = kb32->i.purge.pid;
        } else {
                kb->i.lock.mode = kb32->i.lock.mode;
                kb->i.lock.namelen = kb32->i.lock.namelen;
@@ -111,8 +115,6 @@ static void compat_input(struct dlm_write_request *kb,
 static void compat_output(struct dlm_lock_result *res,
                          struct dlm_lock_result32 *res32)
 {
-       res32->length = res->length - (sizeof(struct dlm_lock_result) -
-                                      sizeof(struct dlm_lock_result32));
        res32->user_astaddr = (__u32)(long)res->user_astaddr;
        res32->user_astparam = (__u32)(long)res->user_astparam;
        res32->user_lksb = (__u32)(long)res->user_lksb;
@@ -128,35 +130,30 @@ static void compat_output(struct dlm_lock_result *res,
 }
 #endif
 
+/* we could possibly check if the cancel of an orphan has resulted in the lkb
+   being removed and then remove that lkb from the orphans list and free it */
 
 void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
 {
        struct dlm_ls *ls;
        struct dlm_user_args *ua;
        struct dlm_user_proc *proc;
-       int remove_ownqueue = 0;
+       int eol = 0, ast_type;
 
-       /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each
-          lkb before dealing with it.  We need to check this
-          flag before taking ls_clear_proc_locks mutex because if
-          it's set, dlm_clear_proc_locks() holds the mutex. */
-
-       if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) {
-               /* log_print("user_add_ast skip1 %x", lkb->lkb_flags); */
+       if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
                return;
-       }
 
        ls = lkb->lkb_resource->res_ls;
        mutex_lock(&ls->ls_clear_proc_locks);
 
        /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast
           can't be delivered.  For ORPHAN's, dlm_clear_proc_locks() freed
-          lkb->ua so we can't try to use it. */
+          lkb->ua so we can't try to use it.  This second check is necessary
+          for cases where a completion ast is received for an operation that
+          began before clear_proc_locks did its cancel/unlock. */
 
-       if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) {
-               /* log_print("user_add_ast skip2 %x", lkb->lkb_flags); */
+       if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
                goto out;
-       }
 
        DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb););
        ua = (struct dlm_user_args *)lkb->lkb_astparam;
@@ -166,28 +163,42 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
                goto out;
 
        spin_lock(&proc->asts_spin);
-       if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
+
+       ast_type = lkb->lkb_ast_type;
+       lkb->lkb_ast_type |= type;
+
+       if (!ast_type) {
                kref_get(&lkb->lkb_ref);
                list_add_tail(&lkb->lkb_astqueue, &proc->asts);
-               lkb->lkb_ast_type |= type;
                wake_up_interruptible(&proc->wait);
        }
-
-       /* noqueue requests that fail may need to be removed from the
-          proc's locks list, there should be a better way of detecting
-          this situation than checking all these things... */
-
-       if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV &&
-           ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue))
-               remove_ownqueue = 1;
-
-       /* unlocks or cancels of waiting requests need to be removed from the
-          proc's unlocking list, again there must be a better way...  */
-
-       if (ua->lksb.sb_status == -DLM_EUNLOCK ||
+       if (type == AST_COMP && (ast_type & AST_COMP))
+               log_debug(ls, "ast overlap %x status %x %x",
+                         lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
+
+       /* Figure out if this lock is at the end of its life and no longer
+          available for the application to use.  The lkb still exists until
+          the final ast is read.  A lock becomes EOL in three situations:
+            1. a noqueue request fails with EAGAIN
+            2. an unlock completes with EUNLOCK
+            3. a cancel of a waiting request completes with ECANCEL
+          An EOL lock needs to be removed from the process's list of locks.
+          And we can't allow any new operation on an EOL lock.  This is
+          not related to the lifetime of the lkb struct which is managed
+          entirely by refcount. */
+
+       if (type == AST_COMP &&
+           lkb->lkb_grmode == DLM_LOCK_IV &&
+           ua->lksb.sb_status == -EAGAIN)
+               eol = 1;
+       else if (ua->lksb.sb_status == -DLM_EUNLOCK ||
            (ua->lksb.sb_status == -DLM_ECANCEL &&
             lkb->lkb_grmode == DLM_LOCK_IV))
-               remove_ownqueue = 1;
+               eol = 1;
+       if (eol) {
+               lkb->lkb_ast_type &= ~AST_BAST;
+               lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
+       }
 
        /* We want to copy the lvb to userspace when the completion
           ast is read if the status is 0, the lock has an lvb and
@@ -204,11 +215,13 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
 
        spin_unlock(&proc->asts_spin);
 
-       if (remove_ownqueue) {
+       if (eol) {
                spin_lock(&ua->proc->locks_spin);
-               list_del_init(&lkb->lkb_ownqueue);
+               if (!list_empty(&lkb->lkb_ownqueue)) {
+                       list_del_init(&lkb->lkb_ownqueue);
+                       dlm_put_lkb(lkb);
+               }
                spin_unlock(&ua->proc->locks_spin);
-               dlm_put_lkb(lkb);
        }
  out:
        mutex_unlock(&ls->ls_clear_proc_locks);
@@ -286,47 +299,71 @@ static int device_user_unlock(struct dlm_user_proc *proc,
        return error;
 }
 
-static int device_create_lockspace(struct dlm_lspace_params *params)
+static int create_misc_device(struct dlm_ls *ls, char *name)
 {
-       dlm_lockspace_t *lockspace;
-       struct dlm_ls *ls;
        int error, len;
 
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       error = dlm_new_lockspace(params->name, strlen(params->name),
-                                 &lockspace, 0, DLM_USER_LVB_LEN);
-       if (error)
-               return error;
-
-       ls = dlm_find_lockspace_local(lockspace);
-       if (!ls)
-               return -ENOENT;
-
        error = -ENOMEM;
-       len = strlen(params->name) + strlen(name_prefix) + 2;
+       len = strlen(name) + strlen(name_prefix) + 2;
        ls->ls_device.name = kzalloc(len, GFP_KERNEL);
        if (!ls->ls_device.name)
                goto fail;
+
        snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
-                params->name);
+                name);
        ls->ls_device.fops = &device_fops;
        ls->ls_device.minor = MISC_DYNAMIC_MINOR;
 
        error = misc_register(&ls->ls_device);
        if (error) {
                kfree(ls->ls_device.name);
-               goto fail;
        }
+fail:
+       return error;
+}
+
+static int device_user_purge(struct dlm_user_proc *proc,
+                            struct dlm_purge_params *params)
+{
+       struct dlm_ls *ls;
+       int error;
+
+       ls = dlm_find_lockspace_local(proc->lockspace);
+       if (!ls)
+               return -ENOENT;
+
+       error = dlm_user_purge(ls, proc, params->nodeid, params->pid);
 
-       error = ls->ls_device.minor;
        dlm_put_lockspace(ls);
        return error;
+}
+
+static int device_create_lockspace(struct dlm_lspace_params *params)
+{
+       dlm_lockspace_t *lockspace;
+       struct dlm_ls *ls;
+       int error;
 
- fail:
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       error = dlm_new_lockspace(params->name, strlen(params->name),
+                                 &lockspace, 0, DLM_USER_LVB_LEN);
+       if (error)
+               return error;
+
+       ls = dlm_find_lockspace_local(lockspace);
+       if (!ls)
+               return -ENOENT;
+
+       error = create_misc_device(ls, params->name);
        dlm_put_lockspace(ls);
-       dlm_release_lockspace(lockspace, 0);
+
+       if (error)
+               dlm_release_lockspace(lockspace, 0);
+       else
+               error = ls->ls_device.minor;
+
        return error;
 }
 
@@ -343,6 +380,10 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
        if (!ls)
                return -ENOENT;
 
+       /* Deregister the misc device first, so we don't have
+        * a device that's not attached to a lockspace. If
+        * dlm_release_lockspace fails then we can recreate it
+        */
        error = misc_deregister(&ls->ls_device);
        if (error) {
                dlm_put_lockspace(ls);
@@ -361,6 +402,8 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
 
        dlm_put_lockspace(ls);
        error = dlm_release_lockspace(lockspace, force);
+       if (error)
+               create_misc_device(ls, ls->ls_name);
  out:
        return error;
 }
@@ -497,6 +540,14 @@ static ssize_t device_write(struct file *file, const char __user *buf,
                error = device_remove_lockspace(&kbuf->i.lspace);
                break;
 
+       case DLM_USER_PURGE:
+               if (!proc) {
+                       log_print("no locking on control device");
+                       goto out_sig;
+               }
+               error = device_user_purge(proc, &kbuf->i.purge);
+               break;
+
        default:
                log_print("Unknown command passed to DLM device : %d\n",
                          kbuf->cmd);
index b16f991..0a5febc 100644 (file)
@@ -1432,7 +1432,7 @@ int vfs_quota_off(struct super_block *sb, int type)
                        mutex_unlock(&dqopt->dqonoff_mutex);
                }
        if (sb->s_bdev)
-               invalidate_bdev(sb->s_bdev, 0);
+               invalidate_bdev(sb->s_bdev);
        return 0;
 }
 
@@ -1468,7 +1468,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
         * we see all the changes from userspace... */
        write_inode_now(inode, 1);
        /* And now flush the block cache so that kernel sees the changes */
-       invalidate_bdev(sb->s_bdev, 0);
+       invalidate_bdev(sb->s_bdev);
        mutex_lock(&inode->i_mutex);
        mutex_lock(&dqopt->dqonoff_mutex);
        if (sb_has_quota_enabled(sb, type)) {
index fc4a3a2..8cbf3f6 100644 (file)
@@ -583,8 +583,7 @@ inode_info_init_once(void *vptr, struct kmem_cache *cachep, unsigned long flags)
 {
        struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
 
@@ -793,7 +792,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 +800,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 +840,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 +861,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 b731b09..0770c4b 100644 (file)
@@ -46,7 +46,6 @@ struct kmem_cache *ecryptfs_lower_page_cache;
  */
 static struct page *ecryptfs_get1page(struct file *file, int index)
 {
-       struct page *page;
        struct dentry *dentry;
        struct inode *inode;
        struct address_space *mapping;
@@ -54,14 +53,7 @@ static struct page *ecryptfs_get1page(struct file *file, int index)
        dentry = file->f_path.dentry;
        inode = dentry->d_inode;
        mapping = inode->i_mapping;
-       page = read_cache_page(mapping, index,
-                              (filler_t *)mapping->a_ops->readpage,
-                              (void *)file);
-       if (IS_ERR(page))
-               goto out;
-       wait_on_page_locked(page);
-out:
-       return page;
+       return read_mapping_page(mapping, index, (void *)file);
 }
 
 static
@@ -233,7 +225,6 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
                ecryptfs_printk(KERN_ERR, "Error reading from page cache\n");
                goto out;
        }
-       wait_on_page_locked(lower_page);
        page_data = kmap_atomic(page, KM_USER0);
        lower_page_data = kmap_atomic(lower_page, KM_USER1);
        memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
index c2235e4..ba7a8b9 100644 (file)
@@ -72,8 +72,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct efs_inode_info *ei = (struct efs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index e89bfc8..1d1e7e3 100644 (file)
@@ -161,10 +161,7 @@ static struct page * ext2_get_page(struct inode *dir, unsigned long n)
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
                kmap(page);
-               if (!PageUptodate(page))
-                       goto fail;
                if (!PageChecked(page))
                        ext2_check_page(page);
                if (PageError(page))
index a046a41..685a1c2 100644 (file)
@@ -160,8 +160,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                rwlock_init(&ei->i_meta_lock);
 #ifdef CONFIG_EXT2_FS_XATTR
                init_rwsem(&ei->xattr_sem);
index 4a4fcd6..54d3c90 100644 (file)
@@ -420,7 +420,7 @@ static void ext3_put_super (struct super_block * sb)
                dump_orphan_list(sb, sbi);
        J_ASSERT(list_empty(&sbi->s_orphan));
 
-       invalidate_bdev(sb->s_bdev, 0);
+       invalidate_bdev(sb->s_bdev);
        if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
                /*
                 * Invalidate the journal device's buffers.  We don't want them
@@ -428,7 +428,7 @@ static void ext3_put_super (struct super_block * sb)
                 * hotswapped, and it breaks the `ro-after' testing code.
                 */
                sync_blockdev(sbi->journal_bdev);
-               invalidate_bdev(sbi->journal_bdev, 0);
+               invalidate_bdev(sbi->journal_bdev);
                ext3_blkdev_remove(sbi);
        }
        sb->s_fs_info = NULL;
@@ -466,8 +466,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct ext3_inode_info *ei = (struct ext3_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                INIT_LIST_HEAD(&ei->i_orphan);
 #ifdef CONFIG_EXT3_FS_XATTR
                init_rwsem(&ei->xattr_sem);
index 61c4718..7191269 100644 (file)
@@ -470,7 +470,7 @@ static void ext4_put_super (struct super_block * sb)
                dump_orphan_list(sb, sbi);
        J_ASSERT(list_empty(&sbi->s_orphan));
 
-       invalidate_bdev(sb->s_bdev, 0);
+       invalidate_bdev(sb->s_bdev);
        if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
                /*
                 * Invalidate the journal device's buffers.  We don't want them
@@ -478,7 +478,7 @@ static void ext4_put_super (struct super_block * sb)
                 * hotswapped, and it breaks the `ro-after' testing code.
                 */
                sync_blockdev(sbi->journal_bdev);
-               invalidate_bdev(sbi->journal_bdev, 0);
+               invalidate_bdev(sbi->journal_bdev);
                ext4_blkdev_remove(sbi);
        }
        sb->s_fs_info = NULL;
@@ -517,8 +517,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                INIT_LIST_HEAD(&ei->i_orphan);
 #ifdef CONFIG_EXT4DEV_FS_XATTR
                init_rwsem(&ei->xattr_sem);
index 05c2941..1959143 100644 (file)
@@ -40,8 +40,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct fat_cache *cache = (struct fat_cache *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                INIT_LIST_HEAD(&cache->cache_list);
 }
 
index 9bfe607..65cb54b 100644 (file)
@@ -499,8 +499,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct msdos_inode_info *ei = (struct msdos_inode_info *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                spin_lock_init(&ei->cache_lru_lock);
                ei->nr_caches = 0;
                ei->cache_valid_id = FAT_CACHE_VALID + 1;
index decac62..ed8f0b0 100644 (file)
@@ -74,10 +74,7 @@ vxfs_get_page(struct address_space *mapping, u_long n)
        pp = read_mapping_page(mapping, n, NULL);
 
        if (!IS_ERR(pp)) {
-               wait_on_page_locked(pp);
                kmap(pp);
-               if (!PageUptodate(pp))
-                       goto fail;
                /** if (!PageChecked(pp)) **/
                        /** vxfs_check_page(pp); **/
                if (PageError(pp))
index 2fd0692..acfad65 100644 (file)
@@ -738,8 +738,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
 
        if (cmd == F_GETLK) {
                if (fc->no_lock) {
-                       if (!posix_test_lock(file, fl, fl))
-                               fl->fl_type = F_UNLCK;
+                       posix_test_lock(file, fl);
                        err = 0;
                } else
                        err = fuse_getlk(file, fl);
index 608db81..d8003be 100644 (file)
@@ -685,8 +685,7 @@ static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep,
 {
        struct inode * inode = foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(inode);
 }
 
@@ -731,12 +730,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 82a1ac7..a96fa07 100644 (file)
@@ -1262,9 +1262,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                              u64 leaf_no)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct buffer_head *bh;
        struct gfs2_leaf *lf;
-       unsigned entries = 0;
+       unsigned entries = 0, entries2 = 0;
        unsigned leaves = 0;
        const struct gfs2_dirent **darr, *dent;
        struct dirent_gather g;
@@ -1290,7 +1291,13 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                return 0;
 
        error = -ENOMEM;
-       larr = vmalloc((leaves + entries) * sizeof(void *));
+       /*
+        * The extra 99 entries are not normally used, but are a buffer
+        * zone in case the number of entries in the leaf is corrupt.
+        * 99 is the maximum number of entries that can fit in a single
+        * leaf block.
+        */
+       larr = vmalloc((leaves + entries + 99) * sizeof(void *));
        if (!larr)
                goto out;
        darr = (const struct gfs2_dirent **)(larr + leaves);
@@ -1305,10 +1312,20 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                lf = (struct gfs2_leaf *)bh->b_data;
                lfn = be64_to_cpu(lf->lf_next);
                if (lf->lf_entries) {
+                       entries2 += be16_to_cpu(lf->lf_entries);
                        dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
                                                gfs2_dirent_gather, NULL, &g);
                        error = PTR_ERR(dent);
-                       if (IS_ERR(dent)) {
+                       if (IS_ERR(dent))
+                               goto out_kfree;
+                       if (entries2 != g.offset) {
+                               fs_warn(sdp, "Number of entries corrupt in dir "
+                                               "leaf %llu, entries2 (%u) != "
+                                               "g.offset (%u)\n",
+                                       (unsigned long long)bh->b_blocknr,
+                                       entries2, g.offset);
+                                       
+                               error = -EIO;
                                goto out_kfree;
                        }
                        error = 0;
@@ -1318,6 +1335,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
                }
        } while(lfn);
 
+       BUG_ON(entries2 != entries);
        error = do_filldir_main(ip, offset, opaque, filldir, darr,
                                entries, copied);
 out_kfree:
@@ -1401,6 +1419,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
                  filldir_t filldir)
 {
        struct gfs2_inode *dip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct dirent_gather g;
        const struct gfs2_dirent **darr, *dent;
        struct buffer_head *dibh;
@@ -1423,8 +1442,8 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
                return error;
 
        error = -ENOMEM;
-       darr = kmalloc(dip->i_di.di_entries * sizeof(struct gfs2_dirent *),
-                      GFP_KERNEL);
+       /* 96 is max number of dirents which can be stuffed into an inode */
+       darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL);
        if (darr) {
                g.pdent = darr;
                g.offset = 0;
@@ -1434,6 +1453,15 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
                        error = PTR_ERR(dent);
                        goto out;
                }
+               if (dip->i_di.di_entries != g.offset) {
+                       fs_warn(sdp, "Number of entries corrupt in dir %llu, "
+                               "ip->i_di.di_entries (%u) != g.offset (%u)\n",
+                               (unsigned long long)dip->i_num.no_addr,
+                               dip->i_di.di_entries,
+                               g.offset);
+                       error = -EIO;
+                       goto out;
+               }
                error = do_filldir_main(dip, offset, opaque, filldir, darr,
                                        dip->i_di.di_entries, &copied);
 out:
index 12accb0..1815429 100644 (file)
 #include <linux/module.h>
 #include <linux/rwsem.h>
 #include <asm/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -40,20 +44,30 @@ struct gfs2_gl_hash_bucket {
         struct hlist_head hb_list;
 };
 
+struct glock_iter {
+       int hash;                     /* hash bucket index         */
+       struct gfs2_sbd *sdp;         /* incore superblock         */
+       struct gfs2_glock *gl;        /* current glock struct      */
+       struct hlist_head *hb_list;   /* current hash bucket ptr   */
+       struct seq_file *seq;         /* sequence file for debugfs */
+       char string[512];             /* scratch space             */
+};
+
 typedef void (*glock_examiner) (struct gfs2_glock * gl);
 
 static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
-static int dump_glock(struct gfs2_glock *gl);
-static int dump_inode(struct gfs2_inode *ip);
-static void gfs2_glock_xmote_th(struct gfs2_holder *gh);
+static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl);
+static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh);
 static void gfs2_glock_drop_th(struct gfs2_glock *gl);
 static DECLARE_RWSEM(gfs2_umount_flush_sem);
+static struct dentry *gfs2_root;
 
 #define GFS2_GL_HASH_SHIFT      15
 #define GFS2_GL_HASH_SIZE       (1 << GFS2_GL_HASH_SHIFT)
 #define GFS2_GL_HASH_MASK       (GFS2_GL_HASH_SIZE - 1)
 
 static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE];
+static struct dentry *gfs2_root;
 
 /*
  * Despite what you might think, the numbers below are not arbitrary :-)
@@ -202,7 +216,6 @@ int gfs2_glock_put(struct gfs2_glock *gl)
                gfs2_assert(sdp, list_empty(&gl->gl_reclaim));
                gfs2_assert(sdp, list_empty(&gl->gl_holders));
                gfs2_assert(sdp, list_empty(&gl->gl_waiters1));
-               gfs2_assert(sdp, list_empty(&gl->gl_waiters2));
                gfs2_assert(sdp, list_empty(&gl->gl_waiters3));
                glock_free(gl);
                rv = 1;
@@ -303,7 +316,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        atomic_set(&gl->gl_ref, 1);
        gl->gl_state = LM_ST_UNLOCKED;
        gl->gl_hash = hash;
-       gl->gl_owner = NULL;
+       gl->gl_owner_pid = 0;
        gl->gl_ip = 0;
        gl->gl_ops = glops;
        gl->gl_req_gh = NULL;
@@ -367,7 +380,7 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
        INIT_LIST_HEAD(&gh->gh_list);
        gh->gh_gl = gl;
        gh->gh_ip = (unsigned long)__builtin_return_address(0);
-       gh->gh_owner = current;
+       gh->gh_owner_pid = current->pid;
        gh->gh_state = state;
        gh->gh_flags = flags;
        gh->gh_error = 0;
@@ -389,7 +402,7 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *
 {
        gh->gh_state = state;
        gh->gh_flags = flags;
-       gh->gh_iflags &= 1 << HIF_ALLOCED;
+       gh->gh_iflags = 0;
        gh->gh_ip = (unsigned long)__builtin_return_address(0);
 }
 
@@ -406,54 +419,8 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
        gh->gh_ip = 0;
 }
 
-/**
- * gfs2_holder_get - get a struct gfs2_holder structure
- * @gl: the glock
- * @state: the state we're requesting
- * @flags: the modifier flags
- * @gfp_flags:
- *
- * Figure out how big an impact this function has.  Either:
- * 1) Replace it with a cache of structures hanging off the struct gfs2_sbd
- * 2) Leave it like it is
- *
- * Returns: the holder structure, NULL on ENOMEM
- */
-
-static struct gfs2_holder *gfs2_holder_get(struct gfs2_glock *gl,
-                                          unsigned int state,
-                                          int flags, gfp_t gfp_flags)
-{
-       struct gfs2_holder *gh;
-
-       gh = kmalloc(sizeof(struct gfs2_holder), gfp_flags);
-       if (!gh)
-               return NULL;
-
-       gfs2_holder_init(gl, state, flags, gh);
-       set_bit(HIF_ALLOCED, &gh->gh_iflags);
-       gh->gh_ip = (unsigned long)__builtin_return_address(0);
-       return gh;
-}
-
-/**
- * gfs2_holder_put - get rid of a struct gfs2_holder structure
- * @gh: the holder structure
- *
- */
-
-static void gfs2_holder_put(struct gfs2_holder *gh)
+static void gfs2_holder_wake(struct gfs2_holder *gh)
 {
-       gfs2_holder_uninit(gh);
-       kfree(gh);
-}
-
-static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh)
-{
-       if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) {
-               gfs2_holder_put(gh);
-               return;
-       }
        clear_bit(HIF_WAIT, &gh->gh_iflags);
        smp_mb();
        wake_up_bit(&gh->gh_iflags, HIF_WAIT);
@@ -519,7 +486,7 @@ static int rq_promote(struct gfs2_holder *gh)
                                gfs2_reclaim_glock(sdp);
                        }
 
-                       gfs2_glock_xmote_th(gh);
+                       gfs2_glock_xmote_th(gh->gh_gl, gh);
                        spin_lock(&gl->gl_spin);
                }
                return 1;
@@ -542,7 +509,7 @@ static int rq_promote(struct gfs2_holder *gh)
        gh->gh_error = 0;
        set_bit(HIF_HOLDER, &gh->gh_iflags);
 
-       gfs2_holder_dispose_or_wake(gh);
+       gfs2_holder_wake(gh);
 
        return 0;
 }
@@ -554,32 +521,24 @@ static int rq_promote(struct gfs2_holder *gh)
  * Returns: 1 if the queue is blocked
  */
 
-static int rq_demote(struct gfs2_holder *gh)
+static int rq_demote(struct gfs2_glock *gl)
 {
-       struct gfs2_glock *gl = gh->gh_gl;
-
        if (!list_empty(&gl->gl_holders))
                return 1;
 
-       if (gl->gl_state == gh->gh_state || gl->gl_state == LM_ST_UNLOCKED) {
-               list_del_init(&gh->gh_list);
-               gh->gh_error = 0;
-               spin_unlock(&gl->gl_spin);
-               gfs2_holder_dispose_or_wake(gh);
-               spin_lock(&gl->gl_spin);
-       } else {
-               gl->gl_req_gh = gh;
-               set_bit(GLF_LOCK, &gl->gl_flags);
-               spin_unlock(&gl->gl_spin);
-
-               if (gh->gh_state == LM_ST_UNLOCKED ||
-                   gl->gl_state != LM_ST_EXCLUSIVE)
-                       gfs2_glock_drop_th(gl);
-               else
-                       gfs2_glock_xmote_th(gh);
-
-               spin_lock(&gl->gl_spin);
+       if (gl->gl_state == gl->gl_demote_state ||
+           gl->gl_state == LM_ST_UNLOCKED) {
+               clear_bit(GLF_DEMOTE, &gl->gl_flags);
+               return 0;
        }
+       set_bit(GLF_LOCK, &gl->gl_flags);
+       spin_unlock(&gl->gl_spin);
+       if (gl->gl_demote_state == LM_ST_UNLOCKED ||
+           gl->gl_state != LM_ST_EXCLUSIVE)
+               gfs2_glock_drop_th(gl);
+       else
+               gfs2_glock_xmote_th(gl, NULL);
+       spin_lock(&gl->gl_spin);
 
        return 0;
 }
@@ -607,16 +566,8 @@ static void run_queue(struct gfs2_glock *gl)
                        else
                                gfs2_assert_warn(gl->gl_sbd, 0);
 
-               } else if (!list_empty(&gl->gl_waiters2) &&
-                          !test_bit(GLF_SKIP_WAITERS2, &gl->gl_flags)) {
-                       gh = list_entry(gl->gl_waiters2.next,
-                                       struct gfs2_holder, gh_list);
-
-                       if (test_bit(HIF_DEMOTE, &gh->gh_iflags))
-                               blocked = rq_demote(gh);
-                       else
-                               gfs2_assert_warn(gl->gl_sbd, 0);
-
+               } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
+                       blocked = rq_demote(gl);
                } else if (!list_empty(&gl->gl_waiters3)) {
                        gh = list_entry(gl->gl_waiters3.next,
                                        struct gfs2_holder, gh_list);
@@ -654,7 +605,7 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl)
        if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
                list_add_tail(&gh.gh_list, &gl->gl_waiters1);
        } else {
-               gl->gl_owner = current;
+               gl->gl_owner_pid = current->pid;
                gl->gl_ip = (unsigned long)__builtin_return_address(0);
                clear_bit(HIF_WAIT, &gh.gh_iflags);
                smp_mb();
@@ -681,7 +632,7 @@ static int gfs2_glmutex_trylock(struct gfs2_glock *gl)
        if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
                acquired = 0;
        } else {
-               gl->gl_owner = current;
+               gl->gl_owner_pid = current->pid;
                gl->gl_ip = (unsigned long)__builtin_return_address(0);
        }
        spin_unlock(&gl->gl_spin);
@@ -699,7 +650,7 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
 {
        spin_lock(&gl->gl_spin);
        clear_bit(GLF_LOCK, &gl->gl_flags);
-       gl->gl_owner = NULL;
+       gl->gl_owner_pid = 0;
        gl->gl_ip = 0;
        run_queue(gl);
        BUG_ON(!spin_is_locked(&gl->gl_spin));
@@ -707,50 +658,24 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
 }
 
 /**
- * handle_callback - add a demote request to a lock's queue
+ * handle_callback - process a demote request
  * @gl: the glock
  * @state: the state the caller wants us to change to
  *
- * Note: This may fail sliently if we are out of memory.
+ * There are only two requests that we are going to see in actual
+ * practise: LM_ST_SHARED and LM_ST_UNLOCKED
  */
 
 static void handle_callback(struct gfs2_glock *gl, unsigned int state)
 {
-       struct gfs2_holder *gh, *new_gh = NULL;
-
-restart:
        spin_lock(&gl->gl_spin);
-
-       list_for_each_entry(gh, &gl->gl_waiters2, gh_list) {
-               if (test_bit(HIF_DEMOTE, &gh->gh_iflags) &&
-                   gl->gl_req_gh != gh) {
-                       if (gh->gh_state != state)
-                               gh->gh_state = LM_ST_UNLOCKED;
-                       goto out;
-               }
-       }
-
-       if (new_gh) {
-               list_add_tail(&new_gh->gh_list, &gl->gl_waiters2);
-               new_gh = NULL;
-       } else {
-               spin_unlock(&gl->gl_spin);
-
-               new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_NOFS);
-               if (!new_gh)
-                       return;
-               set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
-               set_bit(HIF_DEALLOC, &new_gh->gh_iflags);
-               set_bit(HIF_WAIT, &new_gh->gh_iflags);
-
-               goto restart;
+       if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) {
+               gl->gl_demote_state = state;
+               gl->gl_demote_time = jiffies;
+       } else if (gl->gl_demote_state != LM_ST_UNLOCKED) {
+               gl->gl_demote_state = state;
        }
-
-out:
        spin_unlock(&gl->gl_spin);
-
-       if (new_gh)
-               gfs2_holder_put(new_gh);
 }
 
 /**
@@ -810,56 +735,37 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
 
        /*  Deal with each possible exit condition  */
 
-       if (!gh)
+       if (!gh) {
                gl->gl_stamp = jiffies;
-       else if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
+               if (ret & LM_OUT_CANCELED)
+                       op_done = 0;
+               else
+                       clear_bit(GLF_DEMOTE, &gl->gl_flags);
+       } else {
                spin_lock(&gl->gl_spin);
                list_del_init(&gh->gh_list);
                gh->gh_error = -EIO;
-               spin_unlock(&gl->gl_spin);
-       } else if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) {
-               spin_lock(&gl->gl_spin);
-               list_del_init(&gh->gh_list);
-               if (gl->gl_state == gh->gh_state ||
-                   gl->gl_state == LM_ST_UNLOCKED) {
+               if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 
+                       goto out;
+               gh->gh_error = GLR_CANCELED;
+               if (ret & LM_OUT_CANCELED) 
+                       goto out;
+               if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
+                       list_add_tail(&gh->gh_list, &gl->gl_holders);
                        gh->gh_error = 0;
-               } else {
-                       if (gfs2_assert_warn(sdp, gh->gh_flags &
-                                       (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1)
-                               fs_warn(sdp, "ret = 0x%.8X\n", ret);
-                       gh->gh_error = GLR_TRYFAILED;
+                       set_bit(HIF_HOLDER, &gh->gh_iflags);
+                       set_bit(HIF_FIRST, &gh->gh_iflags);
+                       op_done = 0;
+                       goto out;
                }
-               spin_unlock(&gl->gl_spin);
-
-               if (ret & LM_OUT_CANCELED)
-                       handle_callback(gl, LM_ST_UNLOCKED);
-
-       } else if (ret & LM_OUT_CANCELED) {
-               spin_lock(&gl->gl_spin);
-               list_del_init(&gh->gh_list);
-               gh->gh_error = GLR_CANCELED;
-               spin_unlock(&gl->gl_spin);
-
-       } else if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
-               spin_lock(&gl->gl_spin);
-               list_move_tail(&gh->gh_list, &gl->gl_holders);
-               gh->gh_error = 0;
-               set_bit(HIF_HOLDER, &gh->gh_iflags);
-               spin_unlock(&gl->gl_spin);
-
-               set_bit(HIF_FIRST, &gh->gh_iflags);
-
-               op_done = 0;
-
-       } else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
-               spin_lock(&gl->gl_spin);
-               list_del_init(&gh->gh_list);
                gh->gh_error = GLR_TRYFAILED;
-               spin_unlock(&gl->gl_spin);
-
-       } else {
+               if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))
+                       goto out;
+               gh->gh_error = -EINVAL;
                if (gfs2_assert_withdraw(sdp, 0) == -1)
                        fs_err(sdp, "ret = 0x%.8X\n", ret);
+out:
+               spin_unlock(&gl->gl_spin);
        }
 
        if (glops->go_xmote_bh)
@@ -877,7 +783,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
        gfs2_glock_put(gl);
 
        if (gh)
-               gfs2_holder_dispose_or_wake(gh);
+               gfs2_holder_wake(gh);
 }
 
 /**
@@ -888,12 +794,11 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
  *
  */
 
-void gfs2_glock_xmote_th(struct gfs2_holder *gh)
+void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
 {
-       struct gfs2_glock *gl = gh->gh_gl;
        struct gfs2_sbd *sdp = gl->gl_sbd;
-       int flags = gh->gh_flags;
-       unsigned state = gh->gh_state;
+       int flags = gh ? gh->gh_flags : 0;
+       unsigned state = gh ? gh->gh_state : gl->gl_demote_state;
        const struct gfs2_glock_operations *glops = gl->gl_ops;
        int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB |
                                 LM_FLAG_NOEXP | LM_FLAG_ANY |
@@ -943,6 +848,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
        gfs2_assert_warn(sdp, !ret);
 
        state_change(gl, LM_ST_UNLOCKED);
+       clear_bit(GLF_DEMOTE, &gl->gl_flags);
 
        if (glops->go_inval)
                glops->go_inval(gl, DIO_METADATA);
@@ -964,7 +870,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
        gfs2_glock_put(gl);
 
        if (gh)
-               gfs2_holder_dispose_or_wake(gh);
+               gfs2_holder_wake(gh);
 }
 
 /**
@@ -1097,18 +1003,32 @@ static int glock_wait_internal(struct gfs2_holder *gh)
 }
 
 static inline struct gfs2_holder *
-find_holder_by_owner(struct list_head *head, struct task_struct *owner)
+find_holder_by_owner(struct list_head *head, pid_t pid)
 {
        struct gfs2_holder *gh;
 
        list_for_each_entry(gh, head, gh_list) {
-               if (gh->gh_owner == owner)
+               if (gh->gh_owner_pid == pid)
                        return gh;
        }
 
        return NULL;
 }
 
+static void print_dbg(struct glock_iter *gi, const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       if (gi) {
+               vsprintf(gi->string, fmt, args);
+               seq_printf(gi->seq, gi->string);
+       }
+       else
+               vprintk(fmt, args);
+       va_end(args);
+}
+
 /**
  * add_to_queue - Add a holder to the wait queue (but look for recursion)
  * @gh: the holder structure to add
@@ -1120,24 +1040,24 @@ static void add_to_queue(struct gfs2_holder *gh)
        struct gfs2_glock *gl = gh->gh_gl;
        struct gfs2_holder *existing;
 
-       BUG_ON(!gh->gh_owner);
+       BUG_ON(!gh->gh_owner_pid);
        if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
                BUG();
 
-       existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner);
+       existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner_pid);
        if (existing) {
                print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip);
-               printk(KERN_INFO "pid : %d\n", existing->gh_owner->pid);
+               printk(KERN_INFO "pid : %d\n", existing->gh_owner_pid);
                printk(KERN_INFO "lock type : %d lock state : %d\n",
                                existing->gh_gl->gl_name.ln_type, existing->gh_gl->gl_state);
                print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip);
-               printk(KERN_INFO "pid : %d\n", gh->gh_owner->pid);
+               printk(KERN_INFO "pid : %d\n", gh->gh_owner_pid);
                printk(KERN_INFO "lock type : %d lock state : %d\n",
                                gl->gl_name.ln_type, gl->gl_state);
                BUG();
        }
 
-       existing = find_holder_by_owner(&gl->gl_waiters3, gh->gh_owner);
+       existing = find_holder_by_owner(&gl->gl_waiters3, gh->gh_owner_pid);
        if (existing) {
                print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip);
                print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip);
@@ -1267,9 +1187,8 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
                if (glops->go_unlock)
                        glops->go_unlock(gh);
 
-               gl->gl_stamp = jiffies;
-
                spin_lock(&gl->gl_spin);
+               gl->gl_stamp = jiffies;
        }
 
        clear_bit(GLF_LOCK, &gl->gl_flags);
@@ -1841,6 +1760,15 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait)
  *  Diagnostic routines to help debug distributed deadlock
  */
 
+static void gfs2_print_symbol(struct glock_iter *gi, const char *fmt,
+                              unsigned long address)
+{
+       char buffer[KSYM_SYMBOL_LEN];
+
+       sprint_symbol(buffer, address);
+       print_dbg(gi, fmt, buffer);
+}
+
 /**
  * dump_holder - print information about a glock holder
  * @str: a string naming the type of holder
@@ -1849,31 +1777,37 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait)
  * Returns: 0 on success, -ENOBUFS when we run out of space
  */
 
-static int dump_holder(char *str, struct gfs2_holder *gh)
+static int dump_holder(struct glock_iter *gi, char *str,
+                      struct gfs2_holder *gh)
 {
        unsigned int x;
-       int error = -ENOBUFS;
-
-       printk(KERN_INFO "  %s\n", str);
-       printk(KERN_INFO "    owner = %ld\n",
-                  (gh->gh_owner) ? (long)gh->gh_owner->pid : -1);
-       printk(KERN_INFO "    gh_state = %u\n", gh->gh_state);
-       printk(KERN_INFO "    gh_flags =");
+       struct task_struct *gh_owner;
+
+       print_dbg(gi, "  %s\n", str);
+       if (gh->gh_owner_pid) {
+               print_dbg(gi, "    owner = %ld ", (long)gh->gh_owner_pid);
+               gh_owner = find_task_by_pid(gh->gh_owner_pid);
+               if (gh_owner)
+                       print_dbg(gi, "(%s)\n", gh_owner->comm);
+               else
+                       print_dbg(gi, "(ended)\n");
+       } else
+               print_dbg(gi, "    owner = -1\n");
+       print_dbg(gi, "    gh_state = %u\n", gh->gh_state);
+       print_dbg(gi, "    gh_flags =");
        for (x = 0; x < 32; x++)
                if (gh->gh_flags & (1 << x))
-                       printk(" %u", x);
-       printk(" \n");
-       printk(KERN_INFO "    error = %d\n", gh->gh_error);
-       printk(KERN_INFO "    gh_iflags =");
+                       print_dbg(gi, " %u", x);
+       print_dbg(gi, " \n");
+       print_dbg(gi, "    error = %d\n", gh->gh_error);
+       print_dbg(gi, "    gh_iflags =");
        for (x = 0; x < 32; x++)
                if (test_bit(x, &gh->gh_iflags))
-                       printk(" %u", x);
-       printk(" \n");
-       print_symbol(KERN_INFO "    initialized at: %s\n", gh->gh_ip);
-
-       error = 0;
+                       print_dbg(gi, " %u", x);
+       print_dbg(gi, " \n");
+        gfs2_print_symbol(gi, "    initialized at: %s\n", gh->gh_ip);
 
-       return error;
+       return 0;
 }
 
 /**
@@ -1883,25 +1817,20 @@ static int dump_holder(char *str, struct gfs2_holder *gh)
  * Returns: 0 on success, -ENOBUFS when we run out of space
  */
 
-static int dump_inode(struct gfs2_inode *ip)
+static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip)
 {
        unsigned int x;
-       int error = -ENOBUFS;
 
-       printk(KERN_INFO "  Inode:\n");
-       printk(KERN_INFO "    num = %llu %llu\n",
-                   (unsigned long long)ip->i_num.no_formal_ino,
-                   (unsigned long long)ip->i_num.no_addr);
-       printk(KERN_INFO "    type = %u\n", IF2DT(ip->i_inode.i_mode));
-       printk(KERN_INFO "    i_flags =");
+       print_dbg(gi, "  Inode:\n");
+       print_dbg(gi, "    num = %llu/%llu\n",
+                   ip->i_num.no_formal_ino, ip->i_num.no_addr);
+       print_dbg(gi, "    type = %u\n", IF2DT(ip->i_inode.i_mode));
+       print_dbg(gi, "    i_flags =");
        for (x = 0; x < 32; x++)
                if (test_bit(x, &ip->i_flags))
-                       printk(" %u", x);
-       printk(" \n");
-
-       error = 0;
-
-       return error;
+                       print_dbg(gi, " %u", x);
+       print_dbg(gi, " \n");
+       return 0;
 }
 
 /**
@@ -1912,74 +1841,86 @@ static int dump_inode(struct gfs2_inode *ip)
  * Returns: 0 on success, -ENOBUFS when we run out of space
  */
 
-static int dump_glock(struct gfs2_glock *gl)
+static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
 {
        struct gfs2_holder *gh;
        unsigned int x;
        int error = -ENOBUFS;
+       struct task_struct *gl_owner;
 
        spin_lock(&gl->gl_spin);
 
-       printk(KERN_INFO "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type,
-              (unsigned long long)gl->gl_name.ln_number);
-       printk(KERN_INFO "  gl_flags =");
+       print_dbg(gi, "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type,
+                  (unsigned long long)gl->gl_name.ln_number);
+       print_dbg(gi, "  gl_flags =");
        for (x = 0; x < 32; x++) {
                if (test_bit(x, &gl->gl_flags))
-                       printk(" %u", x);
+                       print_dbg(gi, " %u", x);
        }
-       printk(" \n");
-       printk(KERN_INFO "  gl_ref = %d\n", atomic_read(&gl->gl_ref));
-       printk(KERN_INFO "  gl_state = %u\n", gl->gl_state);
-       printk(KERN_INFO "  gl_owner = %s\n", gl->gl_owner->comm);
-       print_symbol(KERN_INFO "  gl_ip = %s\n", gl->gl_ip);
-       printk(KERN_INFO "  req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no");
-       printk(KERN_INFO "  req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
-       printk(KERN_INFO "  lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
-       printk(KERN_INFO "  object = %s\n", (gl->gl_object) ? "yes" : "no");
-       printk(KERN_INFO "  le = %s\n",
+       if (!test_bit(GLF_LOCK, &gl->gl_flags))
+               print_dbg(gi, " (unlocked)");
+       print_dbg(gi, " \n");
+       print_dbg(gi, "  gl_ref = %d\n", atomic_read(&gl->gl_ref));
+       print_dbg(gi, "  gl_state = %u\n", gl->gl_state);
+       if (gl->gl_owner_pid) {
+               gl_owner = find_task_by_pid(gl->gl_owner_pid);
+               if (gl_owner)
+                       print_dbg(gi, "  gl_owner = pid %d (%s)\n",
+                                 gl->gl_owner_pid, gl_owner->comm);
+               else
+                       print_dbg(gi, "  gl_owner = %d (ended)\n",
+                                 gl->gl_owner_pid);
+       } else
+               print_dbg(gi, "  gl_owner = -1\n");
+       print_dbg(gi, "  gl_ip = %lu\n", gl->gl_ip);
+       print_dbg(gi, "  req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no");
+       print_dbg(gi, "  req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
+       print_dbg(gi, "  lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
+       print_dbg(gi, "  object = %s\n", (gl->gl_object) ? "yes" : "no");
+       print_dbg(gi, "  le = %s\n",
                   (list_empty(&gl->gl_le.le_list)) ? "no" : "yes");
-       printk(KERN_INFO "  reclaim = %s\n",
-                   (list_empty(&gl->gl_reclaim)) ? "no" : "yes");
+       print_dbg(gi, "  reclaim = %s\n",
+                  (list_empty(&gl->gl_reclaim)) ? "no" : "yes");
        if (gl->gl_aspace)
-               printk(KERN_INFO "  aspace = 0x%p nrpages = %lu\n", gl->gl_aspace,
-                      gl->gl_aspace->i_mapping->nrpages);
+               print_dbg(gi, "  aspace = 0x%p nrpages = %lu\n", gl->gl_aspace,
+                          gl->gl_aspace->i_mapping->nrpages);
        else
-               printk(KERN_INFO "  aspace = no\n");
-       printk(KERN_INFO "  ail = %d\n", atomic_read(&gl->gl_ail_count));
+               print_dbg(gi, "  aspace = no\n");
+       print_dbg(gi, "  ail = %d\n", atomic_read(&gl->gl_ail_count));
        if (gl->gl_req_gh) {
-               error = dump_holder("Request", gl->gl_req_gh);
+               error = dump_holder(gi, "Request", gl->gl_req_gh);
                if (error)
                        goto out;
        }
        list_for_each_entry(gh, &gl->gl_holders, gh_list) {
-               error = dump_holder("Holder", gh);
+               error = dump_holder(gi, "Holder", gh);
                if (error)
                        goto out;
        }
        list_for_each_entry(gh, &gl->gl_waiters1, gh_list) {
-               error = dump_holder("Waiter1", gh);
-               if (error)
-                       goto out;
-       }
-       list_for_each_entry(gh, &gl->gl_waiters2, gh_list) {
-               error = dump_holder("Waiter2", gh);
+               error = dump_holder(gi, "Waiter1", gh);
                if (error)
                        goto out;
        }
        list_for_each_entry(gh, &gl->gl_waiters3, gh_list) {
-               error = dump_holder("Waiter3", gh);
+               error = dump_holder(gi, "Waiter3", gh);
                if (error)
                        goto out;
        }
+       if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
+               print_dbg(gi, "  Demotion req to state %u (%llu uS ago)\n",
+                         gl->gl_demote_state,
+                         (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ));
+       }
        if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) {
                if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
-                   list_empty(&gl->gl_holders)) {
-                       error = dump_inode(gl->gl_object);
+                       list_empty(&gl->gl_holders)) {
+                       error = dump_inode(gi, gl->gl_object);
                        if (error)
                                goto out;
                } else {
                        error = -ENOBUFS;
-                       printk(KERN_INFO "  Inode: busy\n");
+                       print_dbg(gi, "  Inode: busy\n");
                }
        }
 
@@ -2014,7 +1955,7 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
                        if (gl->gl_sbd != sdp)
                                continue;
 
-                       error = dump_glock(gl);
+                       error = dump_glock(NULL, gl);
                        if (error)
                                break;
                }
@@ -2043,3 +1984,189 @@ int __init gfs2_glock_init(void)
        return 0;
 }
 
+static int gfs2_glock_iter_next(struct glock_iter *gi)
+{
+       read_lock(gl_lock_addr(gi->hash));
+       while (1) {
+               if (!gi->hb_list) {  /* If we don't have a hash bucket yet */
+                       gi->hb_list = &gl_hash_table[gi->hash].hb_list;
+                       if (hlist_empty(gi->hb_list)) {
+                               read_unlock(gl_lock_addr(gi->hash));
+                               gi->hash++;
+                               read_lock(gl_lock_addr(gi->hash));
+                               gi->hb_list = NULL;
+                               if (gi->hash >= GFS2_GL_HASH_SIZE) {
+                                       read_unlock(gl_lock_addr(gi->hash));
+                                       return 1;
+                               }
+                               else
+                                       continue;
+                       }
+                       if (!hlist_empty(gi->hb_list)) {
+                               gi->gl = list_entry(gi->hb_list->first,
+                                                   struct gfs2_glock,
+                                                   gl_list);
+                       }
+               } else {
+                       if (gi->gl->gl_list.next == NULL) {
+                               read_unlock(gl_lock_addr(gi->hash));
+                               gi->hash++;
+                               read_lock(gl_lock_addr(gi->hash));
+                               gi->hb_list = NULL;
+                               continue;
+                       }
+                       gi->gl = list_entry(gi->gl->gl_list.next,
+                                           struct gfs2_glock, gl_list);
+               }
+               if (gi->gl)
+                       break;
+       }
+       read_unlock(gl_lock_addr(gi->hash));
+       return 0;
+}
+
+static void gfs2_glock_iter_free(struct glock_iter *gi)
+{
+       kfree(gi);
+}
+
+static struct glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp)
+{
+       struct glock_iter *gi;
+
+       gi = kmalloc(sizeof (*gi), GFP_KERNEL);
+       if (!gi)
+               return NULL;
+
+       gi->sdp = sdp;
+       gi->hash = 0;
+       gi->gl = NULL;
+       gi->hb_list = NULL;
+       gi->seq = NULL;
+       memset(gi->string, 0, sizeof(gi->string));
+
+       if (gfs2_glock_iter_next(gi)) {
+               gfs2_glock_iter_free(gi);
+               return NULL;
+       }
+
+       return gi;
+}
+
+static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos)
+{
+       struct glock_iter *gi;
+       loff_t n = *pos;
+
+       gi = gfs2_glock_iter_init(file->private);
+       if (!gi)
+               return NULL;
+
+       while (n--) {
+               if (gfs2_glock_iter_next(gi)) {
+                       gfs2_glock_iter_free(gi);
+                       return NULL;
+               }
+       }
+
+       return gi;
+}
+
+static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr,
+                                loff_t *pos)
+{
+       struct glock_iter *gi = iter_ptr;
+
+       (*pos)++;
+
+       if (gfs2_glock_iter_next(gi)) {
+               gfs2_glock_iter_free(gi);
+               return NULL;
+       }
+
+       return gi;
+}
+
+static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr)
+{
+       /* nothing for now */
+}
+
+static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr)
+{
+       struct glock_iter *gi = iter_ptr;
+
+       gi->seq = file;
+       dump_glock(gi, gi->gl);
+
+       return 0;
+}
+
+static struct seq_operations gfs2_glock_seq_ops = {
+       .start = gfs2_glock_seq_start,
+       .next  = gfs2_glock_seq_next,
+       .stop  = gfs2_glock_seq_stop,
+       .show  = gfs2_glock_seq_show,
+};
+
+static int gfs2_debugfs_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq;
+       int ret;
+
+       ret = seq_open(file, &gfs2_glock_seq_ops);
+       if (ret)
+               return ret;
+
+       seq = file->private_data;
+       seq->private = inode->i_private;
+
+       return 0;
+}
+
+static const struct file_operations gfs2_debug_fops = {
+       .owner   = THIS_MODULE,
+       .open    = gfs2_debugfs_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+int gfs2_create_debugfs_file(struct gfs2_sbd *sdp)
+{
+       sdp->debugfs_dir = debugfs_create_dir(sdp->sd_table_name, gfs2_root);
+       if (!sdp->debugfs_dir)
+               return -ENOMEM;
+       sdp->debugfs_dentry_glocks = debugfs_create_file("glocks",
+                                                        S_IFREG | S_IRUGO,
+                                                        sdp->debugfs_dir, sdp,
+                                                        &gfs2_debug_fops);
+       if (!sdp->debugfs_dentry_glocks)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp)
+{
+       if (sdp && sdp->debugfs_dir) {
+               if (sdp->debugfs_dentry_glocks) {
+                       debugfs_remove(sdp->debugfs_dentry_glocks);
+                       sdp->debugfs_dentry_glocks = NULL;
+               }
+               debugfs_remove(sdp->debugfs_dir);
+               sdp->debugfs_dir = NULL;
+       }
+}
+
+int gfs2_register_debugfs(void)
+{
+       gfs2_root = debugfs_create_dir("gfs2", NULL);
+       return gfs2_root ? 0 : -ENOMEM;
+}
+
+void gfs2_unregister_debugfs(void)
+{
+       debugfs_remove(gfs2_root);
+       gfs2_root = NULL;
+}
index f50e40c..11477ca 100644 (file)
@@ -38,7 +38,7 @@ static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
        /* Look in glock's list of holders for one with current task as owner */
        spin_lock(&gl->gl_spin);
        list_for_each_entry(gh, &gl->gl_holders, gh_list) {
-               if (gh->gh_owner == current) {
+               if (gh->gh_owner_pid == current->pid) {
                        locked = 1;
                        break;
                }
@@ -67,7 +67,7 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
 {
        int ret;
        spin_lock(&gl->gl_spin);
-       ret = !list_empty(&gl->gl_waiters2) || !list_empty(&gl->gl_waiters3);
+       ret = test_bit(GLF_DEMOTE, &gl->gl_flags) || !list_empty(&gl->gl_waiters3);
        spin_unlock(&gl->gl_spin);
        return ret;
 }
@@ -135,5 +135,9 @@ void gfs2_scand_internal(struct gfs2_sbd *sdp);
 void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait);
 
 int __init gfs2_glock_init(void);
+int gfs2_create_debugfs_file(struct gfs2_sbd *sdp);
+void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
+int gfs2_register_debugfs(void);
+void gfs2_unregister_debugfs(void);
 
 #endif /* __GLOCK_DOT_H__ */
index 49f0dbf..d995441 100644 (file)
@@ -115,11 +115,8 @@ enum {
        /* Actions */
        HIF_MUTEX               = 0,
        HIF_PROMOTE             = 1,
-       HIF_DEMOTE              = 2,
 
        /* States */
-       HIF_ALLOCED             = 4,
-       HIF_DEALLOC             = 5,
        HIF_HOLDER              = 6,
        HIF_FIRST               = 7,
        HIF_ABORTED             = 9,
@@ -130,7 +127,7 @@ struct gfs2_holder {
        struct list_head gh_list;
 
        struct gfs2_glock *gh_gl;
-       struct task_struct *gh_owner;
+       pid_t gh_owner_pid;
        unsigned int gh_state;
        unsigned gh_flags;
 
@@ -142,8 +139,8 @@ struct gfs2_holder {
 enum {
        GLF_LOCK                = 1,
        GLF_STICKY              = 2,
+       GLF_DEMOTE              = 3,
        GLF_DIRTY               = 5,
-       GLF_SKIP_WAITERS2       = 6,
 };
 
 struct gfs2_glock {
@@ -156,11 +153,12 @@ struct gfs2_glock {
 
        unsigned int gl_state;
        unsigned int gl_hash;
-       struct task_struct *gl_owner;
+       unsigned int gl_demote_state; /* state requested by remote node */
+       unsigned long gl_demote_time; /* time of first demote request */
+       pid_t gl_owner_pid;
        unsigned long gl_ip;
        struct list_head gl_holders;
        struct list_head gl_waiters1;   /* HIF_MUTEX */
-       struct list_head gl_waiters2;   /* HIF_DEMOTE */
        struct list_head gl_waiters3;   /* HIF_PROMOTE */
 
        const struct gfs2_glock_operations *gl_ops;
@@ -611,6 +609,8 @@ struct gfs2_sbd {
 
        unsigned long sd_last_warning;
        struct vfsmount *sd_gfs2mnt;
+       struct dentry *debugfs_dir;    /* debugfs directory */
+       struct dentry *debugfs_dentry_glocks; /* for debugfs */
 };
 
 #endif /* __INCORE_DOT_H__ */
index b167add..c305255 100644 (file)
@@ -151,7 +151,7 @@ static inline unsigned int make_flags(struct gdlm_lock *lp,
 
 /* make_strname - convert GFS lock numbers to a string */
 
-static inline void make_strname(struct lm_lockname *lockname,
+static inline void make_strname(const struct lm_lockname *lockname,
                                struct gdlm_strname *str)
 {
        sprintf(str->name, "%8x%16llx", lockname->ln_type,
@@ -169,6 +169,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
                return -ENOMEM;
 
        lp->lockname = *name;
+       make_strname(name, &lp->strname);
        lp->ls = ls;
        lp->cur = DLM_LOCK_IV;
        lp->lvb = NULL;
@@ -227,7 +228,6 @@ void gdlm_put_lock(void *lock)
 unsigned int gdlm_do_lock(struct gdlm_lock *lp)
 {
        struct gdlm_ls *ls = lp->ls;
-       struct gdlm_strname str;
        int error, bast = 1;
 
        /*
@@ -249,8 +249,6 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp)
        if (test_bit(LFL_NOBAST, &lp->flags))
                bast = 0;
 
-       make_strname(&lp->lockname, &str);
-
        set_bit(LFL_ACTIVE, &lp->flags);
 
        log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type,
@@ -258,8 +256,8 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp)
                  lp->cur, lp->req, lp->lkf);
 
        error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf,
-                        str.name, str.namelen, 0, gdlm_ast, lp,
-                        bast ? gdlm_bast : NULL);
+                        lp->strname.name, lp->strname.namelen, 0, gdlm_ast,
+                        lp, bast ? gdlm_bast : NULL);
 
        if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) {
                lp->lksb.sb_status = -EAGAIN;
@@ -268,7 +266,7 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp)
        }
 
        if (error) {
-               log_debug("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x "
+               log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x "
                          "flags=%lx", ls->fsname, lp->lockname.ln_type,
                          (unsigned long long)lp->lockname.ln_number, error,
                          lp->cur, lp->req, lp->lkf, lp->flags);
@@ -296,7 +294,7 @@ static unsigned int gdlm_do_unlock(struct gdlm_lock *lp)
        error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp);
 
        if (error) {
-               log_debug("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x "
+               log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x "
                          "flags=%lx", ls->fsname, lp->lockname.ln_type,
                          (unsigned long long)lp->lockname.ln_number, error,
                          lp->cur, lp->req, lp->lkf, lp->flags);
index a87c7bf..d074c6e 100644 (file)
@@ -36,7 +36,7 @@
 
 #define GDLM_STRNAME_BYTES     24
 #define GDLM_LVB_SIZE          32
-#define GDLM_DROP_COUNT                200000
+#define GDLM_DROP_COUNT                0
 #define GDLM_DROP_PERIOD       60
 #define GDLM_NAME_LEN          128
 
@@ -106,6 +106,7 @@ enum {
 struct gdlm_lock {
        struct gdlm_ls          *ls;
        struct lm_lockname      lockname;
+       struct gdlm_strname     strname;
        char                    *lvb;
        struct dlm_lksb         lksb;
 
index 1dd4215..f82495e 100644 (file)
@@ -25,6 +25,15 @@ struct plock_op {
        struct gdlm_plock_info info;
 };
 
+struct plock_xop {
+       struct plock_op xop;
+       void *callback;
+       void *fl;
+       void *file;
+       struct file_lock flc;
+};
+
+
 static inline void set_version(struct gdlm_plock_info *info)
 {
        info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
@@ -64,12 +73,14 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
 {
        struct gdlm_ls *ls = lockspace;
        struct plock_op *op;
+       struct plock_xop *xop;
        int rv;
 
-       op = kzalloc(sizeof(*op), GFP_KERNEL);
-       if (!op)
+       xop = kzalloc(sizeof(*xop), GFP_KERNEL);
+       if (!xop)
                return -ENOMEM;
 
+       op = &xop->xop;
        op->info.optype         = GDLM_PLOCK_OP_LOCK;
        op->info.pid            = fl->fl_pid;
        op->info.ex             = (fl->fl_type == F_WRLCK);
@@ -79,9 +90,21 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
        op->info.start          = fl->fl_start;
        op->info.end            = fl->fl_end;
        op->info.owner          = (__u64)(long) fl->fl_owner;
+       if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+               xop->callback   = fl->fl_lmops->fl_grant;
+               locks_init_lock(&xop->flc);
+               locks_copy_lock(&xop->flc, fl);
+               xop->fl         = fl;
+               xop->file       = file;
+       } else
+               xop->callback   = NULL;
 
        send_op(op);
-       wait_event(recv_wq, (op->done != 0));
+
+       if (xop->callback == NULL)
+               wait_event(recv_wq, (op->done != 0));
+       else
+               return -EINPROGRESS;
 
        spin_lock(&ops_lock);
        if (!list_empty(&op->list)) {
@@ -99,7 +122,63 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
                                  (unsigned long long)name->ln_number);
        }
 
-       kfree(op);
+       kfree(xop);
+       return rv;
+}
+
+/* Returns failure iff a succesful lock operation should be canceled */
+static int gdlm_plock_callback(struct plock_op *op)
+{
+       struct file *file;
+       struct file_lock *fl;
+       struct file_lock *flc;
+       int (*notify)(void *, void *, int) = NULL;
+       struct plock_xop *xop = (struct plock_xop *)op;
+       int rv = 0;
+
+       spin_lock(&ops_lock);
+       if (!list_empty(&op->list)) {
+               printk(KERN_INFO "plock op on list\n");
+               list_del(&op->list);
+       }
+       spin_unlock(&ops_lock);
+
+       /* check if the following 2 are still valid or make a copy */
+       file = xop->file;
+       flc = &xop->flc;
+       fl = xop->fl;
+       notify = xop->callback;
+
+       if (op->info.rv) {
+               notify(flc, NULL, op->info.rv);
+               goto out;
+       }
+
+       /* got fs lock; bookkeep locally as well: */
+       flc->fl_flags &= ~FL_SLEEP;
+       if (posix_lock_file(file, flc, NULL)) {
+               /*
+                * This can only happen in the case of kmalloc() failure.
+                * The filesystem's own lock is the authoritative lock,
+                * so a failure to get the lock locally is not a disaster.
+                * As long as GFS cannot reliably cancel locks (especially
+                * in a low-memory situation), we're better off ignoring
+                * this failure than trying to recover.
+                */
+               log_error("gdlm_plock: vfs lock error file %p fl %p",
+                               file, fl);
+       }
+
+       rv = notify(flc, NULL, 0);
+       if (rv) {
+               /* XXX: We need to cancel the fs lock here: */
+               printk("gfs2 lock granted after lock request failed;"
+                                               " dangling lock!\n");
+               goto out;
+       }
+
+out:
+       kfree(xop);
        return rv;
 }
 
@@ -138,6 +217,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,
 
        rv = op->info.rv;
 
+       if (rv == -ENOENT)
+               rv = 0;
+
        kfree(op);
        return rv;
 }
@@ -161,6 +243,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
        op->info.start          = fl->fl_start;
        op->info.end            = fl->fl_end;
 
+
        send_op(op);
        wait_event(recv_wq, (op->done != 0));
 
@@ -173,9 +256,10 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
 
        rv = op->info.rv;
 
-       if (rv == 0)
-               fl->fl_type = F_UNLCK;
-       else if (rv > 0) {
+       fl->fl_type = F_UNLCK;
+       if (rv == -ENOENT)
+               rv = 0;
+       else if (rv == 0 && op->info.pid != fl->fl_pid) {
                fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
                fl->fl_pid = op->info.pid;
                fl->fl_start = op->info.start;
@@ -243,9 +327,14 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
        }
        spin_unlock(&ops_lock);
 
-       if (found)
-               wake_up(&recv_wq);
-       else
+       if (found) {
+               struct plock_xop *xop;
+               xop = (struct plock_xop *)op;
+               if (xop->callback)
+                       count = gdlm_plock_callback(op);
+               else
+                       wake_up(&recv_wq);
+       } else
                printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid,
                        (unsigned long long)info.number);
        return count;
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 acfbc94..5cc1dfa 100644 (file)
@@ -164,13 +164,7 @@ static void nolock_unhold_lvb(void *lock, char *lvb)
 static int nolock_plock_get(void *lockspace, struct lm_lockname *name,
                            struct file *file, struct file_lock *fl)
 {
-       struct file_lock tmp;
-       int ret;
-
-       ret = posix_test_lock(file, fl, &tmp);
-       fl->fl_type = F_UNLCK;
-       if (ret)
-               memcpy(fl, &tmp, sizeof(struct file_lock));
+       posix_test_lock(file, fl);
 
        return 0;
 }
index 16bb4b4..f82d84d 100644 (file)
@@ -33,16 +33,17 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
 
        tr->tr_touched = 1;
 
-       if (!list_empty(&le->le_list))
-               return;
-
        gl = container_of(le, struct gfs2_glock, gl_le);
        if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl)))
                return;
-       gfs2_glock_hold(gl);
-       set_bit(GLF_DIRTY, &gl->gl_flags);
 
        gfs2_log_lock(sdp);
+       if (!list_empty(&le->le_list)){
+               gfs2_log_unlock(sdp);
+               return;
+       }
+       gfs2_glock_hold(gl);
+       set_bit(GLF_DIRTY, &gl->gl_flags);
        sdp->sd_log_num_gl++;
        list_add(&le->le_list, &sdp->sd_log_le_gl);
        gfs2_log_unlock(sdp);
@@ -415,13 +416,14 @@ static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
 
        tr->tr_touched = 1;
 
-       if (!list_empty(&le->le_list))
-               return;
-
        rgd = container_of(le, struct gfs2_rgrpd, rd_le);
-       gfs2_rgrp_bh_hold(rgd);
 
        gfs2_log_lock(sdp);
+       if (!list_empty(&le->le_list)){
+               gfs2_log_unlock(sdp);
+               return;
+       }
+       gfs2_rgrp_bh_hold(rgd);
        sdp->sd_log_num_rg++;
        list_add(&le->le_list, &sdp->sd_log_le_rg);
        gfs2_log_unlock(sdp);
index 6e8a598..e460487 100644 (file)
@@ -27,8 +27,7 @@
 static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct gfs2_inode *ip = foo;
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&ip->i_inode);
                spin_lock_init(&ip->i_spin);
                init_rwsem(&ip->i_rw_mutex);
@@ -39,13 +38,11 @@ static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned
 static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct gfs2_glock *gl = foo;
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                INIT_HLIST_NODE(&gl->gl_list);
                spin_lock_init(&gl->gl_spin);
                INIT_LIST_HEAD(&gl->gl_holders);
                INIT_LIST_HEAD(&gl->gl_waiters1);
-               INIT_LIST_HEAD(&gl->gl_waiters2);
                INIT_LIST_HEAD(&gl->gl_waiters3);
                gl->gl_lvb = NULL;
                atomic_set(&gl->gl_lvb_count, 0);
@@ -103,6 +100,8 @@ static int __init init_gfs2_fs(void)
        if (error)
                goto fail_unregister;
 
+       gfs2_register_debugfs();
+
        printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__);
 
        return 0;
@@ -130,6 +129,7 @@ fail:
 
 static void __exit exit_gfs2_fs(void)
 {
+       gfs2_unregister_debugfs();
        unregister_filesystem(&gfs2_fs_type);
        unregister_filesystem(&gfs2meta_fs_type);
 
index 32caecd..4864659 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
+#include <linux/parser.h>
 
 #include "gfs2.h"
 #include "incore.h"
 #include "sys.h"
 #include "util.h"
 
+enum {
+       Opt_lockproto,
+       Opt_locktable,
+       Opt_hostdata,
+       Opt_spectator,
+       Opt_ignore_local_fs,
+       Opt_localflocks,
+       Opt_localcaching,
+       Opt_debug,
+       Opt_nodebug,
+       Opt_upgrade,
+       Opt_num_glockd,
+       Opt_acl,
+       Opt_noacl,
+       Opt_quota_off,
+       Opt_quota_account,
+       Opt_quota_on,
+       Opt_suiddir,
+       Opt_nosuiddir,
+       Opt_data_writeback,
+       Opt_data_ordered,
+};
+
+static match_table_t tokens = {
+       {Opt_lockproto, "lockproto=%s"},
+       {Opt_locktable, "locktable=%s"},
+       {Opt_hostdata, "hostdata=%s"},
+       {Opt_spectator, "spectator"},
+       {Opt_ignore_local_fs, "ignore_local_fs"},
+       {Opt_localflocks, "localflocks"},
+       {Opt_localcaching, "localcaching"},
+       {Opt_debug, "debug"},
+       {Opt_nodebug, "nodebug"},
+       {Opt_upgrade, "upgrade"},
+       {Opt_num_glockd, "num_glockd=%d"},
+       {Opt_acl, "acl"},
+       {Opt_noacl, "noacl"},
+       {Opt_quota_off, "quota=off"},
+       {Opt_quota_account, "quota=account"},
+       {Opt_quota_on, "quota=on"},
+       {Opt_suiddir, "suiddir"},
+       {Opt_nosuiddir, "nosuiddir"},
+       {Opt_data_writeback, "data=writeback"},
+       {Opt_data_ordered, "data=ordered"}
+};
+
 /**
  * gfs2_mount_args - Parse mount options
  * @sdp:
@@ -54,146 +101,150 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
           process them */
 
        for (options = data; (o = strsep(&options, ",")); ) {
+               int token, option;
+               substring_t tmp[MAX_OPT_ARGS];
+
                if (!*o)
                        continue;
 
-               v = strchr(o, '=');
-               if (v)
-                       *v++ = 0;
+               token = match_token(o, tokens, tmp);
+               switch (token) {
+               case Opt_lockproto:
+                       v = match_strdup(&tmp[0]);
+                       if (!v) {
+                               fs_info(sdp, "no memory for lockproto\n");
+                               error = -ENOMEM;
+                               goto out_error;
+                       }
 
-               if (!strcmp(o, "lockproto")) {
-                       if (!v)
-                               goto need_value;
-                       if (remount && strcmp(v, args->ar_lockproto))
+                       if (remount && strcmp(v, args->ar_lockproto)) {
+                               kfree(v);
                                goto cant_remount;
+                       }
+                       
                        strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN);
                        args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0;
-               }
+                       kfree(v);
+                       break;
+               case Opt_locktable:
+                       v = match_strdup(&tmp[0]);
+                       if (!v) {
+                               fs_info(sdp, "no memory for locktable\n");
+                               error = -ENOMEM;
+                               goto out_error;
+                       }
 
-               else if (!strcmp(o, "locktable")) {
-                       if (!v)
-                               goto need_value;
-                       if (remount && strcmp(v, args->ar_locktable))
+                       if (remount && strcmp(v, args->ar_locktable)) {
+                               kfree(v);
                                goto cant_remount;
+                       }
+
                        strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN);
-                       args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0;
-               }
+                       args->ar_locktable[GFS2_LOCKNAME_LEN - 1]  = 0;
+                       kfree(v);
+                       break;
+               case Opt_hostdata:
+                       v = match_strdup(&tmp[0]);
+                       if (!v) {
+                               fs_info(sdp, "no memory for hostdata\n");
+                               error = -ENOMEM;
+                               goto out_error;
+                       }
 
-               else if (!strcmp(o, "hostdata")) {
-                       if (!v)
-                               goto need_value;
-                       if (remount && strcmp(v, args->ar_hostdata))
+                       if (remount && strcmp(v, args->ar_hostdata)) {
+                               kfree(v);
                                goto cant_remount;
+                       }
+
                        strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN);
                        args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0;
-               }
-
-               else if (!strcmp(o, "spectator")) {
+                       kfree(v);
+                       break;
+               case Opt_spectator:
                        if (remount && !args->ar_spectator)
                                goto cant_remount;
                        args->ar_spectator = 1;
                        sdp->sd_vfs->s_flags |= MS_RDONLY;
-               }
-
-               else if (!strcmp(o, "ignore_local_fs")) {
+                       break;
+               case Opt_ignore_local_fs:
                        if (remount && !args->ar_ignore_local_fs)
                                goto cant_remount;
                        args->ar_ignore_local_fs = 1;
-               }
-
-               else if (!strcmp(o, "localflocks")) {
+                       break;
+               case Opt_localflocks:
                        if (remount && !args->ar_localflocks)
                                goto cant_remount;
                        args->ar_localflocks = 1;
-               }
-
-               else if (!strcmp(o, "localcaching")) {
+                       break;
+               case Opt_localcaching:
                        if (remount && !args->ar_localcaching)
                                goto cant_remount;
                        args->ar_localcaching = 1;
-               }
-
-               else if (!strcmp(o, "debug"))
+                       break;
+               case Opt_debug:
                        args->ar_debug = 1;
-
-               else if (!strcmp(o, "nodebug"))
+                       break;
+               case Opt_nodebug:
                        args->ar_debug = 0;
-
-               else if (!strcmp(o, "upgrade")) {
+                       break;
+               case Opt_upgrade:
                        if (remount && !args->ar_upgrade)
                                goto cant_remount;
                        args->ar_upgrade = 1;
-               }
+                       break;
+               case Opt_num_glockd:
+                       if ((error = match_int(&tmp[0], &option))) {
+                               fs_info(sdp, "problem getting num_glockd\n");
+                               goto out_error;
+                       }
 
-               else if (!strcmp(o, "num_glockd")) {
-                       unsigned int x;
-                       if (!v)
-                               goto need_value;
-                       sscanf(v, "%u", &x);
-                       if (remount && x != args->ar_num_glockd)
+                       if (remount && option != args->ar_num_glockd)
                                goto cant_remount;
-                       if (!x || x > GFS2_GLOCKD_MAX) {
+                       if (!option || option > GFS2_GLOCKD_MAX) {
                                fs_info(sdp, "0 < num_glockd <= %u  (not %u)\n",
-                                       GFS2_GLOCKD_MAX, x);
+                                       GFS2_GLOCKD_MAX, option);
                                error = -EINVAL;
-                               break;
+                               goto out_error;
                        }
-                       args->ar_num_glockd = x;
-               }
-
-               else if (!strcmp(o, "acl")) {
+                       args->ar_num_glockd = option;
+                       break;
+               case Opt_acl:
                        args->ar_posix_acl = 1;
                        sdp->sd_vfs->s_flags |= MS_POSIXACL;
-               }
-
-               else if (!strcmp(o, "noacl")) {
+                       break;
+               case Opt_noacl:
                        args->ar_posix_acl = 0;
                        sdp->sd_vfs->s_flags &= ~MS_POSIXACL;
-               }
-
-               else if (!strcmp(o, "quota")) {
-                       if (!v)
-                               goto need_value;
-                       if (!strcmp(v, "off"))
-                               args->ar_quota = GFS2_QUOTA_OFF;
-                       else if (!strcmp(v, "account"))
-                               args->ar_quota = GFS2_QUOTA_ACCOUNT;
-                       else if (!strcmp(v, "on"))
-                               args->ar_quota = GFS2_QUOTA_ON;
-                       else {
-                               fs_info(sdp, "invalid value for quota\n");
-                               error = -EINVAL;
-                               break;
-                       }
-               }
-
-               else if (!strcmp(o, "suiddir"))
+                       break;
+               case Opt_quota_off:
+                       args->ar_quota = GFS2_QUOTA_OFF;
+                       break;
+               case Opt_quota_account:
+                       args->ar_quota = GFS2_QUOTA_ACCOUNT;
+                       break;
+               case Opt_quota_on:
+                       args->ar_quota = GFS2_QUOTA_ON;
+                       break;
+               case Opt_suiddir:
                        args->ar_suiddir = 1;
-
-               else if (!strcmp(o, "nosuiddir"))
+                       break;
+               case Opt_nosuiddir:
                        args->ar_suiddir = 0;
-
-               else if (!strcmp(o, "data")) {
-                       if (!v)
-                               goto need_value;
-                       if (!strcmp(v, "writeback"))
-                               args->ar_data = GFS2_DATA_WRITEBACK;
-                       else if (!strcmp(v, "ordered"))
-                               args->ar_data = GFS2_DATA_ORDERED;
-                       else {
-                               fs_info(sdp, "invalid value for data\n");
-                               error = -EINVAL;
-                               break;
-                       }
-               }
-
-               else {
+                       break;
+               case Opt_data_writeback:
+                       args->ar_data = GFS2_DATA_WRITEBACK;
+                       break;
+               case Opt_data_ordered:
+                       args->ar_data = GFS2_DATA_ORDERED;
+                       break;
+               default:
                        fs_info(sdp, "unknown option: %s\n", o);
                        error = -EINVAL;
-                       break;
+                       goto out_error;
                }
        }
 
+out_error:
        if (error)
                fs_info(sdp, "invalid mount option(s)\n");
 
@@ -202,10 +253,6 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
 
        return error;
 
-need_value:
-       fs_info(sdp, "need value for option %s\n", o);
-       return -EINVAL;
-
 cant_remount:
        fs_info(sdp, "can't remount with option %s\n", o);
        return -EINVAL;
index b3b7e84..30c1562 100644 (file)
@@ -197,7 +197,19 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
        void *kaddr;
        int error;
 
-       BUG_ON(page->index);
+       /*
+        * Due to the order of unstuffing files and ->nopage(), we can be
+        * asked for a zero page in the case of a stuffed file being extended,
+        * so we need to supply one here. It doesn't happen often.
+        */
+       if (unlikely(page->index)) {
+               kaddr = kmap_atomic(page, KM_USER0);
+               memset(kaddr, 0, PAGE_CACHE_SIZE);
+               kunmap_atomic(kaddr, KM_USER0);
+               flush_dcache_page(page);
+               SetPageUptodate(page);
+               return 0;
+       }
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
@@ -208,9 +220,8 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
               ip->i_di.di_size);
        memset(kaddr + ip->i_di.di_size, 0, PAGE_CACHE_SIZE - ip->i_di.di_size);
        kunmap_atomic(kaddr, KM_USER0);
-
+       flush_dcache_page(page);
        brelse(dibh);
-
        SetPageUptodate(page);
 
        return 0;
@@ -507,7 +518,9 @@ static int gfs2_commit_write(struct file *file, struct page *page,
                gfs2_quota_unlock(ip);
                gfs2_alloc_put(ip);
        }
+       unlock_page(page);
        gfs2_glock_dq_m(1, &ip->i_gh);
+       lock_page(page);
        gfs2_holder_uninit(&ip->i_gh);
        return 0;
 
@@ -520,7 +533,9 @@ fail_endtrans:
                gfs2_quota_unlock(ip);
                gfs2_alloc_put(ip);
        }
+       unlock_page(page);
        gfs2_glock_dq_m(1, &ip->i_gh);
+       lock_page(page);
        gfs2_holder_uninit(&ip->i_gh);
 fail_nounlock:
        ClearPageUptodate(page);
index b50180e..329c4dc 100644 (file)
@@ -513,18 +513,18 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
 
        if (sdp->sd_args.ar_localflocks) {
                if (IS_GETLK(cmd)) {
-                       struct file_lock tmp;
-                       int ret;
-                       ret = posix_test_lock(file, fl, &tmp);
-                       fl->fl_type = F_UNLCK;
-                       if (ret)
-                               memcpy(fl, &tmp, sizeof(struct file_lock));
+                       posix_test_lock(file, fl);
                        return 0;
                } else {
                        return posix_lock_file_wait(file, fl);
                }
        }
 
+       if (cmd == F_CANCELLK) {
+               /* Hack: */
+               cmd = F_SETLK;
+               fl->fl_type = F_UNLCK;
+       }
        if (IS_GETLK(cmd))
                return gfs2_lm_plock_get(sdp, &name, file, fl);
        else if (fl->fl_type == F_UNLCK)
index ee54cb6..2c5f8e7 100644 (file)
@@ -690,6 +690,8 @@ static int fill_super(struct super_block *sb, void *data, int silent)
        if (error)
                goto fail;
 
+       gfs2_create_debugfs_file(sdp);
+
        error = gfs2_sys_fs_add(sdp);
        if (error)
                goto fail;
@@ -754,6 +756,7 @@ fail_lm:
 fail_sys:
        gfs2_sys_fs_del(sdp);
 fail:
+       gfs2_delete_debugfs_file(sdp);
        kfree(sdp);
        sb->s_fs_info = NULL;
        return error;
@@ -896,6 +899,7 @@ error:
 
 static void gfs2_kill_sb(struct super_block *sb)
 {
+       gfs2_delete_debugfs_file(sb->s_fs_info);
        kill_block_super(sb);
 }
 
index b89999d..485ce3d 100644 (file)
@@ -283,6 +283,31 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
        return error;
 }
 
+/**
+ * gfs2_drop_inode - Drop an inode (test for remote unlink)
+ * @inode: The inode to drop
+ *
+ * If we've received a callback on an iopen lock then its because a
+ * remote node tried to deallocate the inode but failed due to this node
+ * still having the inode open. Here we mark the link count zero
+ * since we know that it must have reached zero if the GLF_DEMOTE flag
+ * is set on the iopen glock. If we didn't do a disk read since the
+ * remote node removed the final link then we might otherwise miss
+ * this event. This check ensures that this node will deallocate the
+ * inode's blocks, or alternatively pass the baton on to another
+ * node for later deallocation.
+ */
+static void gfs2_drop_inode(struct inode *inode)
+{
+       if (inode->i_private && inode->i_nlink) {
+               struct gfs2_inode *ip = GFS2_I(inode);
+               struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
+               if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
+                       clear_nlink(inode);
+       }
+       generic_drop_inode(inode);
+}
+
 /**
  * gfs2_clear_inode - Deallocate an inode when VFS is done with it
  * @inode: The VFS inode
@@ -441,7 +466,7 @@ out_unlock:
 out_uninit:
        gfs2_holder_uninit(&ip->i_iopen_gh);
        gfs2_glock_dq_uninit(&gh);
-       if (error)
+       if (error && error != GLR_TRYFAILED)
                fs_warn(sdp, "gfs2_delete_inode: %d\n", error);
 out:
        truncate_inode_pages(&inode->i_data, 0);
@@ -481,6 +506,7 @@ const struct super_operations gfs2_super_ops = {
        .statfs                 = gfs2_statfs,
        .remount_fs             = gfs2_remount_fs,
        .clear_inode            = gfs2_clear_inode,
+       .drop_inode             = gfs2_drop_inode,
        .show_options           = gfs2_show_options,
 };
 
index 8d9c08b..1727f50 100644 (file)
@@ -27,6 +27,7 @@
 #include "trans.h"
 #include "ops_file.h"
 #include "util.h"
+#include "log.h"
 
 #define BFITNOENT ((u32)~0)
 
@@ -697,8 +698,6 @@ struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip)
  * @al: the struct gfs2_alloc structure describing the reservation
  *
  * If there's room for the requested blocks to be allocated from the RG:
- *   Sets the $al_reserved_data field in @al.
- *   Sets the $al_reserved_meta field in @al.
  *   Sets the $al_rgd field in @al.
  *
  * Returns: 1 on success (it fits), 0 on failure (it doesn't fit)
@@ -709,6 +708,9 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
        struct gfs2_sbd *sdp = rgd->rd_sbd;
        int ret = 0;
 
+       if (rgd->rd_rg.rg_flags & GFS2_RGF_NOALLOC)
+               return 0;
+
        spin_lock(&sdp->sd_rindex_spin);
        if (rgd->rd_free_clone >= al->al_requested) {
                al->al_rgd = rgd;
@@ -941,9 +943,13 @@ static int get_local_rgrp(struct gfs2_inode *ip)
                        rgd = gfs2_rgrpd_get_first(sdp);
 
                if (rgd == begin) {
-                       if (++loops >= 2 || !skipped)
+                       if (++loops >= 3)
                                return -ENOSPC;
+                       if (!skipped)
+                               loops++;
                        flags = 0;
+                       if (loops == 2)
+                               gfs2_log_flush(sdp, NULL);
                }
        }
 
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 623f509..4f1888f 100644 (file)
@@ -434,7 +434,7 @@ static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flag
 {
        struct hfs_inode_info *i = p;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&i->vfs_inode);
 }
 
index 1a97f92..37afbec 100644 (file)
@@ -470,7 +470,7 @@ static void hfsplus_init_once(void *p, struct kmem_cache *cachep, unsigned long
 {
        struct hfsplus_inode_info *i = p;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&i->vfs_inode);
 }
 
index e0174e3..1b95f39 100644 (file)
@@ -176,8 +176,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                mutex_init(&ei->i_mutex);
                mutex_init(&ei->i_parent_mutex);
                inode_init_once(&ei->vfs_inode);
index 8c718a3..98959b8 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/backing-dev.h>
 #include <linux/hugetlb.h>
 #include <linux/pagevec.h>
+#include <linux/mman.h>
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/dnotify.h>
@@ -98,10 +99,7 @@ out:
  * Called under down_write(mmap_sem).
  */
 
-#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
-               unsigned long len, unsigned long pgoff, unsigned long flags);
-#else
+#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 static unsigned long
 hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -115,6 +113,12 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       if (flags & MAP_FIXED) {
+               if (prepare_hugepage_range(addr, len, pgoff))
+                       return -EINVAL;
+               return addr;
+       }
+
        if (addr) {
                addr = ALIGN(addr, HPAGE_SIZE);
                vma = find_vma(mm, addr);
@@ -453,7 +457,7 @@ static int hugetlbfs_symlink(struct inode *dir,
  */
 static int hugetlbfs_set_page_dirty(struct page *page)
 {
-       struct page *head = (struct page *)page_private(page);
+       struct page *head = compound_head(page);
 
        SetPageDirty(head);
        return 0;
@@ -552,8 +556,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
 
@@ -744,6 +747,9 @@ struct file *hugetlb_zero_setup(size_t size)
        char buf[16];
        static atomic_t counter;
 
+       if (!hugetlbfs_vfsmount)
+               return ERR_PTR(-ENOENT);
+
        if (!can_do_hugetlb_shm())
                return ERR_PTR(-EPERM);
 
index 5abb097..b4296bf 100644 (file)
@@ -213,8 +213,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct inode * inode = (struct inode *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(inode);
 }
 
index 64a96cd..e99f7ff 100644 (file)
@@ -77,8 +77,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags
 {
        struct iso_inode_info *ei = foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index e51164a..45368f8 100644 (file)
@@ -47,8 +47,7 @@ static void jffs2_i_init_once(void * foo, struct kmem_cache * cachep, unsigned l
 {
        struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                init_MUTEX(&ei->sem);
                inode_init_once(&ei->vfs_inode);
        }
index 58deae0..6b3acb0 100644 (file)
@@ -184,8 +184,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct metapage *mp = (struct metapage *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                mp->lid = 0;
                mp->lsn = 0;
                mp->flag = 0;
index 52d73d5..ea9dc3e 100644 (file)
@@ -752,8 +752,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags
 {
        struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
                INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
                init_rwsem(&jfs_ip->rdwrlock);
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 47a66aa..bf27b6c 100644 (file)
@@ -99,7 +99,9 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Now check for conflicting locks */
-       resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
+       resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie);
+       if (resp->status == nlm_drop_reply)
+               return rpc_drop_reply;
 
        dprintk("lockd: TEST4          status %d\n", ntohl(resp->status));
        nlm_release_host(host);
@@ -143,6 +145,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
        /* Now try to lock the file */
        resp->status = nlmsvc_lock(rqstp, file, &argp->lock,
                                        argp->block, &argp->cookie);
+       if (resp->status == nlm_drop_reply)
+               return rpc_drop_reply;
 
        dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
        nlm_release_host(host);
index cf51f84..b3efa45 100644 (file)
@@ -173,7 +173,7 @@ found:
  */
 static inline struct nlm_block *
 nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
-                               struct nlm_lock *lock, struct nlm_cookie *cookie)
+               struct nlm_lock *lock, struct nlm_cookie *cookie)
 {
        struct nlm_block        *block;
        struct nlm_host         *host;
@@ -210,6 +210,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
        block->b_daemon = rqstp->rq_server;
        block->b_host   = host;
        block->b_file   = file;
+       block->b_fl = NULL;
        file->f_count++;
 
        /* Add to file's list of blocks */
@@ -261,6 +262,7 @@ static void nlmsvc_free_block(struct kref *kref)
        nlmsvc_freegrantargs(block->b_call);
        nlm_release_call(block->b_call);
        nlm_release_file(block->b_file);
+       kfree(block->b_fl);
        kfree(block);
 }
 
@@ -330,6 +332,31 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call)
                kfree(call->a_args.lock.oh.data);
 }
 
+/*
+ * Deferred lock request handling for non-blocking lock
+ */
+static u32
+nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
+{
+       u32 status = nlm_lck_denied_nolocks;
+
+       block->b_flags |= B_QUEUED;
+
+       nlmsvc_insert_block(block, NLM_TIMEOUT);
+
+       block->b_cache_req = &rqstp->rq_chandle;
+       if (rqstp->rq_chandle.defer) {
+               block->b_deferred_req =
+                       rqstp->rq_chandle.defer(block->b_cache_req);
+               if (block->b_deferred_req != NULL)
+                       status = nlm_drop_reply;
+       }
+       dprintk("lockd: nlmsvc_defer_lock_rqst block %p flags %d status %d\n",
+               block, block->b_flags, status);
+
+       return status;
+}
+
 /*
  * Attempt to establish a lock, and if it can't be granted, block it
  * if required.
@@ -338,7 +365,7 @@ __be32
 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                        struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
 {
-       struct nlm_block        *block, *newblock = NULL;
+       struct nlm_block        *block = NULL;
        int                     error;
        __be32                  ret;
 
@@ -351,29 +378,58 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                                wait);
 
 
-       lock->fl.fl_flags &= ~FL_SLEEP;
-again:
        /* Lock file against concurrent access */
        mutex_lock(&file->f_mutex);
-       /* Get existing block (in case client is busy-waiting) */
+       /* Get existing block (in case client is busy-waiting)
+        * or create new block
+        */
        block = nlmsvc_lookup_block(file, lock);
        if (block == NULL) {
-               if (newblock != NULL)
-                       lock = &newblock->b_call->a_args.lock;
-       } else
+               block = nlmsvc_create_block(rqstp, file, lock, cookie);
+               ret = nlm_lck_denied_nolocks;
+               if (block == NULL)
+                       goto out;
                lock = &block->b_call->a_args.lock;
+       } else
+               lock->fl.fl_flags &= ~FL_SLEEP;
 
-       error = posix_lock_file(file->f_file, &lock->fl);
-       lock->fl.fl_flags &= ~FL_SLEEP;
+       if (block->b_flags & B_QUEUED) {
+               dprintk("lockd: nlmsvc_lock deferred block %p flags %d\n",
+                                                       block, block->b_flags);
+               if (block->b_granted) {
+                       nlmsvc_unlink_block(block);
+                       ret = nlm_granted;
+                       goto out;
+               }
+               if (block->b_flags & B_TIMED_OUT) {
+                       nlmsvc_unlink_block(block);
+                       ret = nlm_lck_denied;
+                       goto out;
+               }
+               ret = nlm_drop_reply;
+               goto out;
+       }
 
-       dprintk("lockd: posix_lock_file returned %d\n", error);
+       if (!wait)
+               lock->fl.fl_flags &= ~FL_SLEEP;
+       error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
+       lock->fl.fl_flags &= ~FL_SLEEP;
 
+       dprintk("lockd: vfs_lock_file returned %d\n", error);
        switch(error) {
                case 0:
                        ret = nlm_granted;
                        goto out;
                case -EAGAIN:
+                       ret = nlm_lck_denied;
                        break;
+               case -EINPROGRESS:
+                       if (wait)
+                               break;
+                       /* Filesystem lock operation is in progress
+                          Add it to the queue waiting for callback */
+                       ret = nlmsvc_defer_lock_rqst(rqstp, block);
+                       goto out;
                case -EDEADLK:
                        ret = nlm_deadlock;
                        goto out;
@@ -387,26 +443,11 @@ again:
                goto out;
 
        ret = nlm_lck_blocked;
-       if (block != NULL)
-               goto out;
-
-       /* If we don't have a block, create and initialize it. Then
-        * retry because we may have slept in kmalloc. */
-       /* We have to release f_mutex as nlmsvc_create_block may try to
-        * to claim it while doing host garbage collection */
-       if (newblock == NULL) {
-               mutex_unlock(&file->f_mutex);
-               dprintk("lockd: blocking on this lock (allocating).\n");
-               if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie)))
-                       return nlm_lck_denied_nolocks;
-               goto again;
-       }
 
        /* Append to list of blocked */
-       nlmsvc_insert_block(newblock, NLM_NEVER);
+       nlmsvc_insert_block(block, NLM_NEVER);
 out:
        mutex_unlock(&file->f_mutex);
-       nlmsvc_release_block(newblock);
        nlmsvc_release_block(block);
        dprintk("lockd: nlmsvc_lock returned %u\n", ret);
        return ret;
@@ -416,9 +457,14 @@ out:
  * Test for presence of a conflicting lock.
  */
 __be32
-nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
-                                      struct nlm_lock *conflock)
+nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+               struct nlm_lock *lock, struct nlm_lock *conflock,
+               struct nlm_cookie *cookie)
 {
+       struct nlm_block        *block = NULL;
+       int                     error;
+       __be32                  ret;
+
        dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
                                file->f_file->f_path.dentry->d_inode->i_sb->s_id,
                                file->f_file->f_path.dentry->d_inode->i_ino,
@@ -426,19 +472,70 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
 
-       if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) {
-               dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
-                               conflock->fl.fl_type,
-                               (long long)conflock->fl.fl_start,
-                               (long long)conflock->fl.fl_end);
-               conflock->caller = "somehost";  /* FIXME */
-               conflock->len = strlen(conflock->caller);
-               conflock->oh.len = 0;           /* don't return OH info */
-               conflock->svid = conflock->fl.fl_pid;
-               return nlm_lck_denied;
+       /* Get existing block (in case client is busy-waiting) */
+       block = nlmsvc_lookup_block(file, lock);
+
+       if (block == NULL) {
+               struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+
+               if (conf == NULL)
+                       return nlm_granted;
+               block = nlmsvc_create_block(rqstp, file, lock, cookie);
+               if (block == NULL) {
+                       kfree(conf);
+                       return nlm_granted;
+               }
+               block->b_fl = conf;
+       }
+       if (block->b_flags & B_QUEUED) {
+               dprintk("lockd: nlmsvc_testlock deferred block %p flags %d fl %p\n",
+                       block, block->b_flags, block->b_fl);
+               if (block->b_flags & B_TIMED_OUT) {
+                       nlmsvc_unlink_block(block);
+                       return nlm_lck_denied;
+               }
+               if (block->b_flags & B_GOT_CALLBACK) {
+                       if (block->b_fl != NULL
+                                       && block->b_fl->fl_type != F_UNLCK) {
+                               lock->fl = *block->b_fl;
+                               goto conf_lock;
+                       }
+                       else {
+                               nlmsvc_unlink_block(block);
+                               return nlm_granted;
+                       }
+               }
+               return nlm_drop_reply;
        }
 
-       return nlm_granted;
+       error = vfs_test_lock(file->f_file, &lock->fl);
+       if (error == -EINPROGRESS)
+               return nlmsvc_defer_lock_rqst(rqstp, block);
+       if (error) {
+               ret = nlm_lck_denied_nolocks;
+               goto out;
+       }
+       if (lock->fl.fl_type == F_UNLCK) {
+               ret = nlm_granted;
+               goto out;
+       }
+
+conf_lock:
+       dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
+               lock->fl.fl_type, (long long)lock->fl.fl_start,
+               (long long)lock->fl.fl_end);
+       conflock->caller = "somehost";  /* FIXME */
+       conflock->len = strlen(conflock->caller);
+       conflock->oh.len = 0;           /* don't return OH info */
+       conflock->svid = lock->fl.fl_pid;
+       conflock->fl.fl_type = lock->fl.fl_type;
+       conflock->fl.fl_start = lock->fl.fl_start;
+       conflock->fl.fl_end = lock->fl.fl_end;
+       ret = nlm_lck_denied;
+out:
+       if (block)
+               nlmsvc_release_block(block);
+       return ret;
 }
 
 /*
@@ -464,7 +561,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
        nlmsvc_cancel_blocked(file, lock);
 
        lock->fl.fl_type = F_UNLCK;
-       error = posix_lock_file(file->f_file, &lock->fl);
+       error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
 
        return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
 }
@@ -493,12 +590,71 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
        block = nlmsvc_lookup_block(file, lock);
        mutex_unlock(&file->f_mutex);
        if (block != NULL) {
+               vfs_cancel_lock(block->b_file->f_file,
+                               &block->b_call->a_args.lock.fl);
                status = nlmsvc_unlink_block(block);
                nlmsvc_release_block(block);
        }
        return status ? nlm_lck_denied : nlm_granted;
 }
 
+/*
+ * This is a callback from the filesystem for VFS file lock requests.
+ * It will be used if fl_grant is defined and the filesystem can not
+ * respond to the request immediately.
+ * For GETLK request it will copy the reply to the nlm_block.
+ * For SETLK or SETLKW request it will get the local posix lock.
+ * In all cases it will move the block to the head of nlm_blocked q where
+ * nlmsvc_retry_blocked() can send back a reply for SETLKW or revisit the
+ * deferred rpc for GETLK and SETLK.
+ */
+static void
+nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
+                            int result)
+{
+       block->b_flags |= B_GOT_CALLBACK;
+       if (result == 0)
+               block->b_granted = 1;
+       else
+               block->b_flags |= B_TIMED_OUT;
+       if (conf) {
+               if (block->b_fl)
+                       locks_copy_lock(block->b_fl, conf);
+       }
+}
+
+static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf,
+                                       int result)
+{
+       struct nlm_block *block;
+       int rc = -ENOENT;
+
+       lock_kernel();
+       list_for_each_entry(block, &nlm_blocked, b_list) {
+               if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
+                       dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n",
+                                                       block, block->b_flags);
+                       if (block->b_flags & B_QUEUED) {
+                               if (block->b_flags & B_TIMED_OUT) {
+                                       rc = -ENOLCK;
+                                       break;
+                               }
+                               nlmsvc_update_deferred_block(block, conf, result);
+                       } else if (result == 0)
+                               block->b_granted = 1;
+
+                       nlmsvc_insert_block(block, 0);
+                       svc_wake_up(block->b_daemon);
+                       rc = 0;
+                       break;
+               }
+       }
+       unlock_kernel();
+       if (rc == -ENOENT)
+               printk(KERN_WARNING "lockd: grant for unknown block\n");
+       return rc;
+}
+
 /*
  * Unblock a blocked lock request. This is a callback invoked from the
  * VFS layer when a lock on which we blocked is removed.
@@ -531,6 +687,7 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 struct lock_manager_operations nlmsvc_lock_operations = {
        .fl_compare_owner = nlmsvc_same_owner,
        .fl_notify = nlmsvc_notify_blocked,
+       .fl_grant = nlmsvc_grant_deferred,
 };
 
 /*
@@ -553,6 +710,8 @@ nlmsvc_grant_blocked(struct nlm_block *block)
 
        dprintk("lockd: grant blocked lock %p\n", block);
 
+       kref_get(&block->b_count);
+
        /* Unlink block request from list */
        nlmsvc_unlink_block(block);
 
@@ -566,20 +725,23 @@ nlmsvc_grant_blocked(struct nlm_block *block)
 
        /* Try the lock operation again */
        lock->fl.fl_flags |= FL_SLEEP;
-       error = posix_lock_file(file->f_file, &lock->fl);
+       error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
        lock->fl.fl_flags &= ~FL_SLEEP;
 
        switch (error) {
        case 0:
                break;
        case -EAGAIN:
-               dprintk("lockd: lock still blocked\n");
+       case -EINPROGRESS:
+               dprintk("lockd: lock still blocked error %d\n", error);
                nlmsvc_insert_block(block, NLM_NEVER);
+               nlmsvc_release_block(block);
                return;
        default:
                printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
                                -error, __FUNCTION__);
                nlmsvc_insert_block(block, 10 * HZ);
+               nlmsvc_release_block(block);
                return;
        }
 
@@ -592,7 +754,6 @@ callback:
        nlmsvc_insert_block(block, 30 * HZ);
 
        /* Call the client */
-       kref_get(&block->b_count);
        nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops);
 }
 
@@ -665,6 +826,23 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
        nlmsvc_release_block(block);
 }
 
+/* Helper function to handle retry of a deferred block.
+ * If it is a blocking lock, call grant_blocked.
+ * For a non-blocking lock or test lock, revisit the request.
+ */
+static void
+retry_deferred_block(struct nlm_block *block)
+{
+       if (!(block->b_flags & B_GOT_CALLBACK))
+               block->b_flags |= B_TIMED_OUT;
+       nlmsvc_insert_block(block, NLM_TIMEOUT);
+       dprintk("revisit block %p flags %d\n",  block, block->b_flags);
+       if (block->b_deferred_req) {
+               block->b_deferred_req->revisit(block->b_deferred_req, 0);
+               block->b_deferred_req = NULL;
+       }
+}
+
 /*
  * Retry all blocked locks that have been notified. This is where lockd
  * picks up locks that can be granted, or grant notifications that must
@@ -688,9 +866,12 @@ nlmsvc_retry_blocked(void)
 
                dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
                        block, block->b_when);
-               kref_get(&block->b_count);
-               nlmsvc_grant_blocked(block);
-               nlmsvc_release_block(block);
+               if (block->b_flags & B_QUEUED) {
+                       dprintk("nlmsvc_retry_blocked delete block (%p, granted=%d, flags=%d)\n",
+                               block, block->b_granted, block->b_flags);
+                       retry_deferred_block(block);
+               } else
+                       nlmsvc_grant_blocked(block);
        }
 
        return timeout;
index 31cb484..9cd5c8b 100644 (file)
@@ -33,6 +33,7 @@ cast_to_nlm(__be32 status, u32 vers)
                case nlm_lck_denied_nolocks:
                case nlm_lck_blocked:
                case nlm_lck_denied_grace_period:
+               case nlm_drop_reply:
                        break;
                case nlm4_deadlock:
                        status = nlm_lck_denied;
@@ -127,7 +128,9 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Now check for conflicting locks */
-       resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock));
+       resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie));
+       if (resp->status == nlm_drop_reply)
+               return rpc_drop_reply;
 
        dprintk("lockd: TEST          status %d vers %d\n",
                ntohl(resp->status), rqstp->rq_vers);
@@ -172,6 +175,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
        /* Now try to lock the file */
        resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock,
                                               argp->block, &argp->cookie));
+       if (resp->status == nlm_drop_reply)
+               return rpc_drop_reply;
 
        dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
        nlm_release_host(host);
index c0df00c..84ebba3 100644 (file)
@@ -182,7 +182,7 @@ again:
                        lock.fl_type  = F_UNLCK;
                        lock.fl_start = 0;
                        lock.fl_end   = OFFSET_MAX;
-                       if (posix_lock_file(file->f_file, &lock) < 0) {
+                       if (vfs_lock_file(file->f_file, F_SETLK, &lock, NULL) < 0) {
                                printk("lockd: unlock failure in %s:%d\n",
                                                __FILE__, __LINE__);
                                return 1;
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 52a8100..671a034 100644 (file)
@@ -203,8 +203,7 @@ static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags)
 {
        struct file_lock *lock = (struct file_lock *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) !=
-                                       SLAB_CTOR_CONSTRUCTOR)
+       if (!(flags & SLAB_CTOR_CONSTRUCTOR))
                return;
 
        locks_init_lock(lock);
@@ -666,11 +665,11 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
 }
 
 int
-posix_test_lock(struct file *filp, struct file_lock *fl,
-               struct file_lock *conflock)
+posix_test_lock(struct file *filp, struct file_lock *fl)
 {
        struct file_lock *cfl;
 
+       fl->fl_type = F_UNLCK;
        lock_kernel();
        for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
                if (!IS_POSIX(cfl))
@@ -679,7 +678,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl,
                        break;
        }
        if (cfl) {
-               __locks_copy_lock(conflock, cfl);
+               __locks_copy_lock(fl, cfl);
                unlock_kernel();
                return 1;
        }
@@ -801,7 +800,7 @@ out:
        return error;
 }
 
-static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
+static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
 {
        struct file_lock *fl;
        struct file_lock *new_fl = NULL;
@@ -1007,6 +1006,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
  * posix_lock_file - Apply a POSIX-style lock to a file
  * @filp: The file to apply the lock to
  * @fl: The lock to be applied
+ * @conflock: Place to return a copy of the conflicting lock, if found.
  *
  * Add a POSIX style lock to a file.
  * We merge adjacent & overlapping locks whenever possible.
@@ -1016,26 +1016,12 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
  * whether or not a lock was successfully freed by testing the return
  * value for -ENOENT.
  */
-int posix_lock_file(struct file *filp, struct file_lock *fl)
-{
-       return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
-}
-EXPORT_SYMBOL(posix_lock_file);
-
-/**
- * posix_lock_file_conf - Apply a POSIX-style lock to a file
- * @filp: The file to apply the lock to
- * @fl: The lock to be applied
- * @conflock: Place to return a copy of the conflicting lock, if found.
- *
- * Except for the conflock parameter, acts just like posix_lock_file.
- */
-int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
+int posix_lock_file(struct file *filp, struct file_lock *fl,
                        struct file_lock *conflock)
 {
-       return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock);
+       return __posix_lock_file(filp->f_path.dentry->d_inode, fl, conflock);
 }
-EXPORT_SYMBOL(posix_lock_file_conf);
+EXPORT_SYMBOL(posix_lock_file);
 
 /**
  * posix_lock_file_wait - Apply a POSIX-style lock to a file
@@ -1051,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
        int error;
        might_sleep ();
        for (;;) {
-               error = posix_lock_file(filp, fl);
+               error = posix_lock_file(filp, fl, NULL);
                if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
                        break;
                error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1123,7 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
        fl.fl_end = offset + count - 1;
 
        for (;;) {
-               error = __posix_lock_file_conf(inode, &fl, NULL);
+               error = __posix_lock_file(inode, &fl, NULL);
                if (error != -EAGAIN)
                        break;
                if (!(fl.fl_flags & FL_SLEEP))
@@ -1611,12 +1597,62 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
        return error;
 }
 
+/**
+ * vfs_test_lock - test file byte range lock
+ * @filp: The file to test lock for
+ * @fl: The lock to test
+ * @conf: Place to return a copy of the conflicting lock, if found
+ *
+ * Returns -ERRNO on failure.  Indicates presence of conflicting lock by
+ * setting conf->fl_type to something other than F_UNLCK.
+ */
+int vfs_test_lock(struct file *filp, struct file_lock *fl)
+{
+       if (filp->f_op && filp->f_op->lock)
+               return filp->f_op->lock(filp, F_GETLK, fl);
+       posix_test_lock(filp, fl);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vfs_test_lock);
+
+static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
+{
+       flock->l_pid = fl->fl_pid;
+#if BITS_PER_LONG == 32
+       /*
+        * Make sure we can represent the posix lock via
+        * legacy 32bit flock.
+        */
+       if (fl->fl_start > OFFT_OFFSET_MAX)
+               return -EOVERFLOW;
+       if (fl->fl_end != OFFSET_MAX && fl->fl_end > OFFT_OFFSET_MAX)
+               return -EOVERFLOW;
+#endif
+       flock->l_start = fl->fl_start;
+       flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
+               fl->fl_end - fl->fl_start + 1;
+       flock->l_whence = 0;
+       return 0;
+}
+
+#if BITS_PER_LONG == 32
+static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
+{
+       flock->l_pid = fl->fl_pid;
+       flock->l_start = fl->fl_start;
+       flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
+               fl->fl_end - fl->fl_start + 1;
+       flock->l_whence = 0;
+       flock->l_type = fl->fl_type;
+}
+#endif
+
 /* Report the first existing lock that would conflict with l.
  * This implements the F_GETLK command of fcntl().
  */
 int fcntl_getlk(struct file *filp, struct flock __user *l)
 {
-       struct file_lock *fl, cfl, file_lock;
+       struct file_lock file_lock;
        struct flock flock;
        int error;
 
@@ -1631,38 +1667,15 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
        if (error)
                goto out;
 
-       if (filp->f_op && filp->f_op->lock) {
-               error = filp->f_op->lock(filp, F_GETLK, &file_lock);
-               if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
-                       file_lock.fl_ops->fl_release_private(&file_lock);
-               if (error < 0)
-                       goto out;
-               else
-                 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
-       } else {
-               fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
-       }
+       error = vfs_test_lock(filp, &file_lock);
+       if (error)
+               goto out;
  
-       flock.l_type = F_UNLCK;
-       if (fl != NULL) {
-               flock.l_pid = fl->fl_pid;
-#if BITS_PER_LONG == 32
-               /*
-                * Make sure we can represent the posix lock via
-                * legacy 32bit flock.
-                */
-               error = -EOVERFLOW;
-               if (fl->fl_start > OFFT_OFFSET_MAX)
-                       goto out;
-               if ((fl->fl_end != OFFSET_MAX)
-                   && (fl->fl_end > OFFT_OFFSET_MAX))
+       flock.l_type = file_lock.fl_type;
+       if (file_lock.fl_type != F_UNLCK) {
+               error = posix_lock_to_flock(&flock, &file_lock);
+               if (error)
                        goto out;
-#endif
-               flock.l_start = fl->fl_start;
-               flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
-                       fl->fl_end - fl->fl_start + 1;
-               flock.l_whence = 0;
-               flock.l_type = fl->fl_type;
        }
        error = -EFAULT;
        if (!copy_to_user(l, &flock, sizeof(flock)))
@@ -1671,6 +1684,48 @@ out:
        return error;
 }
 
+/**
+ * vfs_lock_file - file byte range lock
+ * @filp: The file to apply the lock to
+ * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.)
+ * @fl: The lock to be applied
+ * @conf: Place to return a copy of the conflicting lock, if found.
+ *
+ * A caller that doesn't care about the conflicting lock may pass NULL
+ * as the final argument.
+ *
+ * If the filesystem defines a private ->lock() method, then @conf will
+ * be left unchanged; so a caller that cares should initialize it to
+ * some acceptable default.
+ *
+ * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
+ * locks, the ->lock() interface may return asynchronously, before the lock has
+ * been granted or denied by the underlying filesystem, if (and only if)
+ * fl_grant is set. Callers expecting ->lock() to return asynchronously
+ * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
+ * the request is for a blocking lock. When ->lock() does return asynchronously,
+ * it must return -EINPROGRESS, and call ->fl_grant() when the lock
+ * request completes.
+ * If the request is for non-blocking lock the file system should return
+ * -EINPROGRESS then try to get the lock and call the callback routine with
+ * the result. If the request timed out the callback routine will return a
+ * nonzero return code and the file system should release the lock. The file
+ * system is also responsible to keep a corresponding posix lock when it
+ * grants a lock so the VFS can find out which locks are locally held and do
+ * the correct lock cleanup when required.
+ * The underlying filesystem must not drop the kernel lock or call
+ * ->fl_grant() before returning to the caller with a -EINPROGRESS
+ * return code.
+ */
+int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
+{
+       if (filp->f_op && filp->f_op->lock)
+               return filp->f_op->lock(filp, cmd, fl);
+       else
+               return posix_lock_file(filp, fl, conf);
+}
+EXPORT_SYMBOL_GPL(vfs_lock_file);
+
 /* Apply the lock described by l to an open file descriptor.
  * This implements both the F_SETLK and F_SETLKW commands of fcntl().
  */
@@ -1733,21 +1788,17 @@ again:
        if (error)
                goto out;
 
-       if (filp->f_op && filp->f_op->lock != NULL)
-               error = filp->f_op->lock(filp, cmd, file_lock);
-       else {
-               for (;;) {
-                       error = posix_lock_file(filp, file_lock);
-                       if ((error != -EAGAIN) || (cmd == F_SETLK))
-                               break;
-                       error = wait_event_interruptible(file_lock->fl_wait,
-                                       !file_lock->fl_next);
-                       if (!error)
-                               continue;
-
-                       locks_delete_block(file_lock);
+       for (;;) {
+               error = vfs_lock_file(filp, cmd, file_lock, NULL);
+               if (error != -EAGAIN || cmd == F_SETLK)
                        break;
-               }
+               error = wait_event_interruptible(file_lock->fl_wait,
+                               !file_lock->fl_next);
+               if (!error)
+                       continue;
+
+               locks_delete_block(file_lock);
+               break;
        }
 
        /*
@@ -1770,7 +1821,7 @@ out:
  */
 int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
 {
-       struct file_lock *fl, cfl, file_lock;
+       struct file_lock file_lock;
        struct flock64 flock;
        int error;
 
@@ -1785,27 +1836,14 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
        if (error)
                goto out;
 
-       if (filp->f_op && filp->f_op->lock) {
-               error = filp->f_op->lock(filp, F_GETLK, &file_lock);
-               if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
-                       file_lock.fl_ops->fl_release_private(&file_lock);
-               if (error < 0)
-                       goto out;
-               else
-                 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
-       } else {
-               fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
-       }
-       flock.l_type = F_UNLCK;
-       if (fl != NULL) {
-               flock.l_pid = fl->fl_pid;
-               flock.l_start = fl->fl_start;
-               flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
-                       fl->fl_end - fl->fl_start + 1;
-               flock.l_whence = 0;
-               flock.l_type = fl->fl_type;
-       }
+       error = vfs_test_lock(filp, &file_lock);
+       if (error)
+               goto out;
+
+       flock.l_type = file_lock.fl_type;
+       if (file_lock.fl_type != F_UNLCK)
+               posix_lock_to_flock64(&flock, &file_lock);
+
        error = -EFAULT;
        if (!copy_to_user(l, &flock, sizeof(flock)))
                error = 0;
@@ -1876,21 +1914,17 @@ again:
        if (error)
                goto out;
 
-       if (filp->f_op && filp->f_op->lock != NULL)
-               error = filp->f_op->lock(filp, cmd, file_lock);
-       else {
-               for (;;) {
-                       error = posix_lock_file(filp, file_lock);
-                       if ((error != -EAGAIN) || (cmd == F_SETLK64))
-                               break;
-                       error = wait_event_interruptible(file_lock->fl_wait,
-                                       !file_lock->fl_next);
-                       if (!error)
-                               continue;
-
-                       locks_delete_block(file_lock);
+       for (;;) {
+               error = vfs_lock_file(filp, cmd, file_lock, NULL);
+               if (error != -EAGAIN || cmd == F_SETLK64)
                        break;
-               }
+               error = wait_event_interruptible(file_lock->fl_wait,
+                               !file_lock->fl_next);
+               if (!error)
+                       continue;
+
+               locks_delete_block(file_lock);
+               break;
        }
 
        /*
@@ -1935,10 +1969,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
        lock.fl_ops = NULL;
        lock.fl_lmops = NULL;
 
-       if (filp->f_op && filp->f_op->lock != NULL)
-               filp->f_op->lock(filp, F_SETLK, &lock);
-       else
-               posix_lock_file(filp, &lock);
+       vfs_lock_file(filp, F_SETLK, &lock, NULL);
 
        if (lock.fl_ops && lock.fl_ops->fl_release_private)
                lock.fl_ops->fl_release_private(&lock);
@@ -2015,6 +2046,22 @@ posix_unblock_lock(struct file *filp, struct file_lock *waiter)
 
 EXPORT_SYMBOL(posix_unblock_lock);
 
+/**
+ * vfs_cancel_lock - file byte range unblock lock
+ * @filp: The file to apply the unblock to
+ * @fl: The lock to be unblocked
+ *
+ * Used by lock managers to cancel blocked requests
+ */
+int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
+{
+       if (filp->f_op && filp->f_op->lock)
+               return filp->f_op->lock(filp, F_CANCELLK, fl);
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(vfs_cancel_lock);
+
 static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
 {
        struct inode *inode = NULL;
index cb4cb57..e207cbe 100644 (file)
@@ -65,7 +65,6 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
                kmap(page);
                if (!PageUptodate(page))
                        goto fail;
index 92e383a..2f4d43a 100644 (file)
@@ -73,8 +73,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct minix_inode_info *ei = (struct minix_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index 880052c..94b2f60 100644 (file)
@@ -2671,19 +2671,9 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
        struct address_space *mapping = dentry->d_inode->i_mapping;
        page = read_mapping_page(mapping, 0, NULL);
        if (IS_ERR(page))
-               goto sync_fail;
-       wait_on_page_locked(page);
-       if (!PageUptodate(page))
-               goto async_fail;
+               return (char*)page;
        *ppage = page;
        return kmap(page);
-
-async_fail:
-       page_cache_release(page);
-       return ERR_PTR(-EIO);
-
-sync_fail:
-       return (char*)page;
 }
 
 int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
index 7285c94..c29f00a 100644 (file)
@@ -60,8 +60,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                mutex_init(&ei->open_mutex);
                inode_init_once(&ei->vfs_inode);
        }
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..625d8e5 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,14 +324,16 @@ 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)) {
                status = PTR_ERR(page);
                goto out;
        }
-       if (!PageUptodate(page))
-               goto read_error;
 
        /* NOTE: Someone else may have changed the READDIRPLUS flag */
        desc->page = page;
@@ -337,9 +347,6 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
  out:
        dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __FUNCTION__, status);
        return status;
- read_error:
-       page_cache_release(page);
-       return -EIO;
 }
 
 /*
@@ -468,6 +475,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 +485,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 +496,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 +860,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 8e66b5a..5eaee6d 100644 (file)
@@ -391,17 +391,12 @@ out_swapfile:
 
 static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
 {
-       struct file_lock cfl;
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
 
        lock_kernel();
        /* Try local locking first */
-       if (posix_test_lock(filp, fl, &cfl)) {
-               fl->fl_start = cfl.fl_start;
-               fl->fl_end = cfl.fl_end;
-               fl->fl_type = cfl.fl_type;
-               fl->fl_pid = cfl.fl_pid;
+       if (posix_test_lock(filp, fl)) {
                goto out;
        }
 
index 44aa9b7..1e9a915 100644 (file)
@@ -1167,8 +1167,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct nfs_inode *nfsi = (struct nfs_inode *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&nfsi->vfs_inode);
                spin_lock_init(&nfsi->req_lock);
                INIT_LIST_HEAD(&nfsi->dirty);
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..d6a30e9 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;
 }
 
@@ -3018,6 +3017,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
                case -NFS4ERR_DENIED:
                        status = 0;
        }
+       request->fl_ops->fl_release_private(request);
 out:
        up_read(&clp->cl_sem);
        return status;
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 f4a0548..bc28213 100644 (file)
@@ -61,15 +61,9 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
                err = page;
                goto read_failed;
        }
-       if (!PageUptodate(page)) {
-               err = ERR_PTR(-EIO);
-               goto getlink_read_error;
-       }
        nd_set_link(nd, kmap(page));
        return page;
 
-getlink_read_error:
-       page_cache_release(page);
 read_failed:
        nd_set_link(nd, err);
        return NULL;
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 af36070..678f3be 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/nfsd/xdr4.h>
 #include <linux/namei.h>
 #include <linux/mutex.h>
+#include <linux/lockd/bind.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -2657,6 +2658,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct file_lock conflock;
        __be32 status = 0;
        unsigned int strhashval;
+       unsigned int cmd;
        int err;
 
        dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -2739,10 +2741,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                case NFS4_READ_LT:
                case NFS4_READW_LT:
                        file_lock.fl_type = F_RDLCK;
+                       cmd = F_SETLK;
                break;
                case NFS4_WRITE_LT:
                case NFS4_WRITEW_LT:
                        file_lock.fl_type = F_WRLCK;
+                       cmd = F_SETLK;
                break;
                default:
                        status = nfserr_inval;
@@ -2769,9 +2773,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        /* XXX?: Just to divert the locks_release_private at the start of
         * locks_copy_lock: */
-       conflock.fl_ops = NULL;
-       conflock.fl_lmops = NULL;
-       err = posix_lock_file_conf(filp, &file_lock, &conflock);
+       locks_init_lock(&conflock);
+       err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
        switch (-err) {
        case 0: /* success! */
                update_stateid(&lock_stp->st_stateid);
@@ -2788,7 +2791,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfserr_deadlock;
                break;
        default:        
-               dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",err);
+               dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d\n",err);
                status = nfserr_resource;
                break;
        }
@@ -2813,7 +2816,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct inode *inode;
        struct file file;
        struct file_lock file_lock;
-       struct file_lock conflock;
+       int error;
        __be32 status;
 
        if (nfs4_in_grace())
@@ -2869,18 +2872,23 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        nfs4_transform_lock_offset(&file_lock);
 
-       /* posix_test_lock uses the struct file _only_ to resolve the inode.
+       /* vfs_test_lock uses the struct file _only_ to resolve the inode.
         * since LOCKT doesn't require an OPEN, and therefore a struct
-        * file may not exist, pass posix_test_lock a struct file with
+        * file may not exist, pass vfs_test_lock a struct file with
         * only the dentry:inode set.
         */
        memset(&file, 0, sizeof (struct file));
        file.f_path.dentry = cstate->current_fh.fh_dentry;
 
        status = nfs_ok;
-       if (posix_test_lock(&file, &file_lock, &conflock)) {
+       error = vfs_test_lock(&file, &file_lock);
+       if (error) {
+               status = nfserrno(error);
+               goto out;
+       }
+       if (file_lock.fl_type != F_UNLCK) {
                status = nfserr_denied;
-               nfs4_set_lock_denied(&conflock, &lockt->lt_denied);
+               nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
        }
 out:
        nfs4_unlock_state();
@@ -2933,9 +2941,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        /*
        *  Try to unlock the file in the VFS.
        */
-       err = posix_lock_file(filp, &file_lock);
+       err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL);
        if (err) {
-               dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
+               dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
                goto out_nfserr;
        }
        /*
index 9393f4b..caecc58 100644 (file)
@@ -89,9 +89,8 @@ static inline struct page *ntfs_map_page(struct address_space *mapping,
        struct page *page = read_mapping_page(mapping, index, NULL);
 
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
                kmap(page);
-               if (PageUptodate(page) && !PageError(page))
+               if (!PageError(page))
                        return page;
                ntfs_unmap_page(page);
                return ERR_PTR(-EIO);
index 7659cc1..1c08fef 100644 (file)
@@ -2532,14 +2532,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
                page = read_mapping_page(mapping, idx, NULL);
                if (IS_ERR(page)) {
                        ntfs_error(vol->sb, "Failed to read first partial "
-                                       "page (sync error, index 0x%lx).", idx);
-                       return PTR_ERR(page);
-               }
-               wait_on_page_locked(page);
-               if (unlikely(!PageUptodate(page))) {
-                       ntfs_error(vol->sb, "Failed to read first partial page "
-                                       "(async error, index 0x%lx).", idx);
-                       page_cache_release(page);
+                                       "page (error, index 0x%lx).", idx);
                        return PTR_ERR(page);
                }
                /*
@@ -2602,14 +2595,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
                page = read_mapping_page(mapping, idx, NULL);
                if (IS_ERR(page)) {
                        ntfs_error(vol->sb, "Failed to read last partial page "
-                                       "(sync error, index 0x%lx).", idx);
-                       return PTR_ERR(page);
-               }
-               wait_on_page_locked(page);
-               if (unlikely(!PageUptodate(page))) {
-                       ntfs_error(vol->sb, "Failed to read last partial page "
-                                       "(async error, index 0x%lx).", idx);
-                       page_cache_release(page);
+                                       "(error, index 0x%lx).", idx);
                        return PTR_ERR(page);
                }
                kaddr = kmap_atomic(page, KM_USER0);
index d69c459..dbbac55 100644 (file)
@@ -236,8 +236,7 @@ do_non_resident_extend:
                        err = PTR_ERR(page);
                        goto init_err_out;
                }
-               wait_on_page_locked(page);
-               if (unlikely(!PageUptodate(page) || PageError(page))) {
+               if (unlikely(PageError(page))) {
                        page_cache_release(page);
                        err = -EIO;
                        goto init_err_out;
index 1594c90..21d834e 100644 (file)
@@ -2471,7 +2471,6 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
        s64 nr_free = vol->nr_clusters;
        u32 *kaddr;
        struct address_space *mapping = vol->lcnbmp_ino->i_mapping;
-       filler_t *readpage = (filler_t*)mapping->a_ops->readpage;
        struct page *page;
        pgoff_t index, max_index;
 
@@ -2494,24 +2493,14 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
                 * Read the page from page cache, getting it from backing store
                 * if necessary, and increment the use count.
                 */
-               page = read_cache_page(mapping, index, (filler_t*)readpage,
-                               NULL);
+               page = read_mapping_page(mapping, index, NULL);
                /* Ignore pages which errored synchronously. */
                if (IS_ERR(page)) {
-                       ntfs_debug("Sync read_cache_page() error. Skipping "
+                       ntfs_debug("read_mapping_page() error. Skipping "
                                        "page (index 0x%lx).", index);
                        nr_free -= PAGE_CACHE_SIZE * 8;
                        continue;
                }
-               wait_on_page_locked(page);
-               /* Ignore pages which errored asynchronously. */
-               if (!PageUptodate(page)) {
-                       ntfs_debug("Async read_cache_page() error. Skipping "
-                                       "page (index 0x%lx).", index);
-                       page_cache_release(page);
-                       nr_free -= PAGE_CACHE_SIZE * 8;
-                       continue;
-               }
                kaddr = (u32*)kmap_atomic(page, KM_USER0);
                /*
                 * For each 4 bytes, subtract the number of set bits. If this
@@ -2562,7 +2551,6 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
 {
        u32 *kaddr;
        struct address_space *mapping = vol->mftbmp_ino->i_mapping;
-       filler_t *readpage = (filler_t*)mapping->a_ops->readpage;
        struct page *page;
        pgoff_t index;
 
@@ -2576,21 +2564,11 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
                 * Read the page from page cache, getting it from backing store
                 * if necessary, and increment the use count.
                 */
-               page = read_cache_page(mapping, index, (filler_t*)readpage,
-                               NULL);
+               page = read_mapping_page(mapping, index, NULL);
                /* Ignore pages which errored synchronously. */
                if (IS_ERR(page)) {
-                       ntfs_debug("Sync read_cache_page() error. Skipping "
-                                       "page (index 0x%lx).", index);
-                       nr_free -= PAGE_CACHE_SIZE * 8;
-                       continue;
-               }
-               wait_on_page_locked(page);
-               /* Ignore pages which errored asynchronously. */
-               if (!PageUptodate(page)) {
-                       ntfs_debug("Async read_cache_page() error. Skipping "
+                       ntfs_debug("read_mapping_page() error. Skipping "
                                        "page (index 0x%lx).", index);
-                       page_cache_release(page);
                        nr_free -= PAGE_CACHE_SIZE * 8;
                        continue;
                }
@@ -3107,8 +3085,7 @@ static void ntfs_big_inode_init_once(void *foo, struct kmem_cache *cachep,
 {
        ntfs_inode *ni = (ntfs_inode *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-                       SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(VFS_I(ni));
 }
 
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 de952eb..d4e46d0 100644 (file)
@@ -263,8 +263,7 @@ static void dlmfs_init_once(void *foo,
        struct dlmfs_inode_private *ip =
                (struct dlmfs_inode_private *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                ip->ip_dlm = NULL;
                ip->ip_parent = NULL;
 
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..7c5e3f5 100644 (file)
@@ -937,8 +937,7 @@ static void ocfs2_inode_init_once(void *data,
 {
        struct ocfs2_inode_info *oi = data;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                oi->ip_flags = 0;
                oi->ip_open_count = 0;
                spin_lock_init(&oi->ip_lock);
@@ -1538,7 +1537,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 40dc1a5..7134007 100644 (file)
@@ -67,16 +67,9 @@ static char *ocfs2_page_getlink(struct dentry * dentry,
        page = read_mapping_page(mapping, 0, NULL);
        if (IS_ERR(page))
                goto sync_fail;
-       wait_on_page_locked(page);
-       if (!PageUptodate(page))
-               goto async_fail;
        *ppage = page;
        return kmap(page);
 
-async_fail:
-       page_cache_release(page);
-       return ERR_PTR(-EIO);
-
 sync_fail:
        return (char*)page;
 }
index bde1c16..731a90e 100644 (file)
@@ -419,8 +419,7 @@ static void op_inode_init_once(void *data, struct kmem_cache * cachep, unsigned
 {
        struct op_inode_info *oi = (struct op_inode_info *) data;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&oi->vfs_inode);
 }
 
index 1bc9f37..e349132 100644 (file)
@@ -271,7 +271,7 @@ adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev)
                extern void xd_set_geometry(struct block_device *,
                        unsigned char, unsigned char, unsigned int);
                xd_set_geometry(bdev, dr->secspertrack, heads, 1);
-               invalidate_bdev(bdev, 1);
+               invalidate_bh_lrus();
                truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
        }
 #endif
index 8a7d003..6b9dae3 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;
@@ -569,9 +569,6 @@ unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
        page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
                                 NULL);
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
-               if (!PageUptodate(page))
-                       goto fail;
                if (PageError(page))
                        goto fail;
                p->v = page;
index 989af5e..ec158dd 100644 (file)
@@ -715,6 +715,40 @@ static const struct file_operations proc_oom_adjust_operations = {
        .write          = oom_adjust_write,
 };
 
+static ssize_t clear_refs_write(struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF], *end;
+       struct mm_struct *mm;
+
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count))
+               return -EFAULT;
+       if (!simple_strtol(buffer, &end, 0))
+               return -EINVAL;
+       if (*end == '\n')
+               end++;
+       task = get_proc_task(file->f_path.dentry->d_inode);
+       if (!task)
+               return -ESRCH;
+       mm = get_task_mm(task);
+       if (mm) {
+               clear_refs_smap(mm);
+               mmput(mm);
+       }
+       put_task_struct(task);
+       if (end - buffer == 0)
+               return -EIO;
+       return end - buffer;
+}
+
+static struct file_operations proc_clear_refs_operations = {
+       .write          = clear_refs_write,
+};
+
 #ifdef CONFIG_AUDITSYSCALL
 #define TMPBUFLEN 21
 static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
@@ -1851,6 +1885,7 @@ static struct pid_entry tgid_base_stuff[] = {
        REG("mounts",     S_IRUGO, mounts),
        REG("mountstats", S_IRUSR, mountstats),
 #ifdef CONFIG_MMU
+       REG("clear_refs", S_IWUSR, clear_refs),
        REG("smaps",      S_IRUGO, smaps),
 #endif
 #ifdef CONFIG_SECURITY
@@ -2132,6 +2167,7 @@ static struct pid_entry tid_base_stuff[] = {
        LNK("exe",       exe),
        REG("mounts",    S_IRUGO, mounts),
 #ifdef CONFIG_MMU
+       REG("clear_refs", S_IWUSR, clear_refs),
        REG("smaps",     S_IRUGO, smaps),
 #endif
 #ifdef CONFIG_SECURITY
index c372eb1..22b1158 100644 (file)
@@ -109,8 +109,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct proc_inode *ei = (struct proc_inode *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index e2c4c0a..75ec652 100644 (file)
@@ -398,8 +398,6 @@ static const struct file_operations proc_modules_operations = {
 #endif
 
 #ifdef CONFIG_SLAB
-extern struct seq_operations slabinfo_op;
-extern ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
 static int slabinfo_open(struct inode *inode, struct file *file)
 {
        return seq_open(file, &slabinfo_op);
index 7445980..4008c06 100644 (file)
@@ -120,6 +120,14 @@ struct mem_size_stats
        unsigned long shared_dirty;
        unsigned long private_clean;
        unsigned long private_dirty;
+       unsigned long referenced;
+};
+
+struct pmd_walker {
+       struct vm_area_struct *vma;
+       void *private;
+       void (*action)(struct vm_area_struct *, pmd_t *, unsigned long,
+                      unsigned long, void *);
 };
 
 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
@@ -181,18 +189,20 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
 
        if (mss)
                seq_printf(m,
-                          "Size:          %8lu kB\n"
-                          "Rss:           %8lu kB\n"
-                          "Shared_Clean:  %8lu kB\n"
-                          "Shared_Dirty:  %8lu kB\n"
-                          "Private_Clean: %8lu kB\n"
-                          "Private_Dirty: %8lu kB\n",
+                          "Size:           %8lu kB\n"
+                          "Rss:            %8lu kB\n"
+                          "Shared_Clean:   %8lu kB\n"
+                          "Shared_Dirty:   %8lu kB\n"
+                          "Private_Clean:  %8lu kB\n"
+                          "Private_Dirty:  %8lu kB\n"
+                          "Referenced:     %8lu kB\n",
                           (vma->vm_end - vma->vm_start) >> 10,
                           mss->resident >> 10,
                           mss->shared_clean  >> 10,
                           mss->shared_dirty  >> 10,
                           mss->private_clean >> 10,
-                          mss->private_dirty >> 10);
+                          mss->private_dirty >> 10,
+                          mss->referenced >> 10);
 
        if (m->count < m->size)  /* vma is copied successfully */
                m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
@@ -205,15 +215,16 @@ static int show_map(struct seq_file *m, void *v)
 }
 
 static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+                           unsigned long addr, unsigned long end,
+                           void *private)
 {
+       struct mem_size_stats *mss = private;
        pte_t *pte, ptent;
        spinlock_t *ptl;
        struct page *page;
 
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-       do {
+       for (; addr != end; pte++, addr += PAGE_SIZE) {
                ptent = *pte;
                if (!pte_present(ptent))
                        continue;
@@ -224,6 +235,9 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                if (!page)
                        continue;
 
+               /* Accumulate the size in pages that have been accessed. */
+               if (pte_young(ptent) || PageReferenced(page))
+                       mss->referenced += PAGE_SIZE;
                if (page_mapcount(page) >= 2) {
                        if (pte_dirty(ptent))
                                mss->shared_dirty += PAGE_SIZE;
@@ -235,57 +249,99 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        else
                                mss->private_clean += PAGE_SIZE;
                }
-       } while (pte++, addr += PAGE_SIZE, addr != end);
+       }
        pte_unmap_unlock(pte - 1, ptl);
        cond_resched();
 }
 
-static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+                                unsigned long addr, unsigned long end,
+                                void *private)
+{
+       pte_t *pte, ptent;
+       spinlock_t *ptl;
+       struct page *page;
+
+       pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+       for (; addr != end; pte++, addr += PAGE_SIZE) {
+               ptent = *pte;
+               if (!pte_present(ptent))
+                       continue;
+
+               page = vm_normal_page(vma, addr, ptent);
+               if (!page)
+                       continue;
+
+               /* Clear accessed and referenced bits. */
+               ptep_test_and_clear_young(vma, addr, pte);
+               ClearPageReferenced(page);
+       }
+       pte_unmap_unlock(pte - 1, ptl);
+       cond_resched();
+}
+
+static inline void walk_pmd_range(struct pmd_walker *walker, pud_t *pud,
+                                 unsigned long addr, unsigned long end)
 {
        pmd_t *pmd;
        unsigned long next;
 
-       pmd = pmd_offset(pud, addr);
-       do {
+       for (pmd = pmd_offset(pud, addr); addr != end;
+            pmd++, addr = next) {
                next = pmd_addr_end(addr, end);
                if (pmd_none_or_clear_bad(pmd))
                        continue;
-               smaps_pte_range(vma, pmd, addr, next, mss);
-       } while (pmd++, addr = next, addr != end);
+               walker->action(walker->vma, pmd, addr, next, walker->private);
+       }
 }
 
-static inline void smaps_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+static inline void walk_pud_range(struct pmd_walker *walker, pgd_t *pgd,
+                                 unsigned long addr, unsigned long end)
 {
        pud_t *pud;
        unsigned long next;
 
-       pud = pud_offset(pgd, addr);
-       do {
+       for (pud = pud_offset(pgd, addr); addr != end;
+            pud++, addr = next) {
                next = pud_addr_end(addr, end);
                if (pud_none_or_clear_bad(pud))
                        continue;
-               smaps_pmd_range(vma, pud, addr, next, mss);
-       } while (pud++, addr = next, addr != end);
+               walk_pmd_range(walker, pud, addr, next);
+       }
 }
 
-static inline void smaps_pgd_range(struct vm_area_struct *vma,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+/*
+ * walk_page_range - walk the page tables of a VMA with a callback
+ * @vma - VMA to walk
+ * @action - callback invoked for every bottom-level (PTE) page table
+ * @private - private data passed to the callback function
+ *
+ * Recursively walk the page table for the memory area in a VMA, calling
+ * a callback for every bottom-level (PTE) page table.
+ */
+static inline void walk_page_range(struct vm_area_struct *vma,
+                                  void (*action)(struct vm_area_struct *,
+                                                 pmd_t *, unsigned long,
+                                                 unsigned long, void *),
+                                  void *private)
 {
+       unsigned long addr = vma->vm_start;
+       unsigned long end = vma->vm_end;
+       struct pmd_walker walker = {
+               .vma            = vma,
+               .private        = private,
+               .action         = action,
+       };
        pgd_t *pgd;
        unsigned long next;
 
-       pgd = pgd_offset(vma->vm_mm, addr);
-       do {
+       for (pgd = pgd_offset(vma->vm_mm, addr); addr != end;
+            pgd++, addr = next) {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
                        continue;
-               smaps_pud_range(vma, pgd, addr, next, mss);
-       } while (pgd++, addr = next, addr != end);
+               walk_pud_range(&walker, pgd, addr, next);
+       }
 }
 
 static int show_smap(struct seq_file *m, void *v)
@@ -295,10 +351,22 @@ static int show_smap(struct seq_file *m, void *v)
 
        memset(&mss, 0, sizeof mss);
        if (vma->vm_mm && !is_vm_hugetlb_page(vma))
-               smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss);
+               walk_page_range(vma, smaps_pte_range, &mss);
        return show_map_internal(m, v, &mss);
 }
 
+void clear_refs_smap(struct mm_struct *mm)
+{
+       struct vm_area_struct *vma;
+
+       down_read(&mm->mmap_sem);
+       for (vma = mm->mmap; vma; vma = vma->vm_next)
+               if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+                       walk_page_range(vma, clear_refs_pte_range, NULL);
+       flush_tlb_mm(mm);
+       up_read(&mm->mmap_sem);
+}
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
        struct proc_maps_private *priv = m->private;
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 83bc8e7..75fc849 100644 (file)
@@ -536,8 +536,7 @@ static void init_once(void *foo, struct kmem_cache * cachep,
 {
        struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
 
index f13a7f1..7054aae 100644 (file)
@@ -511,8 +511,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags
 {
        struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                INIT_LIST_HEAD(&ei->i_prealloc_list);
                inode_init_once(&ei->vfs_inode);
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
index 2cac562..bf6e582 100644 (file)
@@ -410,11 +410,7 @@ static struct page *reiserfs_get_page(struct inode *dir, unsigned long n)
        mapping_set_gfp_mask(mapping, GFP_NOFS);
        page = read_mapping_page(mapping, n, NULL);
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
                kmap(page);
-               if (!PageUptodate(page))
-                       goto fail;
-
                if (PageError(page))
                        goto fail;
        }
index fd60101..8042851 100644 (file)
@@ -570,8 +570,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct romfs_inode_info *ei = (struct romfs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index 5faba4f..424a3dd 100644 (file)
@@ -69,9 +69,8 @@ static void smb_destroy_inode(struct inode *inode)
 static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct smb_inode_info *ei = (struct smb_inode_info *) foo;
-       unsigned long flagmask = SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR;
 
-       if ((flags & flagmask) == SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
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 ebf7007..e566b38 100644 (file)
@@ -54,17 +54,9 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
 {
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
-       if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
+       if (!IS_ERR(page))
                kmap(page);
-               if (!PageUptodate(page))
-                       goto fail;
-       }
        return page;
-
-fail:
-       dir_put_page(page);
-       return ERR_PTR(-EIO);
 }
 
 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
index 9311cac..3152d74 100644 (file)
@@ -322,8 +322,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
 {
        struct sysv_inode_info *si = (struct sysv_inode_info *)p;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-                       SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&si->vfs_inode);
 }
 
index 8672b88..023b304 100644 (file)
@@ -134,9 +134,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct udf_inode_info *ei = (struct udf_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
-       {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                ei->i_ext.i_data = NULL;
                inode_init_once(&ei->vfs_inode);
        }
index 4890ddf..4fb8b2e 100644 (file)
@@ -180,13 +180,9 @@ fail:
 static struct page *ufs_get_page(struct inode *dir, unsigned long n)
 {
        struct address_space *mapping = dir->i_mapping;
-       struct page *page = read_cache_page(mapping, n,
-                               (filler_t*)mapping->a_ops->readpage, NULL);
+       struct page *page = read_mapping_page(mapping, n, NULL);
        if (!IS_ERR(page)) {
-               wait_on_page_locked(page);
                kmap(page);
-               if (!PageUptodate(page))
-                       goto fail;
                if (!PageChecked(page))
                        ufs_check_page(page);
                if (PageError(page))
index b5a6461..be7c48c 100644 (file)
@@ -1237,8 +1237,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
 {
        struct ufs_inode_info *ei = (struct ufs_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
  
index 1743757..84357f1 100644 (file)
@@ -251,13 +251,11 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
 
        page = find_lock_page(mapping, index);
        if (!page) {
-               page = read_cache_page(mapping, index,
-                                      (filler_t*)mapping->a_ops->readpage,
-                                      NULL);
+               page = read_mapping_page(mapping, index, NULL);
 
                if (IS_ERR(page)) {
                        printk(KERN_ERR "ufs_change_blocknr: "
-                              "read_cache_page error: ino %lu, index: %lu\n",
+                              "read_mapping_page error: ino %lu, index: %lu\n",
                               mapping->host->i_ino, index);
                        goto out;
                }
index 2f2c40d..14e2cbe 100644 (file)
@@ -360,8 +360,7 @@ xfs_fs_inode_init_once(
        kmem_zone_t             *zonep,
        unsigned long           flags)
 {
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-                     SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
 }
 
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;
index 69ffd93..eeb3bef 100644 (file)
@@ -92,5 +92,27 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK         \
                                 | _TIF_SYSCALL_TRACE)
 
+#define ALPHA_UAC_SHIFT                6
+#define ALPHA_UAC_MASK         (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \
+                                1 << TIF_UAC_SIGBUS)
+
+#define SET_UNALIGN_CTL(task,value)    ({                                   \
+       (task)->thread_info->flags = (((task)->thread_info->flags &          \
+               ~ALPHA_UAC_MASK)                                             \
+               | (((value) << ALPHA_UAC_SHIFT)       & (1<<TIF_UAC_NOPRINT))\
+               | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \
+               | (((value) << (ALPHA_UAC_SHIFT - 1)) & (1<<TIF_UAC_NOFIX)));\
+       0; })
+
+#define GET_UNALIGN_CTL(task,value)    ({                              \
+       put_user(((task)->thread_info->flags & (1 << TIF_UAC_NOPRINT))  \
+                 >> ALPHA_UAC_SHIFT                                    \
+                | ((task)->thread_info->flags & (1 << TIF_UAC_SIGBUS)) \
+                >> (ALPHA_UAC_SHIFT + 1)                               \
+                | ((task)->thread_info->flags & (1 << TIF_UAC_NOFIX))  \
+                >> (ALPHA_UAC_SHIFT - 1),                              \
+                (int __user *)(value));                                \
+       })
+
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
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) */
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;
diff --git a/include/asm-blackfin/Kbuild b/include/asm-blackfin/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-blackfin/a.out.h b/include/asm-blackfin/a.out.h
new file mode 100644 (file)
index 0000000..d37a684
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __BFIN_A_OUT_H__
+#define __BFIN_A_OUT_H__
+
+struct exec {
+       unsigned long a_info;   /* Use macros N_MAGIC, etc for access */
+       unsigned a_text;        /* length of text, in bytes */
+       unsigned a_data;        /* length of data, in bytes */
+       unsigned a_bss;         /* length of uninitialized data area for file, in bytes */
+       unsigned a_syms;        /* length of symbol table data in file, in bytes */
+       unsigned a_entry;       /* start address */
+       unsigned a_trsize;      /* length of relocation info for text, in bytes */
+       unsigned a_drsize;      /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)    ((a).a_trsize)
+#define N_DRSIZE(a)    ((a).a_drsize)
+#define N_SYMSIZE(a)   ((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP      TASK_SIZE
+
+#endif
+
+#endif                         /* __BFIN_A_OUT_H__ */
diff --git a/include/asm-blackfin/atomic.h b/include/asm-blackfin/atomic.h
new file mode 100644 (file)
index 0000000..7cf5087
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef __ARCH_BLACKFIN_ATOMIC__
+#define __ARCH_BLACKFIN_ATOMIC__
+
+#include <asm/system.h>        /* local_irq_XXX() */
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ * Generally we do not concern about SMP BFIN systems, so we don't have
+ * to deal with that.
+ *
+ * Tony Kou (tonyko@lineo.ca)   Lineo Inc.   2001
+ */
+
+typedef struct {
+       int counter;
+} atomic_t;
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v)         ((v)->counter)
+#define atomic_set(v, i)       (((v)->counter) = i)
+
+static __inline__ void atomic_add(int i, atomic_t * v)
+{
+       long flags;
+
+       local_irq_save(flags);
+       v->counter += i;
+       local_irq_restore(flags);
+}
+
+static __inline__ void atomic_sub(int i, atomic_t * v)
+{
+       long flags;
+
+       local_irq_save(flags);
+       v->counter -= i;
+       local_irq_restore(flags);
+
+}
+
+static inline int atomic_add_return(int i, atomic_t * v)
+{
+       int __temp = 0;
+       long flags;
+
+       local_irq_save(flags);
+       v->counter += i;
+       __temp = v->counter;
+       local_irq_restore(flags);
+
+
+       return __temp;
+}
+
+#define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
+static inline int atomic_sub_return(int i, atomic_t * v)
+{
+       int __temp = 0;
+       long flags;
+
+       local_irq_save(flags);
+       v->counter -= i;
+       __temp = v->counter;
+       local_irq_restore(flags);
+
+       return __temp;
+}
+
+static __inline__ void atomic_inc(volatile atomic_t * v)
+{
+       long flags;
+
+       local_irq_save(flags);
+       v->counter++;
+       local_irq_restore(flags);
+}
+
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#define atomic_add_unless(v, a, u)                             \
+({                                                             \
+       int c, old;                                             \
+       c = atomic_read(v);                                     \
+       while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
+               c = old;                                        \
+       c != (u);                                               \
+})
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+static __inline__ void atomic_dec(volatile atomic_t * v)
+{
+       long flags;
+
+       local_irq_save(flags);
+       v->counter--;
+       local_irq_restore(flags);
+}
+
+static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t * v)
+{
+       long flags;
+
+       local_irq_save(flags);
+       v->counter &= ~mask;
+       local_irq_restore(flags);
+}
+
+static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v)
+{
+       long flags;
+
+       local_irq_save(flags);
+       v->counter |= mask;
+       local_irq_restore(flags);
+}
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+#include <asm-generic/atomic.h>
+
+#endif                         /* __ARCH_BLACKFIN_ATOMIC __ */
diff --git a/include/asm-blackfin/auxvec.h b/include/asm-blackfin/auxvec.h
new file mode 100644 (file)
index 0000000..215506c
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMBFIN_AUXVEC_H
+#define __ASMBFIN_AUXVEC_H
+
+#endif
diff --git a/include/asm-blackfin/bf5xx_timers.h b/include/asm-blackfin/bf5xx_timers.h
new file mode 100644 (file)
index 0000000..86c7703
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * include/asm/bf5xx_timers.h
+ *
+ * This file contains the major Data structures and constants
+ * used for General Purpose Timer Implementation in BF5xx
+ *
+ * Copyright (C) 2005 John DeHority
+ * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de)
+ *
+ */
+
+#ifndef _BLACKFIN_TIMERS_H_
+#define _BLACKFIN_TIMERS_H_
+
+#undef MAX_BLACKFIN_GPTIMERS
+/*
+ * BF537: 8 timers:
+ */
+#if defined(CONFIG_BF537)
+#  define MAX_BLACKFIN_GPTIMERS 8
+#  define TIMER0_GROUP_REG     TIMER_ENABLE
+#endif
+/*
+ * BF561: 12 timers:
+ */
+#if defined(CONFIG_BF561)
+#  define MAX_BLACKFIN_GPTIMERS 12
+#  define TIMER0_GROUP_REG     TMRS8_ENABLE
+#  define TIMER8_GROUP_REG     TMRS4_ENABLE
+#endif
+/*
+ * All others: 3 timers:
+ */
+#if !defined(MAX_BLACKFIN_GPTIMERS)
+#  define MAX_BLACKFIN_GPTIMERS 3
+#  define TIMER0_GROUP_REG     TIMER_ENABLE
+#endif
+
+#define BLACKFIN_GPTIMER_IDMASK ((1UL << MAX_BLACKFIN_GPTIMERS) - 1)
+#define BFIN_TIMER_OCTET(x) ((x) >> 3)
+
+/* used in masks for timer_enable() and timer_disable() */
+#define TIMER0bit  0x0001  /*  0001b */
+#define TIMER1bit  0x0002  /*  0010b */
+#define TIMER2bit  0x0004  /*  0100b */
+
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+#  define TIMER3bit  0x0008
+#  define TIMER4bit  0x0010
+#  define TIMER5bit  0x0020
+#  define TIMER6bit  0x0040
+#  define TIMER7bit  0x0080
+#endif
+
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+#  define TIMER8bit  0x0100
+#  define TIMER9bit  0x0200
+#  define TIMER10bit 0x0400
+#  define TIMER11bit 0x0800
+#endif
+
+#define TIMER0_id   0
+#define TIMER1_id   1
+#define TIMER2_id   2
+
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+#  define TIMER3_id   3
+#  define TIMER4_id   4
+#  define TIMER5_id   5
+#  define TIMER6_id   6
+#  define TIMER7_id   7
+#endif
+
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+#  define TIMER8_id   8
+#  define TIMER9_id   9
+#  define TIMER10_id 10
+#  define TIMER11_id 11
+#endif
+
+/* associated timers for ppi framesync: */
+
+#if defined(CONFIG_BF561)
+#  define FS0_1_TIMER_ID   TIMER8_id
+#  define FS0_2_TIMER_ID   TIMER9_id
+#  define FS1_1_TIMER_ID   TIMER10_id
+#  define FS1_2_TIMER_ID   TIMER11_id
+#  define FS0_1_TIMER_BIT  TIMER8bit
+#  define FS0_2_TIMER_BIT  TIMER9bit
+#  define FS1_1_TIMER_BIT  TIMER10bit
+#  define FS1_2_TIMER_BIT  TIMER11bit
+#  undef FS1_TIMER_ID
+#  undef FS2_TIMER_ID
+#  undef FS1_TIMER_BIT
+#  undef FS2_TIMER_BIT
+#else
+#  define FS1_TIMER_ID  TIMER0_id
+#  define FS2_TIMER_ID  TIMER1_id
+#  define FS1_TIMER_BIT TIMER0bit
+#  define FS2_TIMER_BIT TIMER1bit
+#endif
+
+/*
+** Timer Configuration Register Bits
+*/
+#define TIMER_ERR           0xC000
+#define TIMER_ERR_OVFL      0x4000
+#define TIMER_ERR_PROG_PER  0x8000
+#define TIMER_ERR_PROG_PW   0xC000
+#define TIMER_EMU_RUN       0x0200
+#define        TIMER_TOGGLE_HI     0x0100
+#define        TIMER_CLK_SEL       0x0080
+#define TIMER_OUT_DIS       0x0040
+#define TIMER_TIN_SEL       0x0020
+#define TIMER_IRQ_ENA       0x0010
+#define TIMER_PERIOD_CNT    0x0008
+#define TIMER_PULSE_HI      0x0004
+#define TIMER_MODE          0x0003
+#define TIMER_MODE_PWM      0x0001
+#define TIMER_MODE_WDTH     0x0002
+#define TIMER_MODE_EXT_CLK  0x0003
+
+/*
+** Timer Status Register Bits
+*/
+#define TIMER_STATUS_TIMIL0 0x0001
+#define TIMER_STATUS_TIMIL1 0x0002
+#define TIMER_STATUS_TIMIL2 0x0004
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+#  define TIMER_STATUS_TIMIL3 0x00000008
+#  define TIMER_STATUS_TIMIL4 0x00010000
+#  define TIMER_STATUS_TIMIL5 0x00020000
+#  define TIMER_STATUS_TIMIL6 0x00040000
+#  define TIMER_STATUS_TIMIL7 0x00080000
+#  if (MAX_BLACKFIN_GPTIMERS > 8)
+#    define TIMER_STATUS_TIMIL8  0x0001
+#    define TIMER_STATUS_TIMIL9  0x0002
+#    define TIMER_STATUS_TIMIL10 0x0004
+#    define TIMER_STATUS_TIMIL11 0x0008
+#  endif
+#  define TIMER_STATUS_INTR   0x000F000F
+#else
+#  define TIMER_STATUS_INTR   0x0007   /* any timer interrupt */
+#endif
+
+#define TIMER_STATUS_TOVF0  0x0010     /* timer 0 overflow error */
+#define TIMER_STATUS_TOVF1  0x0020
+#define TIMER_STATUS_TOVF2  0x0040
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+#  define TIMER_STATUS_TOVF3  0x00000080
+#  define TIMER_STATUS_TOVF4  0x00100000
+#  define TIMER_STATUS_TOVF5  0x00200000
+#  define TIMER_STATUS_TOVF6  0x00400000
+#  define TIMER_STATUS_TOVF7  0x00800000
+#  if (MAX_BLACKFIN_GPTIMERS > 8)
+#    define TIMER_STATUS_TOVF8   0x0010
+#    define TIMER_STATUS_TOVF9   0x0020
+#    define TIMER_STATUS_TOVF10  0x0040
+#    define TIMER_STATUS_TOVF11  0x0080
+#  endif
+#  define TIMER_STATUS_OFLOW  0x00F000F0
+#else
+#  define TIMER_STATUS_OFLOW  0x0070   /* any timer overflow */
+#endif
+
+/*
+** Timer Slave Enable Status : write 1 to clear
+*/
+#define TIMER_STATUS_TRUN0  0x1000
+#define TIMER_STATUS_TRUN1  0x2000
+#define TIMER_STATUS_TRUN2  0x4000
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+#  define TIMER_STATUS_TRUN3  0x00008000
+#  define TIMER_STATUS_TRUN4  0x10000000
+#  define TIMER_STATUS_TRUN5  0x20000000
+#  define TIMER_STATUS_TRUN6  0x40000000
+#  define TIMER_STATUS_TRUN7  0x80000000
+#  define TIMER_STATUS_TRUN   0xF000F000
+#  if (MAX_BLACKFIN_GPTIMERS > 8)
+#    define TIMER_STATUS_TRUN8  0x1000
+#    define TIMER_STATUS_TRUN9  0x2000
+#    define TIMER_STATUS_TRUN10 0x4000
+#    define TIMER_STATUS_TRUN11 0x8000
+#  endif
+#else
+#  define TIMER_STATUS_TRUN   0x7000
+#endif
+
+/*******************************************************************************
+*      GP_TIMER API's
+*******************************************************************************/
+
+void  set_gptimer_pwidth    (int timer_id, int width);
+int   get_gptimer_pwidth    (int timer_id);
+void  set_gptimer_period    (int timer_id, int period);
+int   get_gptimer_period    (int timer_id);
+int   get_gptimer_count     (int timer_id);
+short get_gptimer_intr      (int timer_id);
+void  set_gptimer_config    (int timer_id, short config);
+short get_gptimer_config    (int timer_id);
+void  set_gptimer_pulse_hi  (int timer_id);
+void  clear_gptimer_pulse_hi(int timer_id);
+void  enable_gptimers       (short mask);
+void  disable_gptimers      (short mask);
+short get_enabled_timers    (void);
+int   get_gptimer_status    (int octet);
+void  set_gptimer_status    (int octet, int value);
+
+#endif
diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
new file mode 100644 (file)
index 0000000..e37f816
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * File:         include/asm-blackfin/bfin-global.h
+ * Based on:
+ * Author: *
+ * Created:
+ * Description:  Global extern defines for blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _BFIN_GLOBAL_H_
+#define _BFIN_GLOBAL_H_
+
+#ifndef __ASSEMBLY__
+
+#include <asm-generic/sections.h>
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+
+#if defined(CONFIG_DMA_UNCACHED_2M)
+# define DMA_UNCACHED_REGION (2 * 1024 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_1M)
+# define DMA_UNCACHED_REGION (1024 * 1024)
+#else
+# define DMA_UNCACHED_REGION (0)
+#endif
+
+extern unsigned long get_cclk(void);
+extern unsigned long get_sclk(void);
+
+extern void dump_thread(struct pt_regs *regs, struct user *dump);
+extern void dump_bfin_regs(struct pt_regs *fp, void *retaddr);
+extern void dump_bfin_trace_buffer(void);
+
+extern int init_arch_irq(void);
+extern void bfin_reset(void);
+extern void _cplb_hdr(void);
+/* Blackfin cache functions */
+extern void bfin_icache_init(void);
+extern void bfin_dcache_init(void);
+extern int read_iloc(void);
+extern int bfin_console_init(void);
+extern asmlinkage void lower_to_irq14(void);
+extern void init_dma(void);
+extern void program_IAR(void);
+extern void evt14_softirq(void);
+extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
+extern void bfin_gpio_interrupt_setup(int irq, int irq_pfx, int type);
+
+extern void *l1_data_A_sram_alloc(size_t);
+extern void *l1_data_B_sram_alloc(size_t);
+extern void *l1_inst_sram_alloc(size_t);
+extern void *l1_data_sram_alloc(size_t);
+extern void *l1_data_sram_zalloc(size_t);
+extern int l1_data_A_sram_free(const void*);
+extern int l1_data_B_sram_free(const void*);
+extern int l1_inst_sram_free(const void*);
+extern int l1_data_sram_free(const void*);
+extern int sram_free(const void*);
+
+#define L1_INST_SRAM           0x00000001
+#define L1_DATA_A_SRAM         0x00000002
+#define L1_DATA_B_SRAM         0x00000004
+#define L1_DATA_SRAM           0x00000006
+extern void *sram_alloc_with_lsl(size_t, unsigned long);
+extern int sram_free_with_lsl(const void*);
+
+extern void led_on(int);
+extern void led_off(int);
+extern void led_toggle(int);
+extern void led_disp_num(int);
+extern void led_toggle_num(int);
+extern void init_leds(void);
+
+extern char *bfin_board_name __attribute__ ((weak));
+extern unsigned long wall_jiffies;
+extern unsigned long ipdt_table[];
+extern unsigned long dpdt_table[];
+extern unsigned long icplb_table[];
+extern unsigned long dcplb_table[];
+
+extern unsigned long ipdt_swapcount_table[];
+extern unsigned long dpdt_swapcount_table[];
+
+extern unsigned long table_start, table_end;
+
+extern struct file_operations dpmc_fops;
+extern char _start;
+extern unsigned long _ramstart, _ramend, _rambase;
+extern unsigned long memory_start, memory_end, physical_mem_end;
+extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
+    _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _ebss_b_l1[];
+
+#ifdef CONFIG_MTD_UCLINUX
+extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
+#endif
+
+#endif
+
+#endif                         /* _BLACKFIN_H_ */
diff --git a/include/asm-blackfin/bfin5xx_spi.h b/include/asm-blackfin/bfin5xx_spi.h
new file mode 100644 (file)
index 0000000..95c1c95
--- /dev/null
@@ -0,0 +1,170 @@
+/************************************************************
+*
+* Copyright (C) 2004, Analog Devices. All Rights Reserved
+*
+* FILE bfin5xx_spi.h
+* PROGRAMMER(S): Luke Yang (Analog Devices Inc.)
+*
+*
+* DATE OF CREATION: March. 10th 2006
+*
+* SYNOPSIS:
+*
+* DESCRIPTION: header file for SPI controller driver for Blackfin5xx.
+**************************************************************
+
+* MODIFICATION HISTORY:
+* March 10, 2006  bfin5xx_spi.h Created. (Luke Yang)
+
+************************************************************/
+
+#ifndef _SPI_CHANNEL_H_
+#define _SPI_CHANNEL_H_
+
+#define SPI0_REGBASE       0xffc00500
+
+#define SPI_READ              0
+#define SPI_WRITE             1
+
+#define SPI_CTRL_OFF            0x0
+#define SPI_FLAG_OFF            0x4
+#define SPI_STAT_OFF            0x8
+#define SPI_TXBUFF_OFF          0xc
+#define SPI_RXBUFF_OFF          0x10
+#define SPI_BAUD_OFF            0x14
+#define SPI_SHAW_OFF            0x18
+
+#define CMD_SPI_OUT_ENABLE    1
+#define CMD_SPI_SET_BAUDRATE  2
+#define CMD_SPI_SET_POLAR     3
+#define CMD_SPI_SET_PHASE     4
+#define CMD_SPI_SET_MASTER    5
+#define CMD_SPI_SET_SENDOPT   6
+#define CMD_SPI_SET_RECVOPT   7
+#define CMD_SPI_SET_ORDER     8
+#define CMD_SPI_SET_LENGTH16  9
+#define CMD_SPI_GET_STAT      11
+#define CMD_SPI_GET_CFG       12
+#define CMD_SPI_SET_CSAVAIL   13
+#define CMD_SPI_SET_CSHIGH    14       /* CS unavail */
+#define CMD_SPI_SET_CSLOW     15       /* CS avail */
+#define CMD_SPI_MISO_ENABLE   16
+#define CMD_SPI_SET_CSENABLE  17
+#define CMD_SPI_SET_CSDISABLE 18
+
+#define CMD_SPI_SET_TRIGGER_MODE  19
+#define CMD_SPI_SET_TRIGGER_SENSE 20
+#define CMD_SPI_SET_TRIGGER_EDGE  21
+#define CMD_SPI_SET_TRIGGER_LEVEL 22
+
+#define CMD_SPI_SET_TIME_SPS     23
+#define CMD_SPI_SET_TIME_SAMPLES  24
+#define CMD_SPI_GET_SYSTEMCLOCK   25
+
+#define CMD_SPI_SET_WRITECONTINUOUS     26
+#define CMD_SPI_SET_SKFS               27
+
+#define CMD_SPI_GET_ALLCONFIG 32       /* For debug */
+
+#define SPI_DEFAULT_BARD    0x0100
+
+#define SPI0_IRQ_NUM        IRQ_SPI
+#define SPI_ERR_TRIG      -1
+
+#define BIT_CTL_ENABLE      0x4000
+#define BIT_CTL_OPENDRAIN   0x2000
+#define BIT_CTL_MASTER      0x1000
+#define BIT_CTL_POLAR       0x0800
+#define BIT_CTL_PHASE       0x0400
+#define BIT_CTL_BITORDER    0x0200
+#define BIT_CTL_WORDSIZE    0x0100
+#define BIT_CTL_MISOENABLE  0x0020
+#define BIT_CTL_RXMOD       0x0000
+#define BIT_CTL_TXMOD       0x0001
+#define BIT_CTL_TIMOD_DMA_TX 0x0003
+#define BIT_CTL_TIMOD_DMA_RX 0x0002
+#define BIT_CTL_SENDOPT     0x0004
+#define BIT_CTL_TIMOD       0x0003
+
+#define BIT_STAT_SPIF       0x0001
+#define BIT_STAT_MODF       0x0002
+#define BIT_STAT_TXE        0x0004
+#define BIT_STAT_TXS        0x0008
+#define BIT_STAT_RBSY       0x0010
+#define BIT_STAT_RXS        0x0020
+#define BIT_STAT_TXCOL      0x0040
+#define BIT_STAT_CLR        0xFFFF
+
+#define BIT_STU_SENDOVER    0x0001
+#define BIT_STU_RECVFULL    0x0020
+
+#define CFG_SPI_ENABLE      1
+#define CFG_SPI_DISABLE     0
+
+#define CFG_SPI_OUTENABLE   1
+#define CFG_SPI_OUTDISABLE  0
+
+#define CFG_SPI_ACTLOW      1
+#define CFG_SPI_ACTHIGH     0
+
+#define CFG_SPI_PHASESTART  1
+#define CFG_SPI_PHASEMID    0
+
+#define CFG_SPI_MASTER      1
+#define CFG_SPI_SLAVE       0
+
+#define CFG_SPI_SENELAST    0
+#define CFG_SPI_SENDZERO    1
+
+#define CFG_SPI_RCVFLUSH    1
+#define CFG_SPI_RCVDISCARD  0
+
+#define CFG_SPI_LSBFIRST    1
+#define CFG_SPI_MSBFIRST    0
+
+#define CFG_SPI_WORDSIZE16  1
+#define CFG_SPI_WORDSIZE8   0
+
+#define CFG_SPI_MISOENABLE   1
+#define CFG_SPI_MISODISABLE  0
+
+#define CFG_SPI_READ      0x00
+#define CFG_SPI_WRITE     0x01
+#define CFG_SPI_DMAREAD   0x02
+#define CFG_SPI_DMAWRITE  0x03
+
+#define CFG_SPI_CSCLEARALL  0
+#define CFG_SPI_CHIPSEL1    1
+#define CFG_SPI_CHIPSEL2    2
+#define CFG_SPI_CHIPSEL3    3
+#define CFG_SPI_CHIPSEL4    4
+#define CFG_SPI_CHIPSEL5    5
+#define CFG_SPI_CHIPSEL6    6
+#define CFG_SPI_CHIPSEL7    7
+
+#define CFG_SPI_CS1VALUE    1
+#define CFG_SPI_CS2VALUE    2
+#define CFG_SPI_CS3VALUE    3
+#define CFG_SPI_CS4VALUE    4
+#define CFG_SPI_CS5VALUE    5
+#define CFG_SPI_CS6VALUE    6
+#define CFG_SPI_CS7VALUE    7
+
+/* device.platform_data for SSP controller devices */
+struct bfin5xx_spi_master {
+       u16 num_chipselect;
+       u8 enable_dma;
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct bfin5xx_spi_chip {
+       u16 ctl_reg;
+       u8 enable_dma;
+       u8 bits_per_word;
+       u8 cs_change_per_word;
+       u8 cs_chg_udelay;
+};
+
+#endif /* _SPI_CHANNEL_H_ */
diff --git a/include/asm-blackfin/bfin_simple_timer.h b/include/asm-blackfin/bfin_simple_timer.h
new file mode 100644 (file)
index 0000000..fccbb59
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _bfin_simple_timer_h_
+#define _bfin_simple_timer_h_
+
+#include <linux/ioctl.h>
+
+#define BFIN_SIMPLE_TIMER_IOCTL_MAGIC 't'
+
+#define BFIN_SIMPLE_TIMER_SET_PERIOD _IO (BFIN_SIMPLE_TIMER_IOCTL_MAGIC,  2)
+#define BFIN_SIMPLE_TIMER_START      _IO (BFIN_SIMPLE_TIMER_IOCTL_MAGIC,  6)
+#define BFIN_SIMPLE_TIMER_STOP       _IO (BFIN_SIMPLE_TIMER_IOCTL_MAGIC,  8)
+#define BFIN_SIMPLE_TIMER_READ       _IO (BFIN_SIMPLE_TIMER_IOCTL_MAGIC, 10)
+
+#endif
diff --git a/include/asm-blackfin/bfin_sport.h b/include/asm-blackfin/bfin_sport.h
new file mode 100644 (file)
index 0000000..c76ed8d
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * File:         include/asm-blackfin/bfin_sport.h
+ * Based on:
+ * Author:       Roy Huang (roy.huang@analog.com)
+ *
+ * Created:      Thu Aug. 24 2006
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __BFIN_SPORT_H__
+#define __BFIN_SPORT_H__
+
+#define SPORT_MAJOR    237
+#define SPORT_NR_DEVS  2
+
+/* Sport mode: it can be set to TDM, i2s or others */
+#define NORM_MODE      0x0
+#define TDM_MODE       0x1
+#define I2S_MODE       0x2
+
+/* Data format, normal, a-law or u-law */
+#define NORM_FORMAT    0x0
+#define ALAW_FORMAT    0x2
+#define ULAW_FORMAT    0x3
+struct sport_register;
+
+/* Function driver which use sport must initialize the structure */
+struct sport_config {
+       /*TDM (multichannels), I2S or other mode */
+       unsigned int mode:3;
+
+       /* if TDM mode is selected, channels must be set */
+       int channels;           /* Must be in 8 units */
+       unsigned int frame_delay:4;     /* Delay between frame sync pulse and first bit */
+
+       /* I2S mode */
+       unsigned int right_first:1;     /* Right stereo channel first */
+
+       /* In mormal mode, the following item need to be set */
+       unsigned int lsb_first:1;       /* order of transmit or receive data */
+       unsigned int fsync:1;   /* Frame sync required */
+       unsigned int data_indep:1;      /* data independent frame sync generated */
+       unsigned int act_low:1; /* Active low TFS */
+       unsigned int late_fsync:1;      /* Late frame sync */
+       unsigned int tckfe:1;
+       unsigned int sec_en:1;  /* Secondary side enabled */
+
+       /* Choose clock source */
+       unsigned int int_clk:1; /* Internal or external clock */
+
+       /* If external clock is used, the following fields are ignored */
+       int serial_clk;
+       int fsync_clk;
+
+       unsigned int data_format:2;     /*Normal, u-law or a-law */
+
+       int word_len;           /* How length of the word in bits, 3-32 bits */
+       int dma_enabled;
+};
+
+struct sport_register {
+       unsigned short tcr1;
+       unsigned short reserved0;
+       unsigned short tcr2;
+       unsigned short reserved1;
+       unsigned short tclkdiv;
+       unsigned short reserved2;
+       unsigned short tfsdiv;
+       unsigned short reserved3;
+       unsigned long tx;
+       unsigned long reserved_l0;
+       unsigned long rx;
+       unsigned long reserved_l1;
+       unsigned short rcr1;
+       unsigned short reserved4;
+       unsigned short rcr2;
+       unsigned short reserved5;
+       unsigned short rclkdiv;
+       unsigned short reserved6;
+       unsigned short rfsdiv;
+       unsigned short reserved7;
+       unsigned short stat;
+       unsigned short reserved8;
+       unsigned short chnl;
+       unsigned short reserved9;
+       unsigned short mcmc1;
+       unsigned short reserved10;
+       unsigned short mcmc2;
+       unsigned short reserved11;
+       unsigned long mtcs0;
+       unsigned long mtcs1;
+       unsigned long mtcs2;
+       unsigned long mtcs3;
+       unsigned long mrcs0;
+       unsigned long mrcs1;
+       unsigned long mrcs2;
+       unsigned long mrcs3;
+};
+
+#define SPORT_IOC_MAGIC                'P'
+#define SPORT_IOC_CONFIG       _IOWR('P', 0x01, struct sport_config)
+
+/* Test purpose */
+#define ENABLE_AD73311         _IOWR('P', 0x02, int)
+
+struct sport_dev {
+       struct cdev cdev;       /* Char device structure */
+
+       int sport_num;
+
+       int dma_rx_chan;
+       int dma_tx_chan;
+
+       int rx_irq;
+       unsigned char *rx_buf;  /* Buffer store the received data */
+       int rx_len;             /* How many bytes will be received */
+       int rx_received;        /* How many bytes has been received */
+
+       int tx_irq;
+       const unsigned char *tx_buf;
+       int tx_len;
+       int tx_sent;
+
+       int sport_err_irq;
+
+       struct mutex mutex;     /* mutual exclusion semaphore */
+       struct task_struct *task;
+
+       wait_queue_head_t waitq;
+       int     wait_con;
+       struct sport_register *regs;
+       struct sport_config config;
+};
+
+#define SPORT_TCR1     0
+#define        SPORT_TCR2      1
+#define        SPORT_TCLKDIV   2
+#define        SPORT_TFSDIV    3
+#define        SPORT_RCR1      8
+#define        SPORT_RCR2      9
+#define SPORT_RCLKDIV  10
+#define        SPORT_RFSDIV    11
+#define SPORT_CHANNEL  13
+#define SPORT_MCMC1    14
+#define SPORT_MCMC2    15
+#define SPORT_MTCS0    16
+#define SPORT_MTCS1    17
+#define SPORT_MTCS2    18
+#define SPORT_MTCS3    19
+#define SPORT_MRCS0    20
+#define SPORT_MRCS1    21
+#define SPORT_MRCS2    22
+#define SPORT_MRCS3    23
+
+#endif                         /*__BFIN_SPORT_H__*/
diff --git a/include/asm-blackfin/bitops.h b/include/asm-blackfin/bitops.h
new file mode 100644 (file)
index 0000000..27c2d0e
--- /dev/null
@@ -0,0 +1,213 @@
+#ifndef _BLACKFIN_BITOPS_H
+#define _BLACKFIN_BITOPS_H
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ */
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>     /* swab32 */
+#include <asm/system.h>                /* save_flags */
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffz.h>
+
+static __inline__ void set_bit(int nr, volatile unsigned long *addr)
+{
+       int *a = (int *)addr;
+       int mask;
+       unsigned long flags;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       local_irq_save(flags);
+       *a |= mask;
+       local_irq_restore(flags);
+}
+
+static __inline__ void __set_bit(int nr, volatile unsigned long *addr)
+{
+       int *a = (int *)addr;
+       int mask;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       *a |= mask;
+}
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit()     barrier()
+#define smp_mb__after_clear_bit()      barrier()
+
+static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
+{
+       int *a = (int *)addr;
+       int mask;
+       unsigned long flags;
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       local_irq_save(flags);
+       *a &= ~mask;
+       local_irq_restore(flags);
+}
+
+static __inline__ void __clear_bit(int nr, volatile unsigned long *addr)
+{
+       int *a = (int *)addr;
+       int mask;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       *a &= ~mask;
+}
+
+static __inline__ void change_bit(int nr, volatile unsigned long *addr)
+{
+       int mask, flags;
+       unsigned long *ADDR = (unsigned long *)addr;
+
+       ADDR += nr >> 5;
+       mask = 1 << (nr & 31);
+       local_irq_save(flags);
+       *ADDR ^= mask;
+       local_irq_restore(flags);
+}
+
+static __inline__ void __change_bit(int nr, volatile unsigned long *addr)
+{
+       int mask;
+       unsigned long *ADDR = (unsigned long *)addr;
+
+       ADDR += nr >> 5;
+       mask = 1 << (nr & 31);
+       *ADDR ^= mask;
+}
+
+static __inline__ int test_and_set_bit(int nr, void *addr)
+{
+       int mask, retval;
+       volatile unsigned int *a = (volatile unsigned int *)addr;
+       unsigned long flags;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       local_irq_save(flags);
+       retval = (mask & *a) != 0;
+       *a |= mask;
+       local_irq_restore(flags);
+
+       return retval;
+}
+
+static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+       int mask, retval;
+       volatile unsigned int *a = (volatile unsigned int *)addr;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       retval = (mask & *a) != 0;
+       *a |= mask;
+       return retval;
+}
+
+static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+       int mask, retval;
+       volatile unsigned int *a = (volatile unsigned int *)addr;
+       unsigned long flags;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       local_irq_save(flags);
+       retval = (mask & *a) != 0;
+       *a &= ~mask;
+       local_irq_restore(flags);
+
+       return retval;
+}
+
+static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+       int mask, retval;
+       volatile unsigned int *a = (volatile unsigned int *)addr;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       retval = (mask & *a) != 0;
+       *a &= ~mask;
+       return retval;
+}
+
+static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+       int mask, retval;
+       volatile unsigned int *a = (volatile unsigned int *)addr;
+       unsigned long flags;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       local_irq_save(flags);
+       retval = (mask & *a) != 0;
+       *a ^= mask;
+       local_irq_restore(flags);
+       return retval;
+}
+
+static __inline__ int __test_and_change_bit(int nr,
+                                           volatile unsigned long *addr)
+{
+       int mask, retval;
+       volatile unsigned int *a = (volatile unsigned int *)addr;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       retval = (mask & *a) != 0;
+       *a ^= mask;
+       return retval;
+}
+
+/*
+ * This routine doesn't need to be atomic.
+ */
+static __inline__ int __constant_test_bit(int nr, const void *addr)
+{
+       return ((1UL << (nr & 31)) &
+               (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
+}
+
+static __inline__ int __test_bit(int nr, const void *addr)
+{
+       int *a = (int *)addr;
+       int mask;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       return ((mask & *a) != 0);
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ __constant_test_bit((nr),(addr)) : \
+ __test_bit((nr),(addr)))
+
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/hweight.h>
+
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+
+#include <asm-generic/bitops/minix.h>
+
+#endif                         /* __KERNEL__ */
+
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+
+#endif                         /* _BLACKFIN_BITOPS_H */
diff --git a/include/asm-blackfin/blackfin.h b/include/asm-blackfin/blackfin.h
new file mode 100644 (file)
index 0000000..14e58de
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _BLACKFIN_H_
+#define _BLACKFIN_H_
+
+#include <asm/macros.h>
+#include <asm/mach/blackfin.h>
+#include <asm/bfin-global.h>
+
+#ifndef __ASSEMBLY__
+
+/* SSYNC implementation for C file */
+#if defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+static inline void SSYNC (void)
+{
+       int _tmp;
+       __asm__ __volatile__ ("cli %0;\n\t"
+                       "nop;nop;\n\t"
+                       "ssync;\n\t"
+                       "sti %0;\n\t"
+                       :"=d"(_tmp):);
+}
+#elif defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+static inline void SSYNC (void)
+{
+       int _tmp;
+       __asm__ __volatile__ ("cli %0;\n\t"
+                       "ssync;\n\t"
+                       "sti %0;\n\t"
+                       :"=d"(_tmp):);
+}
+#elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+static inline void SSYNC (void)
+{
+       __builtin_bfin_ssync();
+}
+#elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+static inline void SSYNC (void)
+{
+       __asm__ __volatile__ ("ssync;\n\t");
+}
+#endif
+
+/* CSYNC implementation for C file */
+#if defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+static inline void CSYNC (void)
+{
+       int _tmp;
+       __asm__ __volatile__ ("cli %0;\n\t"
+                       "nop;nop;\n\t"
+                       "csync;\n\t"
+                       "sti %0;\n\t"
+                       :"=d"(_tmp):);
+}
+#elif defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+static inline void CSYNC (void)
+{
+       int _tmp;
+       __asm__ __volatile__ ("cli %0;\n\t"
+                       "csync;\n\t"
+                       "sti %0;\n\t"
+                       :"=d"(_tmp):);
+}
+#elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+static inline void CSYNC (void)
+{
+       __builtin_bfin_csync();
+}
+#elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+static inline void CSYNC (void)
+{
+       __asm__ __volatile__ ("csync;\n\t");
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif                         /* _BLACKFIN_H_ */
diff --git a/include/asm-blackfin/bug.h b/include/asm-blackfin/bug.h
new file mode 100644 (file)
index 0000000..41e53b2
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _BLACKFIN_BUG_H
+#define _BLACKFIN_BUG_H
+#include <asm-generic/bug.h>
+#endif
diff --git a/include/asm-blackfin/bugs.h b/include/asm-blackfin/bugs.h
new file mode 100644 (file)
index 0000000..9093c9c
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  include/asm-blackfin/bugs.h
+ *
+ *  Copyright (C) 1994  Linus Torvalds
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *     void check_bugs(void);
+ */
+
+static void check_bugs(void)
+{
+}
diff --git a/include/asm-blackfin/byteorder.h b/include/asm-blackfin/byteorder.h
new file mode 100644 (file)
index 0000000..6a673d4
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef _BLACKFIN_BYTEORDER_H
+#define _BLACKFIN_BYTEORDER_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+
+#ifdef __GNUC__
+
+static __inline__ __attribute_const__ __u32 ___arch__swahb32(__u32 xx)
+{
+       __u32 tmp;
+       __asm__("%1 = %0 >> 8 (V);\n\t"
+               "%0 = %0 << 8 (V);\n\t"
+               "%0 = %0 | %1;\n\t"
+               : "+d"(xx), "=&d"(tmp));
+       return xx;
+}
+
+static __inline__ __attribute_const__ __u32 ___arch__swahw32(__u32 xx)
+{
+       __u32 rv;
+       __asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
+       return rv;
+}
+
+#define __arch__swahb32(x) ___arch__swahb32(x)
+#define __arch__swahw32(x) ___arch__swahw32(x)
+#define __arch__swab32(x) ___arch__swahb32(___arch__swahw32(x))
+
+static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 xx)
+{
+       __u32 xw = xx;
+       __asm__("%0 <<= 8;\n    %0.L = %0.L + %0.H (NS);\n": "+d"(xw));
+       return (__u16)xw;
+}
+
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#endif
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#include <linux/byteorder/little_endian.h>
+
+#endif                         /* _BLACKFIN_BYTEORDER_H */
diff --git a/include/asm-blackfin/cache.h b/include/asm-blackfin/cache.h
new file mode 100644 (file)
index 0000000..023d721
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * include/asm-blackfin/cache.h
+ */
+#ifndef __ARCH_BLACKFIN_CACHE_H
+#define __ARCH_BLACKFIN_CACHE_H
+
+/*
+ * Bytes per L1 cache line
+ * Blackfin loads 32 bytes for cache
+ */
+#define L1_CACHE_SHIFT 5
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+#define SMP_CACHE_BYTES        L1_CACHE_BYTES
+
+/*
+ * Put cacheline_aliged data to L1 data memory
+ */
+#ifdef CONFIG_CACHELINE_ALIGNED_L1
+#define __cacheline_aligned                            \
+         __attribute__((__aligned__(L1_CACHE_BYTES),   \
+               __section__(".data_l1.cacheline_aligned")))
+#endif
+
+/*
+ * largest L1 which this arch supports
+ */
+#define L1_CACHE_SHIFT_MAX     5
+
+#endif
diff --git a/include/asm-blackfin/cacheflush.h b/include/asm-blackfin/cacheflush.h
new file mode 100644 (file)
index 0000000..e5e000d
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * File:         include/asm-blackfin/cacheflush.h
+ * Based on:    include/asm-m68knommu/cacheflush.h
+ * Author:       LG Soft India
+ *               Copyright (C) 2004 Analog Devices Inc.
+ * Created:      Tue Sep 21 2004
+ * Description:  Blackfin low-level cache routines adapted from the i386
+ *              and PPC versions by Greg Ungerer (gerg@snapgear.com)
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BLACKFIN_CACHEFLUSH_H
+#define _BLACKFIN_CACHEFLUSH_H
+
+#include <asm/cplb.h>
+
+extern void blackfin_icache_dcache_flush_range(unsigned int, unsigned int);
+extern void blackfin_icache_flush_range(unsigned int, unsigned int);
+extern void blackfin_dcache_flush_range(unsigned int, unsigned int);
+extern void blackfin_dcache_invalidate_range(unsigned int, unsigned int);
+extern void blackfin_dflush_page(void *);
+
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_range(vma, start, end)     do { } while (0)
+#define flush_cache_page(vma, vmaddr)          do { } while (0)
+#define flush_cache_vmap(start, end)           do { } while (0)
+#define flush_cache_vunmap(start, end)         do { } while (0)
+
+static inline void flush_icache_range(unsigned start, unsigned end)
+{
+#if defined(CONFIG_BLKFIN_DCACHE) && defined(CONFIG_BLKFIN_CACHE)
+
+# if defined(CONFIG_BLKFIN_WT)
+       blackfin_icache_flush_range((start), (end));
+# else
+       blackfin_icache_dcache_flush_range((start), (end));
+# endif
+
+#else
+
+# if defined(CONFIG_BLKFIN_CACHE)
+       blackfin_icache_flush_range((start), (end));
+# endif
+# if defined(CONFIG_BLKFIN_DCACHE)
+       blackfin_dcache_flush_range((start), (end));
+# endif
+
+#endif
+}
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+do { memcpy(dst, src, len); \
+     flush_icache_range ((unsigned) (dst), (unsigned) (dst) + (len)); \
+} while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)   memcpy(dst, src, len)
+
+#if defined(CONFIG_BLKFIN_DCACHE)
+# define invalidate_dcache_range(start,end)    blackfin_dcache_invalidate_range((start), (end))
+#else
+# define invalidate_dcache_range(start,end)    do { } while (0)
+#endif
+#if defined(CONFIG_BLKFIN_DCACHE) && defined(CONFIG_BLKFIN_WB)
+# define flush_dcache_range(start,end)         blackfin_dcache_flush_range((start), (end))
+# define flush_dcache_page(page)                       blackfin_dflush_page(page_address(page))
+#else
+# define flush_dcache_range(start,end)         do { } while (0)
+# define flush_dcache_page(page)                       do { } while (0)
+#endif
+
+#endif                         /* _BLACKFIN_CACHEFLUSH_H */
diff --git a/include/asm-blackfin/checksum.h b/include/asm-blackfin/checksum.h
new file mode 100644 (file)
index 0000000..2638f25
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef _BFIN_CHECKSUM_H
+#define _BFIN_CHECKSUM_H
+
+/*
+ * MODIFIED FOR BFIN April 30, 2001 akbar.hussain@lineo.com
+ *
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
+                              int len, int sum);
+
+/*
+ * the same as csum_partial_copy, but copies from user space.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
+                                               unsigned char *dst, int len,
+                                               int sum, int *csum_err);
+
+#define csum_partial_copy_nocheck(src, dst, len, sum)  \
+       csum_partial_copy((src), (dst), (len), (sum))
+
+unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl);
+
+/*
+ *     Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+       while (sum >> 16)
+               sum = (sum & 0xffff) + (sum >> 16);
+       return ((~(sum << 16)) >> 16);
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+
+static inline unsigned int
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
+                  unsigned short proto, unsigned int sum)
+{
+
+       __asm__ ("%0 = %0 + %1;\n\t"
+                "CC = AC0;\n\t"
+                "if !CC jump 4;\n\t"
+                "%0 = %0 + %4;\n\t"
+                "%0 = %0 + %2;\n\t"
+                "CC = AC0;\n\t"
+                 "if !CC jump 4;\n\t"
+                 "%0 = %0 + %4;\n\t"
+                "%0 = %0 + %3;\n\t"
+                "CC = AC0;\n\t"
+                 "if !CC jump 4;\n\t"
+                 "%0 = %0 + %4;\n\t"
+                 "NOP;\n\t"
+                : "=d" (sum)
+                : "d" (daddr), "d" (saddr), "d" ((ntohs(len)<<16)+proto*256), "d" (1), "0"(sum));
+
+       return (sum);
+}
+
+static inline unsigned short int
+csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
+                 unsigned short proto, unsigned int sum)
+{
+       return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+extern unsigned short ip_compute_csum(const unsigned char *buff, int len);
+
+#endif                         /* _BFIN_CHECKSUM_H */
diff --git a/include/asm-blackfin/cplb.h b/include/asm-blackfin/cplb.h
new file mode 100644 (file)
index 0000000..e0dd56b
--- /dev/null
@@ -0,0 +1,51 @@
+/************************************************************************
+ *
+ * cplb.h
+ *
+ * (c) Copyright 2002-2003 Analog Devices, Inc.  All rights reserved.
+ *
+ ************************************************************************/
+
+/* Defines necessary for cplb initialisation routines. */
+
+#ifndef _CPLB_H
+#define _CPLB_H
+
+# include <asm/blackfin.h>
+
+#define CPLB_ENABLE_ICACHE_P   0
+#define CPLB_ENABLE_DCACHE_P   1
+#define CPLB_ENABLE_DCACHE2_P  2
+#define CPLB_ENABLE_CPLBS_P    3       /* Deprecated! */
+#define CPLB_ENABLE_ICPLBS_P   4
+#define CPLB_ENABLE_DCPLBS_P   5
+
+#define CPLB_ENABLE_ICACHE     (1<<CPLB_ENABLE_ICACHE_P)
+#define CPLB_ENABLE_DCACHE     (1<<CPLB_ENABLE_DCACHE_P)
+#define CPLB_ENABLE_DCACHE2    (1<<CPLB_ENABLE_DCACHE2_P)
+#define CPLB_ENABLE_CPLBS      (1<<CPLB_ENABLE_CPLBS_P)
+#define CPLB_ENABLE_ICPLBS     (1<<CPLB_ENABLE_ICPLBS_P)
+#define CPLB_ENABLE_DCPLBS     (1<<CPLB_ENABLE_DCPLBS_P)
+#define CPLB_ENABLE_ANY_CPLBS  CPLB_ENABLE_CPLBS | \
+                               CPLB_ENABLE_ICPLBS | \
+                               CPLB_ENABLE_DCPLBS
+
+#define CPLB_RELOADED          0x0000
+#define CPLB_NO_UNLOCKED       0x0001
+#define CPLB_NO_ADDR_MATCH     0x0002
+#define CPLB_PROT_VIOL         0x0003
+#define CPLB_UNKNOWN_ERR       0x0004
+
+#define CPLB_DEF_CACHE         CPLB_L1_CHBL | CPLB_WT
+#define CPLB_CACHE_ENABLED     CPLB_L1_CHBL | CPLB_DIRTY
+
+#define CPLB_ALL_ACCESS        CPLB_SUPV_WR | CPLB_USER_RD | CPLB_USER_WR
+
+#define CPLB_I_PAGE_MGMT       CPLB_LOCK | CPLB_VALID
+#define CPLB_D_PAGE_MGMT       CPLB_LOCK | CPLB_ALL_ACCESS | CPLB_VALID
+#define CPLB_DNOCACHE          CPLB_ALL_ACCESS | CPLB_VALID
+#define CPLB_DDOCACHE          CPLB_DNOCACHE | CPLB_DEF_CACHE
+#define CPLB_INOCACHE          CPLB_USER_RD | CPLB_VALID
+#define CPLB_IDOCACHE          CPLB_INOCACHE | CPLB_L1_CHBL
+
+#endif                         /* _CPLB_H */
diff --git a/include/asm-blackfin/cplbinit.h b/include/asm-blackfin/cplbinit.h
new file mode 100644 (file)
index 0000000..3bad2d1
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * File:         include/asm-blackfin/cplbinit.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <asm/blackfin.h>
+#include <asm/cplb.h>
+
+#define INITIAL_T 0x1
+#define SWITCH_T  0x2
+#define I_CPLB    0x4
+#define D_CPLB    0x8
+
+#define IN_KERNEL 1
+
+enum
+{ZERO_P, L1I_MEM, L1D_MEM, SDRAM_KERN , SDRAM_RAM_MTD, SDRAM_DMAZ, RES_MEM, ASYNC_MEM, L2_MEM};
+
+struct cplb_desc {
+       u32 start; /* start address */
+       u32 end; /* end address */
+       u32 psize; /* prefered size if any otherwise 1MB or 4MB*/
+       u16 attr;/* attributes */
+       u16 i_conf;/* I-CPLB DATA */
+       u16 d_conf;/* D-CPLB DATA */
+       u16 valid;/* valid */
+       const s8 name[30];/* name */
+};
+
+struct cplb_tab {
+  u_long *tab;
+       u16 pos;
+       u16 size;
+};
+
+u_long icplb_table[MAX_CPLBS+1];
+u_long dcplb_table[MAX_CPLBS+1];
+
+/* Till here we are discussing about the static memory management model.
+ * However, the operating envoronments commonly define more CPLB
+ * descriptors to cover the entire addressable memory than will fit into
+ * the available on-chip 16 CPLB MMRs. When this happens, the below table
+ * will be used which will hold all the potentially required CPLB descriptors
+ *
+ * This is how Page descriptor Table is implemented in uClinux/Blackfin.
+ */
+
+#ifdef CONFIG_CPLB_SWITCH_TAB_L1
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+#endif /* CONFIG_CPLB_INFO */
+
+#else
+
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+#endif /* CONFIG_CPLB_INFO */
+
+#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
+
+struct s_cplb {
+       struct cplb_tab init_i;
+       struct cplb_tab init_d;
+       struct cplb_tab switch_i;
+       struct cplb_tab switch_d;
+};
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+static struct cplb_desc cplb_data[] = {
+       {
+               .start = 0,
+               .end = SIZE_4K,
+               .psize = SIZE_4K,
+               .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+               .i_conf = SDRAM_OOPS,
+               .d_conf = SDRAM_OOPS,
+#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
+               .valid = 1,
+#else
+               .valid = 0,
+#endif
+               .name = "ZERO Pointer Saveguard",
+       },
+       {
+               .start = L1_CODE_START,
+               .end = L1_CODE_START + L1_CODE_LENGTH,
+               .psize = SIZE_4M,
+               .attr = INITIAL_T | SWITCH_T | I_CPLB,
+               .i_conf = L1_IMEMORY,
+               .d_conf = 0,
+               .valid = 1,
+               .name = "L1 I-Memory",
+       },
+       {
+               .start = L1_DATA_A_START,
+               .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
+               .psize = SIZE_4M,
+               .attr = INITIAL_T | SWITCH_T | D_CPLB,
+               .i_conf = 0,
+               .d_conf = L1_DMEMORY,
+#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
+               .valid = 1,
+#else
+               .valid = 0,
+#endif
+               .name = "L1 D-Memory",
+       },
+       {
+               .start = 0,
+               .end = 0,  /* dynamic */
+               .psize = 0,
+               .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+               .i_conf =  SDRAM_IGENERIC,
+               .d_conf =  SDRAM_DGENERIC,
+               .valid = 1,
+               .name = "SDRAM Kernel",
+       },
+       {
+               .start = 0, /* dynamic */
+               .end = 0, /* dynamic */
+               .psize = 0,
+               .attr = INITIAL_T | SWITCH_T | D_CPLB,
+               .i_conf =  SDRAM_IGENERIC,
+               .d_conf =  SDRAM_DNON_CHBL,
+               .valid = 1,
+               .name = "SDRAM RAM MTD",
+       },
+       {
+               .start = 0, /* dynamic */
+               .end = 0,   /* dynamic */
+               .psize = SIZE_1M,
+               .attr = INITIAL_T | SWITCH_T | D_CPLB,
+               .d_conf = SDRAM_DNON_CHBL,
+               .valid = 1,//(DMA_UNCACHED_REGION > 0),
+               .name = "SDRAM Uncached DMA ZONE",
+       },
+       {
+               .start = 0, /* dynamic */
+               .end = 0, /* dynamic */
+               .psize = 0,
+               .attr = SWITCH_T | D_CPLB,
+               .i_conf = 0, /* dynamic */
+               .d_conf = 0, /* dynamic */
+               .valid = 1,
+               .name = "SDRAM Reserved Memory",
+       },
+       {
+               .start = ASYNC_BANK0_BASE,
+               .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
+               .psize = 0,
+               .attr = SWITCH_T | D_CPLB,
+               .d_conf = SDRAM_EBIU,
+               .valid = 1,
+               .name = "ASYNC Memory",
+       },
+       {
+#if defined(CONFIG_BF561)
+               .start = L2_SRAM,
+               .end = L2_SRAM_END,
+               .psize = SIZE_1M,
+               .attr = SWITCH_T | D_CPLB,
+               .i_conf = L2_MEMORY,
+               .d_conf = L2_MEMORY,
+               .valid = 1,
+#else
+               .valid = 0,
+#endif
+               .name = "L2 Memory",
+       }
+};
+#endif
diff --git a/include/asm-blackfin/cpumask.h b/include/asm-blackfin/cpumask.h
new file mode 100644 (file)
index 0000000..b20a8e9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_BLACKFIN_CPUMASK_H
+#define _ASM_BLACKFIN_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif                         /* _ASM_BLACKFIN_CPUMASK_H */
diff --git a/include/asm-blackfin/cputime.h b/include/asm-blackfin/cputime.h
new file mode 100644 (file)
index 0000000..2b19705
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __BLACKFIN_CPUTIME_H
+#define __BLACKFIN_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif                         /* __BLACKFIN_CPUTIME_H */
diff --git a/include/asm-blackfin/current.h b/include/asm-blackfin/current.h
new file mode 100644 (file)
index 0000000..31918d2
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _BLACKFIN_CURRENT_H
+#define _BLACKFIN_CURRENT_H
+/*
+ *     current.h
+ *     (C) Copyright 2000, Lineo, David McCullough <davidm@lineo.com>
+ *
+ *     rather than dedicate a register (as the m68k source does), we
+ *     just keep a global,  we should probably just change it all to be
+ *     current and lose _current_task.
+ */
+#include <linux/thread_info.h>
+
+struct task_struct;
+
+static inline struct task_struct *get_current(void) __attribute__ ((__const__));
+static inline struct task_struct *get_current(void)
+{
+       return (current_thread_info()->task);
+}
+
+#define        current (get_current())
+
+#endif                         /* _BLACKFIN_CURRENT_H */
diff --git a/include/asm-blackfin/delay.h b/include/asm-blackfin/delay.h
new file mode 100644 (file)
index 0000000..52e7a10
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _BLACKFIN_DELAY_H
+#define _BLACKFIN_DELAY_H
+
+static inline void __delay(unsigned long loops)
+{
+
+/* FIXME: Currently the assembler doesn't recognize Loop Register Clobbers,
+   uncomment this as soon those are implemented */
+/*
+      __asm__ __volatile__ (  "\t LSETUP (1f,1f) LC0= %0\n\t"
+                              "1:\t NOP;\n\t"
+                              : :"a" (loops)
+                              : "LT0","LB0","LC0");
+
+*/
+
+       __asm__ __volatile__("[--SP] = LC0;\n\t"
+                            "[--SP] = LT0;\n\t"
+                            "[--SP] = LB0;\n\t"
+                            "LSETUP (1f,1f) LC0 = %0;\n\t"
+                            "1:\t NOP;\n\t"
+                            "LB0 = [SP++];\n\t"
+                               "LT0 = [SP++];\n\t"
+                               "LC0 = [SP++];\n"
+                               :
+                               :"a" (loops));
+}
+
+#include <linux/param.h>       /* needed for HZ */
+
+/*
+ * Use only for very small delays ( < 1 msec).  Should probably use a
+ * lookup table, really, as the multiplications take much too long with
+ * short delays.  This is a "reasonable" implementation, though (and the
+ * first constant multiplications gets optimized away if the delay is
+ * a constant)
+ */
+static inline void udelay(unsigned long usecs)
+{
+       extern unsigned long loops_per_jiffy;
+       __delay(usecs * loops_per_jiffy / (1000000 / HZ));
+}
+
+#endif                         /* defined(_BLACKFIN_DELAY_H) */
diff --git a/include/asm-blackfin/device.h b/include/asm-blackfin/device.h
new file mode 100644 (file)
index 0000000..d8f9872
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#include <asm-generic/device.h>
+
diff --git a/include/asm-blackfin/div64.h b/include/asm-blackfin/div64.h
new file mode 100644 (file)
index 0000000..6cd978c
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/div64.h>
diff --git a/include/asm-blackfin/dma-mapping.h b/include/asm-blackfin/dma-mapping.h
new file mode 100644 (file)
index 0000000..7a77d7f
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef _BLACKFIN_DMA_MAPPING_H
+#define _BLACKFIN_DMA_MAPPING_H
+
+#include <asm/scatterlist.h>
+
+void dma_alloc_init(unsigned long start, unsigned long end);
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                        dma_addr_t *dma_handle, gfp_t gfp);
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+                      dma_addr_t dma_handle);
+
+/*
+ * Now for the API extensions over the pci_ one
+ */
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+/*
+ * Map a single buffer of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_dma_sync_single is performed.
+ */
+extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+                                enum dma_data_direction direction);
+
+/*
+ * Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+                         enum dma_data_direction direction);
+
+/*
+ * Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+                     enum dma_data_direction direction);
+
+/*
+ * Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+                     int nhwentries, enum dma_data_direction direction);
+
+#endif                         /* _BLACKFIN_DMA_MAPPING_H */
diff --git a/include/asm-blackfin/dma.h b/include/asm-blackfin/dma.h
new file mode 100644 (file)
index 0000000..be0d913
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * File:         include/asm-blackfin/simple_bf533_dma.h
+ * Based on:     none - original work
+ * Author:       LG Soft India
+ *               Copyright (C) 2004-2005 Analog Devices Inc.
+ * Created:      Tue Sep 21 2004
+ * Description:  This file contains the major Data structures and constants
+ *              used for DMA Implementation in BF533
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BLACKFIN_DMA_H_
+#define _BLACKFIN_DMA_H_
+
+#include <asm/io.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+#include <asm/signal.h>
+#include <asm/semaphore.h>
+
+#include <linux/kernel.h>
+#include <asm/mach/dma.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/blackfin.h>
+
+#define MAX_DMA_ADDRESS PAGE_OFFSET
+
+/*****************************************************************************
+*        Generic DMA  Declarations
+*
+****************************************************************************/
+enum dma_chan_status {
+       DMA_CHANNEL_FREE,
+       DMA_CHANNEL_REQUESTED,
+       DMA_CHANNEL_ENABLED,
+};
+
+/*-------------------------
+ * config reg bits value
+ *-------------------------*/
+#define DATA_SIZE_8            0
+#define DATA_SIZE_16           1
+#define DATA_SIZE_32           2
+
+#define DMA_FLOW_STOP          0
+#define DMA_FLOW_AUTO          1
+#define DMA_FLOW_ARRAY                 4
+#define DMA_FLOW_SMALL                 6
+#define DMA_FLOW_LARGE                 7
+
+#define DIMENSION_LINEAR    0
+#define DIMENSION_2D           1
+
+#define DIR_READ     0
+#define DIR_WRITE    1
+
+#define INTR_DISABLE   0
+#define INTR_ON_BUF    2
+#define INTR_ON_ROW    3
+
+struct dmasg {
+       unsigned long next_desc_addr;
+       unsigned long start_addr;
+       unsigned short cfg;
+       unsigned short x_count;
+       short x_modify;
+       unsigned short y_count;
+       short y_modify;
+} __attribute__((packed));
+
+struct dma_register {
+       unsigned long next_desc_ptr;    /* DMA Next Descriptor Pointer register */
+       unsigned long start_addr;       /* DMA Start address  register */
+
+       unsigned short cfg;     /* DMA Configuration register */
+       unsigned short dummy1;  /* DMA Configuration register */
+
+       unsigned long reserved;
+
+       unsigned short x_count; /* DMA x_count register */
+       unsigned short dummy2;
+
+       short x_modify; /* DMA x_modify register */
+       unsigned short dummy3;
+
+       unsigned short y_count; /* DMA y_count register */
+       unsigned short dummy4;
+
+       short y_modify; /* DMA y_modify register */
+       unsigned short dummy5;
+
+       unsigned long curr_desc_ptr;    /* DMA Current Descriptor Pointer
+                                          register */
+       unsigned short curr_addr_ptr_lo;        /* DMA Current Address Pointer
+                                                  register */
+       unsigned short curr_addr_ptr_hi;        /* DMA Current Address Pointer
+                                                  register */
+       unsigned short irq_status;      /* DMA irq status register */
+       unsigned short dummy6;
+
+       unsigned short peripheral_map;  /* DMA peripheral map register */
+       unsigned short dummy7;
+
+       unsigned short curr_x_count;    /* DMA Current x-count register */
+       unsigned short dummy8;
+
+       unsigned long reserved2;
+
+       unsigned short curr_y_count;    /* DMA Current y-count register */
+       unsigned short dummy9;
+
+       unsigned long reserved3;
+
+};
+
+typedef irqreturn_t(*dma_interrupt_t) (int irq, void *dev_id);
+
+struct dma_channel {
+       struct mutex dmalock;
+       char *device_id;
+       enum dma_chan_status chan_status;
+       struct dma_register *regs;
+       struct dmasg *sg;               /* large mode descriptor */
+       unsigned int ctrl_num;  /* controller number */
+       dma_interrupt_t irq_callback;
+       void *data;
+       unsigned int dma_enable_flag;
+       unsigned int loopback_flag;
+};
+
+/*******************************************************************************
+*      DMA API's
+*******************************************************************************/
+/* functions to set register mode */
+void set_dma_start_addr(unsigned int channel, unsigned long addr);
+void set_dma_next_desc_addr(unsigned int channel, unsigned long addr);
+void set_dma_x_count(unsigned int channel, unsigned short x_count);
+void set_dma_x_modify(unsigned int channel, short x_modify);
+void set_dma_y_count(unsigned int channel, unsigned short y_count);
+void set_dma_y_modify(unsigned int channel, short y_modify);
+void set_dma_config(unsigned int channel, unsigned short config);
+unsigned short set_bfin_dma_config(char direction, char flow_mode,
+                                  char intr_mode, char dma_mode, char width);
+
+/* get curr status for polling */
+unsigned short get_dma_curr_irqstat(unsigned int channel);
+unsigned short get_dma_curr_xcount(unsigned int channel);
+unsigned short get_dma_curr_ycount(unsigned int channel);
+
+/* set large DMA mode descriptor */
+void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg);
+
+/* check if current channel is in use */
+int dma_channel_active(unsigned int channel);
+
+/* common functions must be called in any mode */
+void free_dma(unsigned int channel);
+int dma_channel_active(unsigned int channel); /* check if a channel is in use */
+void disable_dma(unsigned int channel);
+void enable_dma(unsigned int channel);
+int request_dma(unsigned int channel, char *device_id);
+int set_dma_callback(unsigned int channel, dma_interrupt_t callback,
+                    void *data);
+void dma_disable_irq(unsigned int channel);
+void dma_enable_irq(unsigned int channel);
+void clear_dma_irqstat(unsigned int channel);
+void *dma_memcpy(void *dest, const void *src, size_t count);
+void *safe_dma_memcpy(void *dest, const void *src, size_t count);
+
+#endif
diff --git a/include/asm-blackfin/dpmc.h b/include/asm-blackfin/dpmc.h
new file mode 100644 (file)
index 0000000..f162edb
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * include/asm-blackfin/dpmc.h -  Miscellaneous IOCTL commands for Dynamic Power
+ *                             Management Controller Driver.
+ * Copyright (C) 2004 Analog Device Inc.
+ *
+ */
+#ifndef _BLACKFIN_DPMC_H_
+#define _BLACKFIN_DPMC_H_
+
+#define SLEEP_MODE             1
+#define DEEP_SLEEP_MODE                2
+#define ACTIVE_PLL_DISABLED    3
+#define FULLON_MODE            4
+#define ACTIVE_PLL_ENABLED     5
+#define HIBERNATE_MODE         6
+
+#define IOCTL_FULL_ON_MODE     _IO('s', 0xA0)
+#define IOCTL_ACTIVE_MODE      _IO('s', 0xA1)
+#define IOCTL_SLEEP_MODE       _IO('s', 0xA2)
+#define IOCTL_DEEP_SLEEP_MODE  _IO('s', 0xA3)
+#define IOCTL_HIBERNATE_MODE   _IO('s', 0xA4)
+#define IOCTL_CHANGE_FREQUENCY _IOW('s', 0xA5, unsigned long)
+#define IOCTL_CHANGE_VOLTAGE   _IOW('s', 0xA6, unsigned long)
+#define IOCTL_SET_CCLK         _IOW('s', 0xA7, unsigned long)
+#define IOCTL_SET_SCLK         _IOW('s', 0xA8, unsigned long)
+#define IOCTL_GET_PLLSTATUS    _IOW('s', 0xA9, unsigned long)
+#define IOCTL_GET_CORECLOCK    _IOW('s', 0xAA, unsigned long)
+#define IOCTL_GET_SYSTEMCLOCK  _IOW('s', 0xAB, unsigned long)
+#define IOCTL_GET_VCO          _IOW('s', 0xAC, unsigned long)
+#define IOCTL_DISABLE_WDOG_TIMER _IO('s', 0xAD)
+#define IOCTL_UNMASK_WDOG_WAKEUP_EVENT _IO('s',0xAE)
+#define IOCTL_PROGRAM_WDOG_TIMER _IOW('s',0xAF,unsigned long)
+#define IOCTL_CLEAR_WDOG_WAKEUP_EVENT _IO('s',0xB0)
+#define IOCTL_SLEEP_DEEPER_MODE _IO('s',0xB1)
+
+#define DPMC_MINOR             254
+
+#define ON     0
+#define OFF    1
+
+#ifdef __KERNEL__
+
+unsigned long calc_volt(void);
+int calc_vlev(int vlt);
+unsigned long change_voltage(unsigned long volt);
+int calc_msel(int vco_hz);
+unsigned long change_frequency(unsigned long vco_mhz);
+int set_pll_div(unsigned short sel, unsigned char flag);
+int get_vco(void);
+unsigned long change_system_clock(unsigned long clock);
+unsigned long change_core_clock(unsigned long clock);
+unsigned long get_pll_status(void);
+void change_baud(int baud);
+void fullon_mode(void);
+void active_mode(void);
+void sleep_mode(u32 sic_iwr);
+void deep_sleep(u32 sic_iwr);
+void hibernate_mode(u32 sic_iwr);
+void sleep_deeper(u32 sic_iwr);
+void program_wdog_timer(unsigned long);
+void unmask_wdog_wakeup_evt(void);
+void clear_wdog_wakeup_evt(void);
+void disable_wdog_timer(void);
+
+extern unsigned long get_cclk(void);
+extern unsigned long get_sclk(void);
+
+#endif /* __KERNEL__ */
+
+#endif /*_BLACKFIN_DPMC_H_*/
diff --git a/include/asm-blackfin/elf.h b/include/asm-blackfin/elf.h
new file mode 100644 (file)
index 0000000..5264b55
--- /dev/null
@@ -0,0 +1,127 @@
+/* Changes made by  LG Soft Oct 2004*/
+
+#ifndef __ASMBFIN_ELF_H
+#define __ASMBFIN_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_BFIN_PIC            0x00000001      /* -fpic */
+#define EF_BFIN_FDPIC          0x00000002      /* -mfdpic */
+#define EF_BFIN_CODE_IN_L1     0x00000010      /* --code-in-l1 */
+#define EF_BFIN_DATA_IN_L1     0x00000020      /* --data-in-l1 */
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_bfinfp_struct elf_fpregset_t;
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_BLACKFIN)
+
+#define elf_check_fdpic(x) ((x)->e_flags & EF_BFIN_FDPIC /* && !((x)->e_flags & EF_FRV_NON_PIC_RELOCS) */)
+#define elf_check_const_displacement(x) ((x)->e_flags & EF_BFIN_PIC)
+
+/* EM_BLACKFIN defined in linux/elf.h  */
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+#define ELF_DATA       ELFDATA2LSB
+#define ELF_ARCH       EM_BLACKFIN
+
+#define ELF_PLAT_INIT(_r)      _r->p1 = 0
+
+#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map_addr, _interp_map_addr, _dynamic_addr)    \
+do {                                                                                   \
+       _regs->r7       = 0;                                            \
+       _regs->p0       = _exec_map_addr;                               \
+       _regs->p1       = _interp_map_addr;                             \
+       _regs->p2       = _dynamic_addr;                                \
+} while(0)
+
+#define USE_ELF_CORE_DUMP
+#define ELF_FDPIC_CORE_EFLAGS  EF_BFIN_FDPIC
+#define ELF_EXEC_PAGESIZE      4096
+
+#define        R_unused0       0       /* relocation type 0 is not defined */
+#define R_pcrel5m2     1       /*LSETUP part a */
+#define R_unused1      2       /* relocation type 2 is not defined */
+#define R_pcrel10      3       /* type 3, if cc jump <target>  */
+#define R_pcrel12_jump 4       /* type 4, jump <target> */
+#define R_rimm16       5       /* type 0x5, rN = <target> */
+#define R_luimm16      6       /* # 0x6, preg.l=<target> Load imm 16 to lower half */
+#define R_huimm16      7       /* # 0x7, preg.h=<target> Load imm 16 to upper half */
+#define R_pcrel12_jump_s 8     /* # 0x8 jump.s <target> */
+#define R_pcrel24_jump_x 9     /* # 0x9 jump.x <target> */
+#define R_pcrel24       10     /* # 0xa call <target> , not expandable */
+#define R_unusedb       11     /* # 0xb not generated */
+#define R_unusedc       12     /* # 0xc  not used */
+#define R_pcrel24_jump_l 13    /*0xd jump.l <target> */
+#define R_pcrel24_call_x 14    /* 0xE, call.x <target> if <target> is above 24 bit limit call through P1 */
+#define R_var_eq_symb    15    /* 0xf, linker should treat it same as 0x12 */
+#define R_byte_data      16    /* 0x10, .byte var = symbol */
+#define R_byte2_data     17    /* 0x11, .byte2 var = symbol */
+#define R_byte4_data     18    /* 0x12, .byte4 var = symbol and .var var=symbol */
+#define R_pcrel11        19    /* 0x13, lsetup part b */
+#define R_unused14      20     /* 0x14, undefined */
+#define R_unused15       21    /* not generated by VDSP 3.5 */
+
+/* arithmetic relocations */
+#define R_push          0xE0
+#define R_const                 0xE1
+#define R_add           0xE2
+#define R_sub           0xE3
+#define R_mult          0xE4
+#define R_div           0xE5
+#define R_mod           0xE6
+#define R_lshift        0xE7
+#define R_rshift        0xE8
+#define R_and           0xE9
+#define R_or            0xEA
+#define R_xor           0xEB
+#define R_land          0xEC
+#define R_lor           0xED
+#define R_len           0xEE
+#define R_neg           0xEF
+#define R_comp          0xF0
+#define R_page          0xF1
+#define R_hwpage        0xF2
+#define R_addr          0xF3
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         0xD0000000UL
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs)       \
+        memcpy((char *) &pr_reg, (char *)regs,  \
+               sizeof(struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports.  */
+
+#define ELF_HWCAP      (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.  */
+
+#define ELF_PLATFORM  (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#endif
+
+#endif
diff --git a/include/asm-blackfin/emergency-restart.h b/include/asm-blackfin/emergency-restart.h
new file mode 100644 (file)
index 0000000..27f6c78
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_EMERGENCY_RESTART_H
+#define _ASM_EMERGENCY_RESTART_H
+
+#include <asm-generic/emergency-restart.h>
+
+#endif                         /* _ASM_EMERGENCY_RESTART_H */
diff --git a/include/asm-blackfin/entry.h b/include/asm-blackfin/entry.h
new file mode 100644 (file)
index 0000000..562c6d3
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __BFIN_ENTRY_H
+#define __BFIN_ENTRY_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+
+#ifdef __ASSEMBLY__
+
+#define        LFLUSH_I_AND_D  0x00000808
+#define        LSIGTRAP        5
+
+/* process bits for task_struct.flags */
+#define        PF_TRACESYS_OFF 3
+#define        PF_TRACESYS_BIT 5
+#define        PF_PTRACED_OFF  3
+#define        PF_PTRACED_BIT  4
+#define        PF_DTRACE_OFF   1
+#define        PF_DTRACE_BIT   5
+
+/* This one is used for exceptions, emulation, and NMI.  It doesn't push
+   RETI and doesn't do cli.  */
+#define SAVE_ALL_SYS           save_context_no_interrupts
+/* This is used for all normal interrupts.  It saves a minimum of registers
+   to the stack, loads the IRQ number, and jumps to common code.  */
+#define INTERRUPT_ENTRY(N)                                             \
+    [--sp] = SYSCFG;                                                   \
+                                                                       \
+    [--sp] = P0;       /*orig_p0*/                                     \
+    [--sp] = R0;       /*orig_r0*/                                     \
+    [--sp] = (R7:0,P5:0);                                              \
+    R0 = (N);                                                          \
+    jump __common_int_entry;
+
+/* For timer interrupts, we need to save IPEND, since the user_mode
+          macro accesses it to determine where to account time.  */
+#define TIMER_INTERRUPT_ENTRY(N)                                       \
+    [--sp] = SYSCFG;                                                   \
+                                                                       \
+    [--sp] = P0;       /*orig_p0*/                                     \
+    [--sp] = R0;       /*orig_r0*/                                     \
+    [--sp] = (R7:0,P5:0);                                              \
+    p0.l = lo(IPEND);                                                  \
+    p0.h = hi(IPEND);                                                  \
+    r1 = [p0];                                                         \
+    R0 = (N);                                                          \
+    jump __common_int_entry;
+
+/* This one pushes RETI without using CLI.  Interrupts are enabled.  */
+#define SAVE_CONTEXT_SYSCALL   save_context_syscall
+#define SAVE_CONTEXT           save_context_with_interrupts
+
+#define RESTORE_ALL_SYS                restore_context_no_interrupts
+#define RESTORE_CONTEXT                restore_context_with_interrupts
+
+#endif                         /* __ASSEMBLY__ */
+#endif                         /* __BFIN_ENTRY_H */
diff --git a/include/asm-blackfin/errno.h b/include/asm-blackfin/errno.h
new file mode 100644 (file)
index 0000000..164e4f3
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _BFIN_ERRNO_H
+#define _BFIN_ERRNO_H
+
+#include<asm-generic/errno.h>
+
+#endif                         /* _BFIN_ERRNO_H */
diff --git a/include/asm-blackfin/fcntl.h b/include/asm-blackfin/fcntl.h
new file mode 100644 (file)
index 0000000..9c40371
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _BFIN_FCNTL_H
+#define _BFIN_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_DIRECTORY     040000 /* must be a directory */
+#define O_NOFOLLOW     0100000 /* don't follow links */
+#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
+#define O_LARGEFILE    0400000
+
+#include <asm-generic/fcntl.h>
+
+#endif
diff --git a/include/asm-blackfin/flat.h b/include/asm-blackfin/flat.h
new file mode 100644 (file)
index 0000000..e70074e
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * include/asm-blackfin/flat.h -- uClinux flat-format executables
+ *
+ * Copyright (C) 2003,
+ *
+ */
+
+#ifndef __BLACKFIN_FLAT_H__
+#define __BLACKFIN_FLAT_H__
+
+#include <asm/unaligned.h>
+
+#define        flat_stack_align(sp)    /* nothing needed */
+#define        flat_argvp_envp_on_stack()              0
+#define        flat_old_ram_flag(flags)                (flags)
+
+extern unsigned long bfin_get_addr_from_rp (unsigned long *ptr,
+                                       unsigned long relval,
+                                       unsigned long flags,
+                                       unsigned long *persistent);
+
+extern void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
+                               unsigned long relval);
+
+/* The amount by which a relocation can exceed the program image limits
+   without being regarded as an error.  */
+
+#define        flat_reloc_valid(reloc, size)   ((reloc) <= (size))
+
+#define        flat_get_addr_from_rp(rp, relval, flags, persistent)    \
+       bfin_get_addr_from_rp(rp, relval, flags, persistent)
+#define        flat_put_addr_at_rp(rp, val, relval)    \
+       bfin_put_addr_at_rp(rp, val, relval)
+
+/* Convert a relocation entry into an address.  */
+static inline unsigned long
+flat_get_relocate_addr (unsigned long relval)
+{
+       return relval & 0x03ffffff; /* Mask out top 6 bits */
+}
+
+static inline int flat_set_persistent(unsigned long relval,
+                                     unsigned long *persistent)
+{
+       int type = (relval >> 26) & 7;
+       if (type == 3) {
+               *persistent = relval << 16;
+               return 1;
+       }
+       return 0;
+}
+
+static inline int flat_addr_absolute(unsigned long relval)
+{
+       return (relval & (1 << 29)) != 0;
+}
+
+#endif                         /* __BLACKFIN_FLAT_H__ */
diff --git a/include/asm-blackfin/futex.h b/include/asm-blackfin/futex.h
new file mode 100644 (file)
index 0000000..6a332a9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#include <asm-generic/futex.h>
+
+#endif
diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h
new file mode 100644 (file)
index 0000000..d16fe3c
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * File:         arch/blackfin/kernel/bfin_gpio.h
+ * Based on:
+ * Author:      Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+*  Number     BF537/6/4    BF561    BF533/2/1
+*
+*  GPIO_0       PF0         PF0        PF0
+*  GPIO_1       PF1         PF1        PF1
+*  GPIO_2       PF2         PF2        PF2
+*  GPIO_3       PF3         PF3        PF3
+*  GPIO_4       PF4         PF4        PF4
+*  GPIO_5       PF5         PF5        PF5
+*  GPIO_6       PF6         PF6        PF6
+*  GPIO_7       PF7         PF7        PF7
+*  GPIO_8       PF8         PF8        PF8
+*  GPIO_9       PF9         PF9        PF9
+*  GPIO_10      PF10        PF10       PF10
+*  GPIO_11      PF11        PF11       PF11
+*  GPIO_12      PF12        PF12       PF12
+*  GPIO_13      PF13        PF13       PF13
+*  GPIO_14      PF14        PF14       PF14
+*  GPIO_15      PF15        PF15       PF15
+*  GPIO_16      PG0         PF16
+*  GPIO_17      PG1         PF17
+*  GPIO_18      PG2         PF18
+*  GPIO_19      PG3         PF19
+*  GPIO_20      PG4         PF20
+*  GPIO_21      PG5         PF21
+*  GPIO_22      PG6         PF22
+*  GPIO_23      PG7         PF23
+*  GPIO_24      PG8         PF24
+*  GPIO_25      PG9         PF25
+*  GPIO_26      PG10        PF26
+*  GPIO_27      PG11        PF27
+*  GPIO_28      PG12        PF28
+*  GPIO_29      PG13        PF29
+*  GPIO_30      PG14        PF30
+*  GPIO_31      PG15        PF31
+*  GPIO_32      PH0         PF32
+*  GPIO_33      PH1         PF33
+*  GPIO_34      PH2         PF34
+*  GPIO_35      PH3         PF35
+*  GPIO_36      PH4         PF36
+*  GPIO_37      PH5         PF37
+*  GPIO_38      PH6         PF38
+*  GPIO_39      PH7         PF39
+*  GPIO_40      PH8         PF40
+*  GPIO_41      PH9         PF41
+*  GPIO_42      PH10        PF42
+*  GPIO_43      PH11        PF43
+*  GPIO_44      PH12        PF44
+*  GPIO_45      PH13        PF45
+*  GPIO_46      PH14        PF46
+*  GPIO_47      PH15        PF47
+*/
+
+#ifndef __ARCH_BLACKFIN_GPIO_H__
+#define __ARCH_BLACKFIN_GPIO_H__
+
+#define gpio_bank(x) ((x) >> 4)
+#define gpio_bit(x)  (1<<((x) & 0xF))
+#define gpio_sub_n(x) ((x) & 0xF)
+
+#define GPIO_BANKSIZE 16
+
+#define        GPIO_0  0
+#define        GPIO_1  1
+#define        GPIO_2  2
+#define        GPIO_3  3
+#define        GPIO_4  4
+#define        GPIO_5  5
+#define        GPIO_6  6
+#define        GPIO_7  7
+#define        GPIO_8  8
+#define        GPIO_9  9
+#define        GPIO_10 10
+#define        GPIO_11 11
+#define        GPIO_12 12
+#define        GPIO_13 13
+#define        GPIO_14 14
+#define        GPIO_15 15
+#define        GPIO_16 16
+#define        GPIO_17 17
+#define        GPIO_18 18
+#define        GPIO_19 19
+#define        GPIO_20 20
+#define        GPIO_21 21
+#define        GPIO_22 22
+#define        GPIO_23 23
+#define        GPIO_24 24
+#define        GPIO_25 25
+#define        GPIO_26 26
+#define        GPIO_27 27
+#define        GPIO_28 28
+#define        GPIO_29 29
+#define        GPIO_30 30
+#define        GPIO_31 31
+#define        GPIO_32 32
+#define        GPIO_33 33
+#define        GPIO_34 34
+#define        GPIO_35 35
+#define        GPIO_36 36
+#define        GPIO_37 37
+#define        GPIO_38 38
+#define        GPIO_39 39
+#define        GPIO_40 40
+#define        GPIO_41 41
+#define        GPIO_42 42
+#define        GPIO_43 43
+#define        GPIO_44 44
+#define        GPIO_45 45
+#define        GPIO_46 46
+#define        GPIO_47 47
+
+
+#define PERIPHERAL_USAGE 1
+#define GPIO_USAGE 0
+
+#ifdef BF533_FAMILY
+#define MAX_BLACKFIN_GPIOS 16
+#endif
+
+#ifdef BF537_FAMILY
+#define MAX_BLACKFIN_GPIOS 48
+#define PORT_F 0
+#define PORT_G 1
+#define PORT_H 2
+#define PORT_J 3
+
+#define        GPIO_PF0        0
+#define        GPIO_PF1        1
+#define        GPIO_PF2        2
+#define        GPIO_PF3        3
+#define        GPIO_PF4        4
+#define        GPIO_PF5        5
+#define        GPIO_PF6        6
+#define        GPIO_PF7        7
+#define        GPIO_PF8        8
+#define        GPIO_PF9        9
+#define        GPIO_PF10       10
+#define        GPIO_PF11       11
+#define        GPIO_PF12       12
+#define        GPIO_PF13       13
+#define        GPIO_PF14       14
+#define        GPIO_PF15       15
+#define        GPIO_PG0        16
+#define        GPIO_PG1        17
+#define        GPIO_PG2        18
+#define        GPIO_PG3        19
+#define        GPIO_PG4        20
+#define        GPIO_PG5        21
+#define        GPIO_PG6        22
+#define        GPIO_PG7        23
+#define        GPIO_PG8        24
+#define        GPIO_PG9        25
+#define        GPIO_PG10       26
+#define        GPIO_PG11       27
+#define        GPIO_PG12       28
+#define        GPIO_PG13       29
+#define        GPIO_PG14       30
+#define        GPIO_PG15       31
+#define        GPIO_PH0        32
+#define        GPIO_PH1        33
+#define        GPIO_PH2        34
+#define        GPIO_PH3        35
+#define        GPIO_PH4        36
+#define        GPIO_PH5        37
+#define        GPIO_PH6        38
+#define        GPIO_PH7        39
+#define        GPIO_PH8        40
+#define        GPIO_PH9        41
+#define        GPIO_PH10       42
+#define        GPIO_PH11       43
+#define        GPIO_PH12       44
+#define        GPIO_PH13       45
+#define        GPIO_PH14       46
+#define        GPIO_PH15       47
+
+#endif
+
+#ifdef BF561_FAMILY
+#define MAX_BLACKFIN_GPIOS 48
+#define PORT_FIO0 0
+#define PORT_FIO1 1
+#define PORT_FIO2 2
+#endif
+
+#ifndef __ASSEMBLY__
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin General Purpose Ports Access Functions
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: These functions abstract direct register access
+*              to Blackfin processor General Purpose
+*              Ports Regsiters
+*
+* CAUTION: These functions do not belong to the GPIO Driver API
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+void set_gpio_dir(unsigned short, unsigned short);
+void set_gpio_inen(unsigned short, unsigned short);
+void set_gpio_polar(unsigned short, unsigned short);
+void set_gpio_edge(unsigned short, unsigned short);
+void set_gpio_both(unsigned short, unsigned short);
+void set_gpio_data(unsigned short, unsigned short);
+void set_gpio_maska(unsigned short, unsigned short);
+void set_gpio_maskb(unsigned short, unsigned short);
+void set_gpio_toggle(unsigned short);
+void set_gpiop_dir(unsigned short, unsigned short);
+void set_gpiop_inen(unsigned short, unsigned short);
+void set_gpiop_polar(unsigned short, unsigned short);
+void set_gpiop_edge(unsigned short, unsigned short);
+void set_gpiop_both(unsigned short, unsigned short);
+void set_gpiop_data(unsigned short, unsigned short);
+void set_gpiop_maska(unsigned short, unsigned short);
+void set_gpiop_maskb(unsigned short, unsigned short);
+unsigned short get_gpio_dir(unsigned short);
+unsigned short get_gpio_inen(unsigned short);
+unsigned short get_gpio_polar(unsigned short);
+unsigned short get_gpio_edge(unsigned short);
+unsigned short get_gpio_both(unsigned short);
+unsigned short get_gpio_maska(unsigned short);
+unsigned short get_gpio_maskb(unsigned short);
+unsigned short get_gpio_data(unsigned short);
+unsigned short get_gpiop_dir(unsigned short);
+unsigned short get_gpiop_inen(unsigned short);
+unsigned short get_gpiop_polar(unsigned short);
+unsigned short get_gpiop_edge(unsigned short);
+unsigned short get_gpiop_both(unsigned short);
+unsigned short get_gpiop_maska(unsigned short);
+unsigned short get_gpiop_maskb(unsigned short);
+unsigned short get_gpiop_data(unsigned short);
+
+struct gpio_port_t {
+       unsigned short data;
+       unsigned short dummy1;
+       unsigned short data_clear;
+       unsigned short dummy2;
+       unsigned short data_set;
+       unsigned short dummy3;
+       unsigned short toggle;
+       unsigned short dummy4;
+       unsigned short maska;
+       unsigned short dummy5;
+       unsigned short maska_clear;
+       unsigned short dummy6;
+       unsigned short maska_set;
+       unsigned short dummy7;
+       unsigned short maska_toggle;
+       unsigned short dummy8;
+       unsigned short maskb;
+       unsigned short dummy9;
+       unsigned short maskb_clear;
+       unsigned short dummy10;
+       unsigned short maskb_set;
+       unsigned short dummy11;
+       unsigned short maskb_toggle;
+       unsigned short dummy12;
+       unsigned short dir;
+       unsigned short dummy13;
+       unsigned short polar;
+       unsigned short dummy14;
+       unsigned short edge;
+       unsigned short dummy15;
+       unsigned short both;
+       unsigned short dummy16;
+       unsigned short inen;
+};
+
+#ifdef CONFIG_PM
+#define PM_WAKE_RISING 0x1
+#define PM_WAKE_FALLING        0x2
+#define PM_WAKE_HIGH   0x4
+#define PM_WAKE_LOW    0x8
+#define PM_WAKE_BOTH_EDGES     (PM_WAKE_RISING | PM_WAKE_FALLING)
+
+int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type);
+void gpio_pm_wakeup_free(unsigned short gpio);
+unsigned int gpio_pm_setup(void);
+void gpio_pm_restore(void);
+
+struct gpio_port_s {
+       unsigned short data;
+       unsigned short data_clear;
+       unsigned short data_set;
+       unsigned short toggle;
+       unsigned short maska;
+       unsigned short maska_clear;
+       unsigned short maska_set;
+       unsigned short maska_toggle;
+       unsigned short maskb;
+       unsigned short maskb_clear;
+       unsigned short maskb_set;
+       unsigned short maskb_toggle;
+       unsigned short dir;
+       unsigned short polar;
+       unsigned short edge;
+       unsigned short both;
+       unsigned short inen;
+
+       unsigned short fer;
+};
+#endif /*CONFIG_PM*/
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: Blackfin GPIO Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+int gpio_request(unsigned short, const char *);
+void gpio_free(unsigned short);
+
+void gpio_set_value(unsigned short gpio, unsigned short arg);
+unsigned short gpio_get_value(unsigned short gpio);
+
+#define gpio_get_value(gpio)           get_gpio_data(gpio)
+#define gpio_set_value(gpio, value)    set_gpio_data(gpio, value)
+
+void gpio_direction_input(unsigned short gpio);
+void gpio_direction_output(unsigned short gpio);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_BLACKFIN_GPIO_H__ */
diff --git a/include/asm-blackfin/hardirq.h b/include/asm-blackfin/hardirq.h
new file mode 100644 (file)
index 0000000..0cab0d3
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __BFIN_HARDIRQ_H
+#define __BFIN_HARDIRQ_H
+
+#include <linux/cache.h>
+#include <linux/threads.h>
+#include <asm/irq.h>
+
+typedef struct {
+       unsigned int __softirq_pending;
+       unsigned int __syscall_count;
+       struct task_struct *__ksoftirqd_task;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+/*
+ * We put the hardirq and softirq counter into the preemption
+ * counter. The bitmask has the following meaning:
+ *
+ * - bits 0-7 are the preemption count (max preemption depth: 256)
+ * - bits 8-15 are the softirq count (max # of softirqs: 256)
+ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ *
+ * - ( bit 26 is the PREEMPT_ACTIVE flag. )
+ *
+ * PREEMPT_MASK: 0x000000ff
+ * HARDIRQ_MASK: 0x0000ff00
+ * SOFTIRQ_MASK: 0x00ff0000
+ */
+
+#define HARDIRQ_BITS   8
+
+#ifdef NR_IRQS
+# if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+# endif
+#endif
+
+#define __ARCH_IRQ_EXIT_IRQS_DISABLED  1
+
+#endif
diff --git a/include/asm-blackfin/hw_irq.h b/include/asm-blackfin/hw_irq.h
new file mode 100644 (file)
index 0000000..5b51eae
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_BFIN_HW_IRQ_H
+#define __ASM_BFIN_HW_IRQ_H
+
+/* Dummy include. */
+
+#endif
diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h
new file mode 100644 (file)
index 0000000..41b2db4
--- /dev/null
@@ -0,0 +1,32 @@
+/****************************************************************************/
+
+/*
+ *  linux/include/asm-blackfin/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ *  Copyright (C) 2001       Lineo Inc., davidm@snapgear.com
+ *  Copyright (C) 2002       Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 2002       Yoshinori Sato (ysato@users.sourceforge.jp)
+ *  Copyright (C) 2005       Hennerich Michael (hennerich@blackfin.uclinux.org)
+ */
+
+/****************************************************************************/
+#ifndef _BLACKFIN_IDE_H
+#define _BLACKFIN_IDE_H
+/****************************************************************************/
+#ifdef __KERNEL__
+/****************************************************************************/
+
+#define MAX_HWIFS      1
+
+/* Legacy ... BLK_DEV_IDECS */
+#define IDE_ARCH_OBSOLETE_INIT
+#define ide_default_io_ctl(base)       ((base) + 0x206) /* obsolete */
+
+
+#include <asm-generic/ide_iops.h>
+
+/****************************************************************************/
+#endif                         /* __KERNEL__ */
+#endif                         /* _BLACKFIN_IDE_H */
+/****************************************************************************/
diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h
new file mode 100644 (file)
index 0000000..7e6995e
--- /dev/null
@@ -0,0 +1,207 @@
+#ifndef _BFIN_IO_H
+#define _BFIN_IO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
+#include <linux/compiler.h>
+
+/*
+ * These are for ISA/PCI shared memory _only_ and should never be used
+ * on any other type of memory, including Zorro memory. They are meant to
+ * access the bus in the bus byte order which is little-endian!.
+ *
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the bfin architecture, we just read/write the
+ * memory location directly.
+ */
+#ifndef __ASSEMBLY__
+
+static inline unsigned char readb(void __iomem *addr)
+{
+       unsigned int val;
+       int tmp;
+
+       __asm__ __volatile__ ("cli %1;\n\t"
+                       "NOP; NOP; SSYNC;\n\t"
+                       "%0 = b [%2] (z);\n\t"
+                       "sti %1;\n\t"
+                       : "=d"(val), "=d"(tmp): "a"(addr)
+                       );
+
+       return (unsigned char) val;
+}
+
+static inline unsigned short readw(void __iomem *addr)
+{
+       unsigned int val;
+       int tmp;
+
+       __asm__ __volatile__ ("cli %1;\n\t"
+                       "NOP; NOP; SSYNC;\n\t"
+                       "%0 = w [%2] (z);\n\t"
+                       "sti %1;\n\t"
+                       : "=d"(val), "=d"(tmp): "a"(addr)
+                       );
+
+       return (unsigned short) val;
+}
+
+static inline unsigned int readl(void __iomem *addr)
+{
+       unsigned int val;
+       int tmp;
+
+       __asm__ __volatile__ ("cli %1;\n\t"
+                       "NOP; NOP; SSYNC;\n\t"
+                       "%0 = [%2];\n\t"
+                       "sti %1;\n\t"
+                       : "=d"(val), "=d"(tmp): "a"(addr)
+                       );
+       return val;
+}
+
+#endif /*  __ASSEMBLY__ */
+
+#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)     memcpy((void *)(a),(b),(c))
+
+#define inb(addr)    readb(addr)
+#define inw(addr)    readw(addr)
+#define inl(addr)    readl(addr)
+#define outb(x,addr) ((void) writeb(x,addr))
+#define outw(x,addr) ((void) writew(x,addr))
+#define outl(x,addr) ((void) writel(x,addr))
+
+#define inb_p(addr)    inb(addr)
+#define inw_p(addr)    inw(addr)
+#define inl_p(addr)    inl(addr)
+#define outb_p(x,addr) outb(x,addr)
+#define outw_p(x,addr) outw(x,addr)
+#define outl_p(x,addr) outl(x,addr)
+
+#define ioread8_rep(a,d,c)     insb(a,d,c)
+#define ioread16_rep(a,d,c)    insw(a,d,c)
+#define ioread32_rep(a,d,c)    insl(a,d,c)
+#define iowrite8_rep(a,s,c)    outsb(a,s,c)
+#define iowrite16_rep(a,s,c)   outsw(a,s,c)
+#define iowrite32_rep(a,s,c)   outsl(a,s,c)
+
+#define ioread8(X)                     readb(X)
+#define ioread16(X)                    readw(X)
+#define ioread32(X)                    readl(X)
+#define iowrite8(val,X)                        writeb(val,X)
+#define iowrite16(val,X)               writew(val,X)
+#define iowrite32(val,X)               writel(val,X)
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* Values for nocacheflag and cmode */
+#define IOMAP_NOCACHE_SER              1
+
+#ifndef __ASSEMBLY__
+
+extern void outsb(void __iomem *port, const void *addr, unsigned long count);
+extern void outsw(void __iomem *port, const void *addr, unsigned long count);
+extern void outsl(void __iomem *port, const void *addr, unsigned long count);
+
+extern void insb(const void __iomem *port, void *addr, unsigned long count);
+extern void insw(const void __iomem *port, void *addr, unsigned long count);
+extern void insl(const void __iomem *port, void *addr, unsigned long count);
+
+/*
+ * Map some physical address range into the kernel address space.
+ */
+static inline void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
+                               int cacheflag)
+{
+       return (void __iomem *)physaddr;
+}
+
+/*
+ * Unmap a ioremap()ed region again
+ */
+static inline void iounmap(void *addr)
+{
+}
+
+/*
+ * __iounmap unmaps nearly everything, so be careful
+ * it doesn't free currently pointer/page tables anymore but it
+ * wans't used anyway and might be added later.
+ */
+static inline void __iounmap(void *addr, unsigned long size)
+{
+}
+
+/*
+ * Set new cache mode for some kernel address space.
+ * The caller must push data for that range itself, if such data may already
+ * be in the cache.
+ */
+static inline void kernel_set_cachemode(void *addr, unsigned long size,
+                                       int cmode)
+{
+}
+
+static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
+{
+       return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+}
+static inline void __iomem *ioremap_nocache(unsigned long physaddr,
+                                           unsigned long size)
+{
+       return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+}
+
+extern void blkfin_inv_cache_all(void);
+
+#endif
+
+#define        ioport_map(port, nr)            ((void __iomem*)(port))
+#define        ioport_unmap(addr)
+
+#define dma_cache_inv(_start,_size) do { blkfin_inv_cache_all();} while (0)
+#define dma_cache_wback(_start,_size) do { } while (0)
+#define dma_cache_wback_inv(_start,_size) do { blkfin_inv_cache_all();} while (0)
+
+/* Pages to physical address... */
+#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
+#define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
+
+#define mm_ptov(vaddr)         ((void *) (vaddr))
+#define mm_vtop(vaddr)         ((unsigned long) (vaddr))
+#define phys_to_virt(vaddr)    ((void *) (vaddr))
+#define virt_to_phys(vaddr)    ((unsigned long) (vaddr))
+
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p)   __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p)  p
+
+#endif                         /* __KERNEL__ */
+
+#endif                         /* _BFIN_IO_H */
diff --git a/include/asm-blackfin/ioctl.h b/include/asm-blackfin/ioctl.h
new file mode 100644 (file)
index 0000000..b279fe0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-blackfin/ioctls.h b/include/asm-blackfin/ioctls.h
new file mode 100644 (file)
index 0000000..8356204
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __ARCH_BFIN_IOCTLS_H__
+#define __ARCH_BFIN_IOCTLS_H__
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402
+#define TCSETSW                0x5403
+#define TCSETSF                0x5404
+#define TCGETA         0x5405
+#define TCSETA         0x5406
+#define TCSETAW                0x5407
+#define TCSETAF                0x5408
+#define TCSBRK         0x5409
+#define TCXONC         0x540A
+#define TCFLSH         0x540B
+#define TIOCEXCL       0x540C
+#define TIOCNXCL       0x540D
+#define TIOCSCTTY      0x540E
+#define TIOCGPGRP      0x540F
+#define TIOCSPGRP      0x5410
+#define TIOCOUTQ       0x5411
+#define TIOCSTI                0x5412
+#define TIOCGWINSZ     0x5413
+#define TIOCSWINSZ     0x5414
+#define TIOCMGET       0x5415
+#define TIOCMBIS       0x5416
+#define TIOCMBIC       0x5417
+#define TIOCMSET       0x5418
+#define TIOCGSOFTCAR   0x5419
+#define TIOCSSOFTCAR   0x541A
+#define FIONREAD       0x541B
+#define TIOCINQ                FIONREAD
+#define TIOCLINUX      0x541C
+#define TIOCCONS       0x541D
+#define TIOCGSERIAL    0x541E
+#define TIOCSSERIAL    0x541F
+#define TIOCPKT                0x5420
+#define FIONBIO                0x5421
+#define TIOCNOTTY      0x5422
+#define TIOCSETD       0x5423
+#define TIOCGETD       0x5424
+#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
+#define TIOCGSID       0x5429  /* Return the session ID of FD */
+#define TIOCGPTN       _IOR('T',0x30, unsigned int)    /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK     _IOW('T',0x31, int)     /* Lock/unlock Pty */
+
+#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
+#define FIOCLEX                0x5451
+#define FIOASYNC       0x5452
+#define TIOCSERCONFIG  0x5453
+#define TIOCSERGWILD   0x5454
+#define TIOCSERSWILD   0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458  /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+
+#define FIOQSIZE       0x545E
+
+/* Used for packet mode */
+#define TIOCPKT_DATA            0
+#define TIOCPKT_FLUSHREAD       1
+#define TIOCPKT_FLUSHWRITE      2
+#define TIOCPKT_STOP            4
+#define TIOCPKT_START           8
+#define TIOCPKT_NOSTOP         16
+#define TIOCPKT_DOSTOP         32
+
+#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+
+#endif                         /* __ARCH_BFIN_IOCTLS_H__ */
diff --git a/include/asm-blackfin/ipc.h b/include/asm-blackfin/ipc.h
new file mode 100644 (file)
index 0000000..a46e3d9
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ipc.h>
diff --git a/include/asm-blackfin/ipcbuf.h b/include/asm-blackfin/ipcbuf.h
new file mode 100644 (file)
index 0000000..8f0899c
--- /dev/null
@@ -0,0 +1,30 @@
+/* Changes origined from m68k version.    Lineo Inc.  May 2001   */
+
+#ifndef __BFIN_IPCBUF_H__
+#define __BFIN_IPCBUF_H__
+
+/*
+ * The user_ipc_perm structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm {
+       __kernel_key_t key;
+       __kernel_uid32_t uid;
+       __kernel_gid32_t gid;
+       __kernel_uid32_t cuid;
+       __kernel_gid32_t cgid;
+       __kernel_mode_t mode;
+       unsigned short __pad1;
+       unsigned short seq;
+       unsigned short __pad2;
+       unsigned long __unused1;
+       unsigned long __unused2;
+};
+
+#endif                         /* __BFIN_IPCBUF_H__ */
diff --git a/include/asm-blackfin/irq.h b/include/asm-blackfin/irq.h
new file mode 100644 (file)
index 0000000..65480da
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * Changed by HuTao Apr18, 2003
+ *
+ * Copyright was missing when I got the code so took from MIPS arch ...MaTed---
+ * Copyright (C) 1994 by Waldorf GMBH, written by Ralf Baechle
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 by Ralf Baechle
+ *
+ * Adapted for BlackFin (ADI) by Ted Ma <mated@sympatico.ca>
+ * Copyright (c) 2002 Arcturus Networks Inc. (www.arcturusnetworks.com)
+ * Copyright (c) 2002 Lineo, Inc. <mattw@lineo.com>
+ */
+
+#ifndef _BFIN_IRQ_H_
+#define _BFIN_IRQ_H_
+
+#include <asm/mach/irq.h>
+#include <asm/ptrace.h>
+
+/*******************************************************************************
+ *****   INTRODUCTION ***********
+ *   On the Blackfin, the interrupt structure allows remmapping of the hardware
+ *   levels.
+ * - I'm going to assume that the H/W level is going to stay at the default
+ *   settings. If someone wants to go through and abstart this out, feel free
+ *   to mod the interrupt numbering scheme.
+ * - I'm abstracting the interrupts so that uClinux does not know anything
+ *   about the H/W levels. If you want to change the H/W AND keep the abstracted
+ *   levels that uClinux sees, you should be able to do most of it here.
+ * - I've left the "abstract" numbering sparce in case someone wants to pull the
+ *   interrupts apart (just the TX/RX for the various devices)
+ *******************************************************************************/
+
+/* SYS_IRQS and NR_IRQS are defined in <asm/mach-bf5xx/irq.h>*/
+
+/*
+ * Machine specific interrupt sources.
+ *
+ * Adding an interrupt service routine for a source with this bit
+ * set indicates a special machine specific interrupt source.
+ * The machine specific files define these sources.
+ *
+ * The IRQ_MACHSPEC bit is now gone - the only thing it did was to
+ * introduce unnecessary overhead.
+ *
+ * All interrupt handling is actually machine specific so it is better
+ * to use function pointers, as used by the Sparc port, and select the
+ * interrupt handling functions when initializing the kernel. This way
+ * we save some unnecessary overhead at run-time.
+ *                                                      01/11/97 - Jes
+ */
+
+extern void ack_bad_irq(unsigned int irq);
+
+static __inline__ int irq_canonicalize(int irq)
+{
+       return irq;
+}
+
+/* count of spurious interrupts */
+/* extern volatile unsigned int num_spurious; */
+
+#ifndef NO_IRQ
+#define NO_IRQ ((unsigned int)(-1))
+#endif
+
+#endif                         /* _BFIN_IRQ_H_ */
diff --git a/include/asm-blackfin/irq_handler.h b/include/asm-blackfin/irq_handler.h
new file mode 100644 (file)
index 0000000..d830f0a
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _IRQ_HANDLER_H
+#define _IRQ_HANDLER_H
+
+/* BASE LEVEL interrupt handler routines */
+asmlinkage void evt_emulation(void);
+asmlinkage void evt_exception(void);
+asmlinkage void trap(void);
+asmlinkage void evt_ivhw(void);
+asmlinkage void evt_timer(void);
+asmlinkage void evt_evt2(void);
+asmlinkage void evt_evt7(void);
+asmlinkage void evt_evt8(void);
+asmlinkage void evt_evt9(void);
+asmlinkage void evt_evt10(void);
+asmlinkage void evt_evt11(void);
+asmlinkage void evt_evt12(void);
+asmlinkage void evt_evt13(void);
+asmlinkage void evt_soft_int1(void);
+asmlinkage void evt_system_call(void);
+asmlinkage void init_exception_buff(void);
+
+#endif
diff --git a/include/asm-blackfin/irq_regs.h b/include/asm-blackfin/irq_regs.h
new file mode 100644 (file)
index 0000000..3dd9c0b
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-blackfin/kdebug.h b/include/asm-blackfin/kdebug.h
new file mode 100644 (file)
index 0000000..6ece1b0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
diff --git a/include/asm-blackfin/kmap_types.h b/include/asm-blackfin/kmap_types.h
new file mode 100644 (file)
index 0000000..e215f71
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+enum km_type {
+       KM_BOUNCE_READ,
+       KM_SKB_SUNRPC_DATA,
+       KM_SKB_DATA_SOFTIRQ,
+       KM_USER0,
+       KM_USER1,
+       KM_BIO_SRC_IRQ,
+       KM_BIO_DST_IRQ,
+       KM_PTE0,
+       KM_PTE1,
+       KM_IRQ0,
+       KM_IRQ1,
+       KM_SOFTIRQ0,
+       KM_SOFTIRQ1,
+       KM_TYPE_NR
+};
+
+#endif
diff --git a/include/asm-blackfin/l1layout.h b/include/asm-blackfin/l1layout.h
new file mode 100644 (file)
index 0000000..c13ded7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * l1layout.h
+ * Defines a layout of L1 scratchpad memory that userspace can rely on.
+ */
+
+#ifndef _L1LAYOUT_H_
+#define _L1LAYOUT_H_
+
+#include <asm/blackfin.h>
+
+#ifndef __ASSEMBLY__
+
+/* Data that is "mapped" into the process VM at the start of the L1 scratch
+   memory, so that each process can access it at a fixed address.  Used for
+   stack checking.  */
+struct l1_scratch_task_info
+{
+       /* Points to the start of the stack.  */
+       void *stack_start;
+       /* Not updated by the kernel; a user process can modify this to
+          keep track of the lowest address of the stack pointer during its
+          runtime.  */
+       void *lowest_sp;
+};
+
+/* A pointer to the structure in memory.  */
+#define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)L1_SCRATCH_START)
+
+#endif
+
+#endif
diff --git a/include/asm-blackfin/linkage.h b/include/asm-blackfin/linkage.h
new file mode 100644 (file)
index 0000000..5a822bb
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN .align 4
+#define __ALIGN_STR ".align 4"
+
+#endif
diff --git a/include/asm-blackfin/local.h b/include/asm-blackfin/local.h
new file mode 100644 (file)
index 0000000..75afffb
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __BLACKFIN_LOCAL_H
+#define __BLACKFIN_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif                         /* __BLACKFIN_LOCAL_H */
diff --git a/include/asm-blackfin/mach-bf533/anomaly.h b/include/asm-blackfin/mach-bf533/anomaly.h
new file mode 100644 (file)
index 0000000..a84d390
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * File:         include/asm-blackfin/mach-bf533/anomaly.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This file shoule be up to date with:
+ *  - Revision U, May 17, 2006; ADSP-BF533 Blackfin Processor Anomaly List
+ *  - Revision Y, May 17, 2006; ADSP-BF532 Blackfin Processor Anomaly List
+ *  - Revision T, May 17, 2006; ADSP-BF531 Blackfin Processor Anomaly List
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+
+/* We do not support 0.1 or 0.2 silicon - sorry */
+#if (defined(CONFIG_BF_REV_0_1) || defined(CONFIG_BF_REV_0_2))
+#error Kernel will not work on BF533 Version 0.1 or 0.2
+#endif
+
+/* Issues that are common to 0.5, 0.4, and 0.3 silicon */
+#if  (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_4) || defined(CONFIG_BF_REV_0_3))
+#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
+                            slot1 and store of a P register in slot 2 is not
+                            supported */
+#define ANOMALY_05000105 /* Watchpoint Status Register (WPSTAT) bits are set on
+                            every corresponding match */
+#define ANOMALY_05000119 /* DMA_RUN bit is not valid after a Peripheral Receive
+                            Channel DMA stops */
+#define ANOMALY_05000122 /* Rx.H can not be used to access 16-bit System MMR
+                            registers. */
+#define ANOMALY_05000166 /* PPI Data Lengths Between 8 and 16 do not zero out
+                            upper bits*/
+#define ANOMALY_05000167 /* Turning Serial Ports on With External Frame Syncs */
+#define ANOMALY_05000180 /* PPI_DELAY not functional in PPI modes with 0 frame
+                            syncs */
+#define ANOMALY_05000208 /* VSTAT status bit in PLL_STAT register is not
+                            functional */
+#define ANOMALY_05000219 /* NMI event at boot time results in unpredictable
+                            state */
+#define ANOMALY_05000229 /* SPI Slave Boot Mode modifies registers */
+#define ANOMALY_05000272 /* Certain data cache write through modes fail for
+                            VDDint <=0.9V */
+#define ANOMALY_05000273 /* Writes to Synchronous SDRAM memory may be lost */
+#define ANOMALY_05000277 /* Writes to a flag data register one SCLK cycle after
+                            an edge is detected may clear interrupt */
+#define ANOMALY_05000278 /* Disabling Peripherals with DMA running may cause
+                            DMA system instability */
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context is
+                            not restored */
+#define ANOMALY_05000282 /* Memory DMA corruption with 32-bit data and traffic
+                            control */
+#define ANOMALY_05000283 /* A system MMR write is stalled indefinitely when
+                            killed in a particular stage*/
+#define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
+                           registers are interrupted */
+#define ANOMALY_05000311 /* Erroneous flag pin operations under specific sequences*/
+
+#endif
+
+/* These issues only occur on 0.3 or 0.4 BF533 */
+#if (defined(CONFIG_BF_REV_0_4) || defined(CONFIG_BF_REV_0_3))
+#define ANOMALY_05000099 /* UART Line Status Register (UART_LSR) bits are not
+                            updated at the same time. */
+#define ANOMALY_05000158 /* Boot fails when data cache enabled: Data from a Data
+                           Cache Fill can be corrupted after or during
+                            Instruction DMA if certain core stalls exist */
+#define ANOMALY_05000179 /* PPI_COUNT cannot be programmed to 0 in General
+                            Purpose TX or RX modes */
+#define ANOMALY_05000198 /* Failing SYSTEM MMR accesses when stalled by
+                            preceding memory read */
+#define ANOMALY_05000200 /* SPORT TFS and DT are incorrectly driven during
+                            inactive channels in certain conditions */
+#define ANOMALY_05000202 /* Possible infinite stall with specific dual dag
+                            situation */
+#define ANOMALY_05000215 /* UART TX Interrupt masked erroneously */
+#define ANOMALY_05000225 /* Incorrect pulse-width of UART start-bit */
+#define ANOMALY_05000227 /* Scratchpad memory bank reads may return incorrect
+                            data*/
+#define ANOMALY_05000230 /* UART Receiver is less robust against Baudrate
+                            Differences in certain Conditions */
+#define ANOMALY_05000231 /* UART STB bit incorrectly affects receiver setting */
+#define ANOMALY_05000242 /* DF bit in PLL_CTL register does not respond to
+                            hardware reset */
+#define ANOMALY_05000244 /* With instruction cache enabled, a CSYNC or SSYNC or
+                            IDLE around a Change of Control causes
+                            unpredictable results */
+#define ANOMALY_05000245 /* Spurious Hardware Error from an access in the
+                            shadow of a conditional branch */
+#define ANOMALY_05000246 /* Data CPLB's should prevent spurious hardware
+                            errors */
+#define ANOMALY_05000253 /* Maximum external clock speed for Timers */
+#define ANOMALY_05000255 /* Entering Hibernate Mode with RTC Seconds event
+                            interrupt not functional */
+#define ANOMALY_05000257 /* An interrupt or exception during short Hardware
+                            loops may cause the instruction fetch unit to
+                            malfunction */
+#define ANOMALY_05000258 /* Instruction Cache is corrupted when bit 9 and 12 of
+                            the ICPLB Data registers differ */
+#define ANOMALY_05000260 /* ICPLB_STATUS MMR register may be corrupted */
+#define ANOMALY_05000261 /* DCPLB_FAULT_ADDR MMR register may be corrupted */
+#define ANOMALY_05000262 /* Stores to data cache may be lost */
+#define ANOMALY_05000263 /* Hardware loop corrupted when taking an ICPLB exception */
+#define ANOMALY_05000264 /* A Sync instruction (CSYNC, SSYNC) or an IDLE
+                            instruction will cause an infinite stall in the
+                            second to last instruction in a hardware loop */
+#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on
+                            SPORT external receive and transmit clocks. */
+#define ANOMALY_05000269 /* High I/O activity causes the output voltage of the
+                            internal voltage regulator (VDDint) to increase. */
+#define ANOMALY_05000270 /* High I/O activity causes the output voltage of the
+                            internal voltage regulator (VDDint) to decrease */
+#endif
+
+/* These issues are only on 0.4 silicon */
+#if (defined(CONFIG_BF_REV_0_4))
+#define ANOMALY_05000234 /* Incorrect Revision Number in DSPID Register */
+#define ANOMALY_05000250 /* Incorrect Bit-Shift of Data Word in Multichannel
+                            (TDM) */
+#endif
+
+/* These issues are only on 0.3 silicon */
+#if defined(CONFIG_BF_REV_0_3)
+#define ANOMALY_05000183 /* Timer Pin limitations for PPI TX Modes with
+                            External Frame Syncs */
+#define ANOMALY_05000189 /* False Protection Exceptions caused by Speculative
+                            Instruction or Data Fetches, or by Fetches at the
+                            boundary of reserved memory space */
+#define ANOMALY_05000193 /* False Flag Pin Interrupts on Edge Sensitive Inputs
+                            when polarity setting is changed */
+#define ANOMALY_05000194 /* Sport Restarting in specific modes may cause data
+                            corruption */
+#define ANOMALY_05000199 /* DMA current address shows wrong value during carry
+                            fix */
+#define ANOMALY_05000201 /* Receive frame sync not ignored during active
+                            frames in sport MCM */
+#define ANOMALY_05000203 /* Specific sequence that can cause DMA error or DMA
+                            stopping */
+#if defined(CONFIG_BF533)
+#define ANOMALY_05000204 /* Incorrect data read with write-through cache and
+                            allocate cache lines on reads only mode */
+#endif /* CONFIG_BF533 */
+#define ANOMALY_05000207 /* Recovery from "brown-out" condition */
+#define ANOMALY_05000209 /* Speed-Path in computational unit affects certain
+                            instructions */
+#define ANOMALY_05000233 /* PPI_FS3 is not driven in 2 or 3 internal Frame
+                            Sync Transmit Mode */
+#define ANOMALY_05000271 /* Spontaneous reset of Internal Voltage Regulator */
+#endif
+
+#endif /*  _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf533/bf533.h b/include/asm-blackfin/mach-bf533/bf533.h
new file mode 100644 (file)
index 0000000..185fc12
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * File:         include/asm-blackfin/mach-bf533/bf533.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __MACH_BF533_H__
+#define __MACH_BF533_H__
+
+#define SUPPORTED_REVID 2
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15            0x8000
+#define IMASK_IVG14            0x4000
+#define IMASK_IVG13            0x2000
+#define IMASK_IVG12            0x1000
+
+#define IMASK_IVG11            0x0800
+#define IMASK_IVG10            0x0400
+#define IMASK_IVG9             0x0200
+#define IMASK_IVG8             0x0100
+
+#define IMASK_IVG7             0x0080
+#define IMASK_IVGTMR           0x0040
+#define IMASK_IVGHW            0x0020
+
+/***************************/
+
+
+#define BLKFIN_DSUBBANKS       4
+#define BLKFIN_DWAYS           2
+#define BLKFIN_DLINES          64
+#define BLKFIN_ISUBBANKS       4
+#define BLKFIN_IWAYS           4
+#define BLKFIN_ILINES          32
+
+#define WAY0_L                 0x1
+#define WAY1_L                 0x2
+#define WAY01_L                        0x3
+#define WAY2_L                 0x4
+#define WAY02_L                        0x5
+#define        WAY12_L                 0x6
+#define        WAY012_L                0x7
+
+#define        WAY3_L                  0x8
+#define        WAY03_L                 0x9
+#define        WAY13_L                 0xA
+#define        WAY013_L                0xB
+
+#define        WAY32_L                 0xC
+#define        WAY320_L                0xD
+#define        WAY321_L                0xE
+#define        WAYALL_L                0xF
+
+#define DMC_ENABLE (2<<2)      /*yes, 2, not 1 */
+
+/* IAR0 BIT FIELDS*/
+#define RTC_ERROR_BIT                  0x0FFFFFFF
+#define UART_ERROR_BIT                 0xF0FFFFFF
+#define SPORT1_ERROR_BIT               0xFF0FFFFF
+#define SPI_ERROR_BIT                  0xFFF0FFFF
+#define SPORT0_ERROR_BIT               0xFFFF0FFF
+#define PPI_ERROR_BIT                  0xFFFFF0FF
+#define DMA_ERROR_BIT                  0xFFFFFF0F
+#define PLLWAKE_ERROR_BIT              0xFFFFFFFF
+
+/* IAR1 BIT FIELDS*/
+#define DMA7_UARTTX_BIT                        0x0FFFFFFF
+#define DMA6_UARTRX_BIT                        0xF0FFFFFF
+#define DMA5_SPI_BIT                   0xFF0FFFFF
+#define DMA4_SPORT1TX_BIT              0xFFF0FFFF
+#define DMA3_SPORT1RX_BIT              0xFFFF0FFF
+#define DMA2_SPORT0TX_BIT              0xFFFFF0FF
+#define DMA1_SPORT0RX_BIT              0xFFFFFF0F
+#define DMA0_PPI_BIT                   0xFFFFFFFF
+
+/* IAR2 BIT FIELDS*/
+#define WDTIMER_BIT                    0x0FFFFFFF
+#define MEMDMA1_BIT                    0xF0FFFFFF
+#define MEMDMA0_BIT                    0xFF0FFFFF
+#define PFB_BIT                                0xFFF0FFFF
+#define PFA_BIT                                0xFFFF0FFF
+#define TIMER2_BIT                     0xFFFFF0FF
+#define TIMER1_BIT                     0xFFFFFF0F
+#define TIMER0_BIT                     0xFFFFFFFF
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL     ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL     ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+#ifdef CONFIG_C_CDPRIO
+#define V_CDPRIO 0x100
+#else
+#define V_CDPRIO 0x0
+#endif
+
+#define AMGCTLVAL      (V_AMBEN | V_AMCKEN | V_CDPRIO)
+
+#define MAX_VC 650000000
+#define MIN_VC 50000000
+
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
+/********************************PLL Settings **************************************/
+#if (CONFIG_VCO_MULT < 0)
+#error "VCO Multiplier is less than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT == 0)
+#error "VCO Multiplier should be greater than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT > 64)
+#error "VCO Multiplier is more than 64. Please select a different value"
+#endif
+
+#ifndef CONFIG_CLKIN_HALF
+#define CONFIG_VCO_HZ  (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)
+#else
+#define CONFIG_VCO_HZ  ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2)
+#endif
+
+#ifndef CONFIG_PLL_BYPASS
+#define CONFIG_CCLK_HZ (CONFIG_VCO_HZ/CONFIG_CCLK_DIV)
+#define CONFIG_SCLK_HZ (CONFIG_VCO_HZ/CONFIG_SCLK_DIV)
+#else
+#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ
+#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ
+#endif
+
+#if (CONFIG_SCLK_DIV < 1)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_SCLK_DIV > 15)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_CCLK_DIV != 1)
+#if (CONFIG_CCLK_DIV != 2)
+#if (CONFIG_CCLK_DIV != 4)
+#if (CONFIG_CCLK_DIV != 8)
+#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value"
+#endif
+#endif
+#endif
+#endif
+
+#if (CONFIG_VCO_HZ > MAX_VC)
+#error "VCO selected is more than maximum value. Please change the VCO multipler"
+#endif
+
+#if (CONFIG_SCLK_HZ > 133000000)
+#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ < 27000000)
+#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ > CONFIG_CCLK_HZ)
+#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ)
+#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ)
+#error "Please select sclk less than cclk"
+#endif
+#endif
+#endif
+
+#if (CONFIG_CCLK_DIV == 1)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV1
+#endif
+#if (CONFIG_CCLK_DIV == 2)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV2
+#endif
+#if (CONFIG_CCLK_DIV == 4)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV4
+#endif
+#if (CONFIG_CCLK_DIV == 8)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV8
+#endif
+#ifndef CONFIG_CCLK_ACT_DIV
+#define CONFIG_CCLK_ACT_DIV   CONFIG_CCLK_DIV_not_defined_properly
+#endif
+
+#if defined(ANOMALY_05000273) && (CONFIG_CCLK_DIV == 1)
+#error ANOMALY 05000273, please make sure CCLK is at least 2x SCLK
+#endif
+
+#endif                         /* CONFIG_BFIN_KERNEL_CLOCK */
+
+#ifdef CONFIG_BF533
+#define CPU "BF533"
+#define CPUID 0x027a5000
+#endif
+#ifdef CONFIG_BF532
+#define CPU "BF532"
+#define CPUID 0x0275A000
+#endif
+#ifdef CONFIG_BF531
+#define CPU "BF531"
+#define CPUID 0x027a5000
+#endif
+#ifndef CPU
+#define        CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#if (CONFIG_MEM_SIZE % 4)
+#error "SDRAM mem size must be multible of 4MB"
+#endif
+
+#define SDRAM_IGENERIC    (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
+#define SDRAM_IKERNEL     (SDRAM_IGENERIC | CPLB_LOCK)
+#define L1_IMEMORY        (               CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
+#define SDRAM_INON_CHBL   (               CPLB_USER_RD | CPLB_VALID)
+
+/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/
+
+#define ANOMALY_05000158_WORKAROUND            0x200
+#ifdef CONFIG_BLKFIN_WB                /*Write Back Policy */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_DIRTY \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#else                          /*Write Through */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW  | CPLB_DIRTY \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#endif
+
+#define L1_DMEMORY       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
+#define SDRAM_DNON_CHBL  (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY)
+#define SDRAM_EBIU       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY)
+#define SDRAM_OOPS      (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
+
+#define SIZE_1K 0x00000400     /* 1K */
+#define SIZE_4K 0x00001000     /* 4K */
+#define SIZE_1M 0x00100000     /* 1M */
+#define SIZE_4M 0x00400000     /* 4M */
+
+#define MAX_CPLBS (16 * 2)
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 1 for ASYNC Memory
+*/
+
+
+#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+
+#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1) * 2)
+
+#endif                         /* __MACH_BF533_H__  */
diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
new file mode 100644 (file)
index 0000000..23bf76a
--- /dev/null
@@ -0,0 +1,108 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+
+#define NR_PORTS                1
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
+
+#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+#define UART_GET_DLH(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
+#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
+#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
+#define UART_PUT_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER),v)
+#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
+#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
+
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+# define CONFIG_SERIAL_BFIN_CTSRTS
+# ifndef CONFIG_UART0_CTS_PIN
+#  define CONFIG_UART0_CTS_PIN -1
+# endif
+# ifndef CONFIG_UART0_RTS_PIN
+#  define CONFIG_UART0_RTS_PIN -1
+# endif
+#endif
+
+struct bfin_serial_port {
+        struct uart_port        port;
+        unsigned int            old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       int                     tx_done;
+       int                     tx_count;
+       struct circ_buf         rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+       struct work_struct      tx_dma_workqueue;
+#else
+       struct work_struct      cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int                     cts_pin;
+       int                     rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+       unsigned long   uart_base_addr;
+       int             uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       unsigned int    uart_tx_dma_channel;
+       unsigned int    uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int             uart_cts_pin;
+       int             uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+       0xFFC00400,
+       IRQ_UART_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART_TX,
+       CH_UART_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+       CONFIG_UART0_CTS_PIN,
+       CONFIG_UART0_RTS_PIN,
+#endif
+};
+
+
+int nr_ports = NR_PORTS;
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       if (uart->cts_pin >= 0) {
+               gpio_request(uart->cts_pin, NULL);
+               gpio_direction_input(uart->cts_pin);
+       }
+       if (uart->rts_pin >= 0) {
+               gpio_request(uart->rts_pin, NULL);
+               gpio_direction_input(uart->rts_pin);
+       }
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf533/blackfin.h b/include/asm-blackfin/mach-bf533/blackfin.h
new file mode 100644 (file)
index 0000000..e438449
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * File:         include/asm-blackfin/mach-bf533/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF533_FAMILY
+
+#include "bf533.h"
+#include "mem_map.h"
+#include "defBF532.h"
+#include "anomaly.h"
+
+#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY))
+#include "cdefBF532.h"
+#endif
+
+#endif                         /* _MACH_BLACKFIN_H_ */
diff --git a/include/asm-blackfin/mach-bf533/cdefBF532.h b/include/asm-blackfin/mach-bf533/cdefBF532.h
new file mode 100644 (file)
index 0000000..1d7c494
--- /dev/null
@@ -0,0 +1,706 @@
+/*
+ * File:         include/asm-blackfin/mach-bf533/cdefBF532.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF532_H
+#define _CDEF_BF532_H
+/*
+#if !defined(__ADSPLPBLACKFIN__)
+#warning cdefBF532.h should only be included for 532 compatible chips.
+#endif
+*/
+/*include all Core registers and bit definitions*/
+#include "defBF532.h"
+
+/*include core specific register pointer definitions*/
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+#include <asm/system.h>
+
+/* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
+#define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
+#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+#define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
+#define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)          bfin_write16(PLL_LOCKCNT,val)
+#define bfin_read_CHIPID()                   bfin_read32(CHIPID)
+#define bfin_read_SWRST()                    bfin_read16(SWRST)
+#define bfin_write_SWRST(val)                bfin_write16(SWRST,val)
+#define bfin_read_SYSCR()                    bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)                bfin_write16(SYSCR,val)
+#define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
+#define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       bfin_write16(VR_CTL, val);
+       __builtin_bfin_ssync();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+       local_irq_save(flags);
+       asm("IDLE;");
+       local_irq_restore(flags);
+       bfin_write32(SIC_IWR, iwr);
+}
+
+/* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
+#define bfin_read_SIC_IAR0()                 bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)             bfin_write32(SIC_IAR0,val)
+#define bfin_read_SIC_IAR1()                 bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)             bfin_write32(SIC_IAR1,val)
+#define bfin_read_SIC_IAR2()                 bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)             bfin_write32(SIC_IAR2,val)
+#define bfin_read_SIC_IAR3()                 bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)             bfin_write32(SIC_IAR3,val)
+#define bfin_read_SIC_IMASK()                bfin_read32(SIC_IMASK)
+#define bfin_write_SIC_IMASK(val)            bfin_write32(SIC_IMASK,val)
+#define bfin_read_SIC_ISR()                  bfin_read32(SIC_ISR)
+#define bfin_write_SIC_ISR(val)              bfin_write32(SIC_ISR,val)
+#define bfin_read_SIC_IWR()                  bfin_read32(SIC_IWR)
+#define bfin_write_SIC_IWR(val)              bfin_write32(SIC_IWR,val)
+
+/* Watchdog Timer (0xFFC0 1000-0xFFC0 13FF) */
+#define bfin_read_WDOG_CTL()                 bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val)             bfin_write16(WDOG_CTL,val)
+#define bfin_read_WDOG_CNT()                 bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val)             bfin_write32(WDOG_CNT,val)
+#define bfin_read_WDOG_STAT()                bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val)            bfin_write32(WDOG_STAT,val)
+
+/* Real Time Clock (0xFFC0 1400-0xFFC0 17FF) */
+#define bfin_read_RTC_STAT()                 bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val)             bfin_write32(RTC_STAT,val)
+#define bfin_read_RTC_ICTL()                 bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val)             bfin_write16(RTC_ICTL,val)
+#define bfin_read_RTC_ISTAT()                bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val)            bfin_write16(RTC_ISTAT,val)
+#define bfin_read_RTC_SWCNT()                bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val)            bfin_write16(RTC_SWCNT,val)
+#define bfin_read_RTC_ALARM()                bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val)            bfin_write32(RTC_ALARM,val)
+#define bfin_read_RTC_FAST()                 bfin_read16(RTC_FAST)
+#define bfin_write_RTC_FAST(val)             bfin_write16(RTC_FAST,val)
+#define bfin_read_RTC_PREN()                 bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val)             bfin_write16(RTC_PREN,val)
+
+/* General Purpose IO (0xFFC0 2400-0xFFC0 27FF) */
+#define bfin_read_FIO_DIR()                  bfin_read16(FIO_DIR)
+#define bfin_write_FIO_DIR(val)              bfin_write16(FIO_DIR,val)
+#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
+#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C,val)
+#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
+#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S,val)
+#define bfin_read_FIO_MASKA_C()              bfin_read16(FIO_MASKA_C)
+#define bfin_write_FIO_MASKA_C(val)          bfin_write16(FIO_MASKA_C,val)
+#define bfin_read_FIO_MASKA_S()              bfin_read16(FIO_MASKA_S)
+#define bfin_write_FIO_MASKA_S(val)          bfin_write16(FIO_MASKA_S,val)
+#define bfin_read_FIO_MASKB_C()              bfin_read16(FIO_MASKB_C)
+#define bfin_write_FIO_MASKB_C(val)          bfin_write16(FIO_MASKB_C,val)
+#define bfin_read_FIO_MASKB_S()              bfin_read16(FIO_MASKB_S)
+#define bfin_write_FIO_MASKB_S(val)          bfin_write16(FIO_MASKB_S,val)
+#define bfin_read_FIO_POLAR()                bfin_read16(FIO_POLAR)
+#define bfin_write_FIO_POLAR(val)            bfin_write16(FIO_POLAR,val)
+#define bfin_read_FIO_EDGE()                 bfin_read16(FIO_EDGE)
+#define bfin_write_FIO_EDGE(val)             bfin_write16(FIO_EDGE,val)
+#define bfin_read_FIO_BOTH()                 bfin_read16(FIO_BOTH)
+#define bfin_write_FIO_BOTH(val)             bfin_write16(FIO_BOTH,val)
+#define bfin_read_FIO_INEN()                 bfin_read16(FIO_INEN)
+#define bfin_write_FIO_INEN(val)             bfin_write16(FIO_INEN,val)
+#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
+#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D,val)
+#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
+#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T,val)
+#define bfin_read_FIO_MASKA_D()              bfin_read16(FIO_MASKA_D)
+#define bfin_write_FIO_MASKA_D(val)          bfin_write16(FIO_MASKA_D,val)
+#define bfin_read_FIO_MASKA_T()              bfin_read16(FIO_MASKA_T)
+#define bfin_write_FIO_MASKA_T(val)          bfin_write16(FIO_MASKA_T,val)
+#define bfin_read_FIO_MASKB_D()              bfin_read16(FIO_MASKB_D)
+#define bfin_write_FIO_MASKB_D(val)          bfin_write16(FIO_MASKB_D,val)
+#define bfin_read_FIO_MASKB_T()              bfin_read16(FIO_MASKB_T)
+#define bfin_write_FIO_MASKB_T(val)          bfin_write16(FIO_MASKB_T,val)
+
+/* DMA Traffic controls */
+#define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
+#define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
+#define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
+#define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
+#define bfin_read_DMA_TC_PER()               bfin_read16(DMA_TC_PER)
+#define bfin_write_DMA_TC_PER(val)           bfin_write16(DMA_TC_PER,val)
+#define bfin_read_DMA_TC_CNT()               bfin_read16(DMA_TC_CNT)
+#define bfin_write_DMA_TC_CNT(val)           bfin_write16(DMA_TC_CNT,val)
+
+/* DMA Controller */
+#define bfin_read_DMA0_CONFIG()              bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val)          bfin_write16(DMA0_CONFIG,val)
+#define bfin_read_DMA0_NEXT_DESC_PTR()       bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val)   bfin_write32(DMA0_NEXT_DESC_PTR,val)
+#define bfin_read_DMA0_START_ADDR()          bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val)      bfin_write32(DMA0_START_ADDR,val)
+#define bfin_read_DMA0_X_COUNT()             bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val)         bfin_write16(DMA0_X_COUNT,val)
+#define bfin_read_DMA0_Y_COUNT()             bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val)         bfin_write16(DMA0_Y_COUNT,val)
+#define bfin_read_DMA0_X_MODIFY()            bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val)        bfin_write16(DMA0_X_MODIFY,val)
+#define bfin_read_DMA0_Y_MODIFY()            bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val)        bfin_write16(DMA0_Y_MODIFY,val)
+#define bfin_read_DMA0_CURR_DESC_PTR()       bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val)   bfin_write32(DMA0_CURR_DESC_PTR,val)
+#define bfin_read_DMA0_CURR_ADDR()           bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val)       bfin_write32(DMA0_CURR_ADDR,val)
+#define bfin_read_DMA0_CURR_X_COUNT()        bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val)    bfin_write16(DMA0_CURR_X_COUNT,val)
+#define bfin_read_DMA0_CURR_Y_COUNT()        bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val)    bfin_write16(DMA0_CURR_Y_COUNT,val)
+#define bfin_read_DMA0_IRQ_STATUS()          bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val)      bfin_write16(DMA0_IRQ_STATUS,val)
+#define bfin_read_DMA0_PERIPHERAL_MAP()      bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val)  bfin_write16(DMA0_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA1_CONFIG()              bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val)          bfin_write16(DMA1_CONFIG,val)
+#define bfin_read_DMA1_NEXT_DESC_PTR()       bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val)   bfin_write32(DMA1_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_START_ADDR()          bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val)      bfin_write32(DMA1_START_ADDR,val)
+#define bfin_read_DMA1_X_COUNT()             bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val)         bfin_write16(DMA1_X_COUNT,val)
+#define bfin_read_DMA1_Y_COUNT()             bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val)         bfin_write16(DMA1_Y_COUNT,val)
+#define bfin_read_DMA1_X_MODIFY()            bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val)        bfin_write16(DMA1_X_MODIFY,val)
+#define bfin_read_DMA1_Y_MODIFY()            bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val)        bfin_write16(DMA1_Y_MODIFY,val)
+#define bfin_read_DMA1_CURR_DESC_PTR()       bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val)   bfin_write32(DMA1_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_CURR_ADDR()           bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val)       bfin_write32(DMA1_CURR_ADDR,val)
+#define bfin_read_DMA1_CURR_X_COUNT()        bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val)    bfin_write16(DMA1_CURR_X_COUNT,val)
+#define bfin_read_DMA1_CURR_Y_COUNT()        bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val)    bfin_write16(DMA1_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_IRQ_STATUS()          bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val)      bfin_write16(DMA1_IRQ_STATUS,val)
+#define bfin_read_DMA1_PERIPHERAL_MAP()      bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val)  bfin_write16(DMA1_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA2_CONFIG()              bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val)          bfin_write16(DMA2_CONFIG,val)
+#define bfin_read_DMA2_NEXT_DESC_PTR()       bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val)   bfin_write32(DMA2_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_START_ADDR()          bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val)      bfin_write32(DMA2_START_ADDR,val)
+#define bfin_read_DMA2_X_COUNT()             bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val)         bfin_write16(DMA2_X_COUNT,val)
+#define bfin_read_DMA2_Y_COUNT()             bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val)         bfin_write16(DMA2_Y_COUNT,val)
+#define bfin_read_DMA2_X_MODIFY()            bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val)        bfin_write16(DMA2_X_MODIFY,val)
+#define bfin_read_DMA2_Y_MODIFY()            bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val)        bfin_write16(DMA2_Y_MODIFY,val)
+#define bfin_read_DMA2_CURR_DESC_PTR()       bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val)   bfin_write32(DMA2_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_CURR_ADDR()           bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val)       bfin_write32(DMA2_CURR_ADDR,val)
+#define bfin_read_DMA2_CURR_X_COUNT()        bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val)    bfin_write16(DMA2_CURR_X_COUNT,val)
+#define bfin_read_DMA2_CURR_Y_COUNT()        bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val)    bfin_write16(DMA2_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_IRQ_STATUS()          bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val)      bfin_write16(DMA2_IRQ_STATUS,val)
+#define bfin_read_DMA2_PERIPHERAL_MAP()      bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val)  bfin_write16(DMA2_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA3_CONFIG()              bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val)          bfin_write16(DMA3_CONFIG,val)
+#define bfin_read_DMA3_NEXT_DESC_PTR()       bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val)   bfin_write32(DMA3_NEXT_DESC_PTR,val)
+#define bfin_read_DMA3_START_ADDR()          bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val)      bfin_write32(DMA3_START_ADDR,val)
+#define bfin_read_DMA3_X_COUNT()             bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val)         bfin_write16(DMA3_X_COUNT,val)
+#define bfin_read_DMA3_Y_COUNT()             bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val)         bfin_write16(DMA3_Y_COUNT,val)
+#define bfin_read_DMA3_X_MODIFY()            bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val)        bfin_write16(DMA3_X_MODIFY,val)
+#define bfin_read_DMA3_Y_MODIFY()            bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val)        bfin_write16(DMA3_Y_MODIFY,val)
+#define bfin_read_DMA3_CURR_DESC_PTR()       bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val)   bfin_write32(DMA3_CURR_DESC_PTR,val)
+#define bfin_read_DMA3_CURR_ADDR()           bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val)       bfin_write32(DMA3_CURR_ADDR,val)
+#define bfin_read_DMA3_CURR_X_COUNT()        bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val)    bfin_write16(DMA3_CURR_X_COUNT,val)
+#define bfin_read_DMA3_CURR_Y_COUNT()        bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val)    bfin_write16(DMA3_CURR_Y_COUNT,val)
+#define bfin_read_DMA3_IRQ_STATUS()          bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val)      bfin_write16(DMA3_IRQ_STATUS,val)
+#define bfin_read_DMA3_PERIPHERAL_MAP()      bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val)  bfin_write16(DMA3_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA4_CONFIG()              bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val)          bfin_write16(DMA4_CONFIG,val)
+#define bfin_read_DMA4_NEXT_DESC_PTR()       bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val)   bfin_write32(DMA4_NEXT_DESC_PTR,val)
+#define bfin_read_DMA4_START_ADDR()          bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val)      bfin_write32(DMA4_START_ADDR,val)
+#define bfin_read_DMA4_X_COUNT()             bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val)         bfin_write16(DMA4_X_COUNT,val)
+#define bfin_read_DMA4_Y_COUNT()             bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val)         bfin_write16(DMA4_Y_COUNT,val)
+#define bfin_read_DMA4_X_MODIFY()            bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val)        bfin_write16(DMA4_X_MODIFY,val)
+#define bfin_read_DMA4_Y_MODIFY()            bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val)        bfin_write16(DMA4_Y_MODIFY,val)
+#define bfin_read_DMA4_CURR_DESC_PTR()       bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val)   bfin_write32(DMA4_CURR_DESC_PTR,val)
+#define bfin_read_DMA4_CURR_ADDR()           bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val)       bfin_write32(DMA4_CURR_ADDR,val)
+#define bfin_read_DMA4_CURR_X_COUNT()        bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val)    bfin_write16(DMA4_CURR_X_COUNT,val)
+#define bfin_read_DMA4_CURR_Y_COUNT()        bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val)    bfin_write16(DMA4_CURR_Y_COUNT,val)
+#define bfin_read_DMA4_IRQ_STATUS()          bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val)      bfin_write16(DMA4_IRQ_STATUS,val)
+#define bfin_read_DMA4_PERIPHERAL_MAP()      bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val)  bfin_write16(DMA4_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA5_CONFIG()              bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val)          bfin_write16(DMA5_CONFIG,val)
+#define bfin_read_DMA5_NEXT_DESC_PTR()       bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val)   bfin_write32(DMA5_NEXT_DESC_PTR,val)
+#define bfin_read_DMA5_START_ADDR()          bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val)      bfin_write32(DMA5_START_ADDR,val)
+#define bfin_read_DMA5_X_COUNT()             bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val)         bfin_write16(DMA5_X_COUNT,val)
+#define bfin_read_DMA5_Y_COUNT()             bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val)         bfin_write16(DMA5_Y_COUNT,val)
+#define bfin_read_DMA5_X_MODIFY()            bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val)        bfin_write16(DMA5_X_MODIFY,val)
+#define bfin_read_DMA5_Y_MODIFY()            bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val)        bfin_write16(DMA5_Y_MODIFY,val)
+#define bfin_read_DMA5_CURR_DESC_PTR()       bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val)   bfin_write32(DMA5_CURR_DESC_PTR,val)
+#define bfin_read_DMA5_CURR_ADDR()           bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val)       bfin_write32(DMA5_CURR_ADDR,val)
+#define bfin_read_DMA5_CURR_X_COUNT()        bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val)    bfin_write16(DMA5_CURR_X_COUNT,val)
+#define bfin_read_DMA5_CURR_Y_COUNT()        bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val)    bfin_write16(DMA5_CURR_Y_COUNT,val)
+#define bfin_read_DMA5_IRQ_STATUS()          bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val)      bfin_write16(DMA5_IRQ_STATUS,val)
+#define bfin_read_DMA5_PERIPHERAL_MAP()      bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val)  bfin_write16(DMA5_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA6_CONFIG()              bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val)          bfin_write16(DMA6_CONFIG,val)
+#define bfin_read_DMA6_NEXT_DESC_PTR()       bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val)   bfin_write32(DMA6_NEXT_DESC_PTR,val)
+#define bfin_read_DMA6_START_ADDR()          bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val)      bfin_write32(DMA6_START_ADDR,val)
+#define bfin_read_DMA6_X_COUNT()             bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val)         bfin_write16(DMA6_X_COUNT,val)
+#define bfin_read_DMA6_Y_COUNT()             bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val)         bfin_write16(DMA6_Y_COUNT,val)
+#define bfin_read_DMA6_X_MODIFY()            bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val)        bfin_write16(DMA6_X_MODIFY,val)
+#define bfin_read_DMA6_Y_MODIFY()            bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val)        bfin_write16(DMA6_Y_MODIFY,val)
+#define bfin_read_DMA6_CURR_DESC_PTR()       bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val)   bfin_write32(DMA6_CURR_DESC_PTR,val)
+#define bfin_read_DMA6_CURR_ADDR()           bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val)       bfin_write32(DMA6_CURR_ADDR,val)
+#define bfin_read_DMA6_CURR_X_COUNT()        bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val)    bfin_write16(DMA6_CURR_X_COUNT,val)
+#define bfin_read_DMA6_CURR_Y_COUNT()        bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val)    bfin_write16(DMA6_CURR_Y_COUNT,val)
+#define bfin_read_DMA6_IRQ_STATUS()          bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val)      bfin_write16(DMA6_IRQ_STATUS,val)
+#define bfin_read_DMA6_PERIPHERAL_MAP()      bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val)  bfin_write16(DMA6_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA7_CONFIG()              bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val)          bfin_write16(DMA7_CONFIG,val)
+#define bfin_read_DMA7_NEXT_DESC_PTR()       bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val)   bfin_write32(DMA7_NEXT_DESC_PTR,val)
+#define bfin_read_DMA7_START_ADDR()          bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val)      bfin_write32(DMA7_START_ADDR,val)
+#define bfin_read_DMA7_X_COUNT()             bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val)         bfin_write16(DMA7_X_COUNT,val)
+#define bfin_read_DMA7_Y_COUNT()             bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val)         bfin_write16(DMA7_Y_COUNT,val)
+#define bfin_read_DMA7_X_MODIFY()            bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val)        bfin_write16(DMA7_X_MODIFY,val)
+#define bfin_read_DMA7_Y_MODIFY()            bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val)        bfin_write16(DMA7_Y_MODIFY,val)
+#define bfin_read_DMA7_CURR_DESC_PTR()       bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val)   bfin_write32(DMA7_CURR_DESC_PTR,val)
+#define bfin_read_DMA7_CURR_ADDR()           bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val)       bfin_write32(DMA7_CURR_ADDR,val)
+#define bfin_read_DMA7_CURR_X_COUNT()        bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val)    bfin_write16(DMA7_CURR_X_COUNT,val)
+#define bfin_read_DMA7_CURR_Y_COUNT()        bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val)    bfin_write16(DMA7_CURR_Y_COUNT,val)
+#define bfin_read_DMA7_IRQ_STATUS()          bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val)      bfin_write16(DMA7_IRQ_STATUS,val)
+#define bfin_read_DMA7_PERIPHERAL_MAP()      bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val)  bfin_write16(DMA7_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_D1_CONFIG()           bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)       bfin_write16(MDMA_D1_CONFIG,val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR()    bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA_D1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D1_START_ADDR()       bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)   bfin_write32(MDMA_D1_START_ADDR,val)
+#define bfin_read_MDMA_D1_X_COUNT()          bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)      bfin_write16(MDMA_D1_X_COUNT,val)
+#define bfin_read_MDMA_D1_Y_COUNT()          bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)      bfin_write16(MDMA_D1_Y_COUNT,val)
+#define bfin_read_MDMA_D1_X_MODIFY()         bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)     bfin_write16(MDMA_D1_X_MODIFY,val)
+#define bfin_read_MDMA_D1_Y_MODIFY()         bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)     bfin_write16(MDMA_D1_Y_MODIFY,val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR()    bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D1_CURR_ADDR()        bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)    bfin_write32(MDMA_D1_CURR_ADDR,val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()     bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val) bfin_write16(MDMA_D1_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()     bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val) bfin_write16(MDMA_D1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()       bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)   bfin_write16(MDMA_D1_IRQ_STATUS,val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()   bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA_D1_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_S1_CONFIG()           bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)       bfin_write16(MDMA_S1_CONFIG,val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR()    bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA_S1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S1_START_ADDR()       bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)   bfin_write32(MDMA_S1_START_ADDR,val)
+#define bfin_read_MDMA_S1_X_COUNT()          bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)      bfin_write16(MDMA_S1_X_COUNT,val)
+#define bfin_read_MDMA_S1_Y_COUNT()          bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)      bfin_write16(MDMA_S1_Y_COUNT,val)
+#define bfin_read_MDMA_S1_X_MODIFY()         bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)     bfin_write16(MDMA_S1_X_MODIFY,val)
+#define bfin_read_MDMA_S1_Y_MODIFY()         bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)     bfin_write16(MDMA_S1_Y_MODIFY,val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR()    bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S1_CURR_ADDR()        bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)    bfin_write32(MDMA_S1_CURR_ADDR,val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()     bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val) bfin_write16(MDMA_S1_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()     bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val) bfin_write16(MDMA_S1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()       bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)   bfin_write16(MDMA_S1_IRQ_STATUS,val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()   bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA_S1_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_D0_CONFIG()           bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)       bfin_write16(MDMA_D0_CONFIG,val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR()    bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D0_START_ADDR()       bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)   bfin_write32(MDMA_D0_START_ADDR,val)
+#define bfin_read_MDMA_D0_X_COUNT()          bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)      bfin_write16(MDMA_D0_X_COUNT,val)
+#define bfin_read_MDMA_D0_Y_COUNT()          bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)      bfin_write16(MDMA_D0_Y_COUNT,val)
+#define bfin_read_MDMA_D0_X_MODIFY()         bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)     bfin_write16(MDMA_D0_X_MODIFY,val)
+#define bfin_read_MDMA_D0_Y_MODIFY()         bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)     bfin_write16(MDMA_D0_Y_MODIFY,val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR()    bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_write32(MDMA_D0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D0_CURR_ADDR()        bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)    bfin_write32(MDMA_D0_CURR_ADDR,val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()     bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val) bfin_write16(MDMA_D0_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()     bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val) bfin_write16(MDMA_D0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()       bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)   bfin_write16(MDMA_D0_IRQ_STATUS,val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()   bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA_D0_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_S0_CONFIG()           bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)       bfin_write16(MDMA_S0_CONFIG,val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR()    bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA_S0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S0_START_ADDR()       bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)   bfin_write32(MDMA_S0_START_ADDR,val)
+#define bfin_read_MDMA_S0_X_COUNT()          bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)      bfin_write16(MDMA_S0_X_COUNT,val)
+#define bfin_read_MDMA_S0_Y_COUNT()          bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)      bfin_write16(MDMA_S0_Y_COUNT,val)
+#define bfin_read_MDMA_S0_X_MODIFY()         bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)     bfin_write16(MDMA_S0_X_MODIFY,val)
+#define bfin_read_MDMA_S0_Y_MODIFY()         bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)     bfin_write16(MDMA_S0_Y_MODIFY,val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR()    bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_write32(MDMA_S0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S0_CURR_ADDR()        bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)    bfin_write32(MDMA_S0_CURR_ADDR,val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()     bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val) bfin_write16(MDMA_S0_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()     bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val) bfin_write16(MDMA_S0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()       bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)   bfin_write16(MDMA_S0_IRQ_STATUS,val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()   bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA_S0_PERIPHERAL_MAP,val)
+
+/* Aysnchronous Memory Controller - External Bus Interface Unit (0xFFC0 3C00-0xFFC0 3FFF) */
+#define bfin_read_EBIU_AMGCTL()              bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)          bfin_write16(EBIU_AMGCTL,val)
+#define bfin_read_EBIU_AMBCTL0()             bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)         bfin_write32(EBIU_AMBCTL0,val)
+#define bfin_read_EBIU_AMBCTL1()             bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)         bfin_write32(EBIU_AMBCTL1,val)
+
+/* SDRAM Controller External Bus Interface Unit (0xFFC0 4C00-0xFFC0 4FFF) */
+#define bfin_read_EBIU_SDGCTL()              bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val)          bfin_write32(EBIU_SDGCTL,val)
+#define bfin_read_EBIU_SDRRC()               bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val)           bfin_write16(EBIU_SDRRC,val)
+#define bfin_read_EBIU_SDSTAT()              bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val)          bfin_write16(EBIU_SDSTAT,val)
+#define bfin_read_EBIU_SDBCTL()              bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val)          bfin_write16(EBIU_SDBCTL,val)
+
+/* UART Controller */
+#define bfin_read_UART_THR()                 bfin_read16(UART_THR)
+#define bfin_write_UART_THR(val)             bfin_write16(UART_THR,val)
+#define bfin_read_UART_RBR()                 bfin_read16(UART_RBR)
+#define bfin_write_UART_RBR(val)             bfin_write16(UART_RBR,val)
+#define bfin_read_UART_DLL()                 bfin_read16(UART_DLL)
+#define bfin_write_UART_DLL(val)             bfin_write16(UART_DLL,val)
+#define bfin_read_UART_IER()                 bfin_read16(UART_IER)
+#define bfin_write_UART_IER(val)             bfin_write16(UART_IER,val)
+#define bfin_read_UART_DLH()                 bfin_read16(UART_DLH)
+#define bfin_write_UART_DLH(val)             bfin_write16(UART_DLH,val)
+#define bfin_read_UART_IIR()                 bfin_read16(UART_IIR)
+#define bfin_write_UART_IIR(val)             bfin_write16(UART_IIR,val)
+#define bfin_read_UART_LCR()                 bfin_read16(UART_LCR)
+#define bfin_write_UART_LCR(val)             bfin_write16(UART_LCR,val)
+#define bfin_read_UART_MCR()                 bfin_read16(UART_MCR)
+#define bfin_write_UART_MCR(val)             bfin_write16(UART_MCR,val)
+#define bfin_read_UART_LSR()                 bfin_read16(UART_LSR)
+#define bfin_write_UART_LSR(val)             bfin_write16(UART_LSR,val)
+/*
+#define UART_MSR
+*/
+#define bfin_read_UART_SCR()                 bfin_read16(UART_SCR)
+#define bfin_write_UART_SCR(val)             bfin_write16(UART_SCR,val)
+#define bfin_read_UART_GCTL()                bfin_read16(UART_GCTL)
+#define bfin_write_UART_GCTL(val)            bfin_write16(UART_GCTL,val)
+
+/* SPI Controller */
+#define bfin_read_SPI_CTL()                  bfin_read16(SPI_CTL)
+#define bfin_write_SPI_CTL(val)              bfin_write16(SPI_CTL,val)
+#define bfin_read_SPI_FLG()                  bfin_read16(SPI_FLG)
+#define bfin_write_SPI_FLG(val)              bfin_write16(SPI_FLG,val)
+#define bfin_read_SPI_STAT()                 bfin_read16(SPI_STAT)
+#define bfin_write_SPI_STAT(val)             bfin_write16(SPI_STAT,val)
+#define bfin_read_SPI_TDBR()                 bfin_read16(SPI_TDBR)
+#define bfin_write_SPI_TDBR(val)             bfin_write16(SPI_TDBR,val)
+#define bfin_read_SPI_RDBR()                 bfin_read16(SPI_RDBR)
+#define bfin_write_SPI_RDBR(val)             bfin_write16(SPI_RDBR,val)
+#define bfin_read_SPI_BAUD()                 bfin_read16(SPI_BAUD)
+#define bfin_write_SPI_BAUD(val)             bfin_write16(SPI_BAUD,val)
+#define bfin_read_SPI_SHADOW()               bfin_read16(SPI_SHADOW)
+#define bfin_write_SPI_SHADOW(val)           bfin_write16(SPI_SHADOW,val)
+
+/* TIMER 0, 1, 2 Registers */
+#define bfin_read_TIMER0_CONFIG()            bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)        bfin_write16(TIMER0_CONFIG,val)
+#define bfin_read_TIMER0_COUNTER()           bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)       bfin_write32(TIMER0_COUNTER,val)
+#define bfin_read_TIMER0_PERIOD()            bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)        bfin_write32(TIMER0_PERIOD,val)
+#define bfin_read_TIMER0_WIDTH()             bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)         bfin_write32(TIMER0_WIDTH,val)
+
+#define bfin_read_TIMER1_CONFIG()            bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)        bfin_write16(TIMER1_CONFIG,val)
+#define bfin_read_TIMER1_COUNTER()           bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)       bfin_write32(TIMER1_COUNTER,val)
+#define bfin_read_TIMER1_PERIOD()            bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)        bfin_write32(TIMER1_PERIOD,val)
+#define bfin_read_TIMER1_WIDTH()             bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)         bfin_write32(TIMER1_WIDTH,val)
+
+#define bfin_read_TIMER2_CONFIG()            bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)        bfin_write16(TIMER2_CONFIG,val)
+#define bfin_read_TIMER2_COUNTER()           bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)       bfin_write32(TIMER2_COUNTER,val)
+#define bfin_read_TIMER2_PERIOD()            bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)        bfin_write32(TIMER2_PERIOD,val)
+#define bfin_read_TIMER2_WIDTH()             bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)         bfin_write32(TIMER2_WIDTH,val)
+
+#define bfin_read_TIMER_ENABLE()             bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val)         bfin_write16(TIMER_ENABLE,val)
+#define bfin_read_TIMER_DISABLE()            bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val)        bfin_write16(TIMER_DISABLE,val)
+#define bfin_read_TIMER_STATUS()             bfin_read16(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val)         bfin_write16(TIMER_STATUS,val)
+
+/* SPORT0 Controller */
+#define bfin_read_SPORT0_TCR1()              bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)          bfin_write16(SPORT0_TCR1,val)
+#define bfin_read_SPORT0_TCR2()              bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)          bfin_write16(SPORT0_TCR2,val)
+#define bfin_read_SPORT0_TCLKDIV()           bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)       bfin_write16(SPORT0_TCLKDIV,val)
+#define bfin_read_SPORT0_TFSDIV()            bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)        bfin_write16(SPORT0_TFSDIV,val)
+#define bfin_read_SPORT0_TX()                bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)            bfin_write32(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX()                bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)            bfin_write32(SPORT0_RX,val)
+#define bfin_read_SPORT0_TX32()              bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)          bfin_write32(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX32()              bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)          bfin_write32(SPORT0_RX,val)
+#define bfin_read_SPORT0_TX16()              bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)          bfin_write16(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX16()              bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)          bfin_write16(SPORT0_RX,val)
+#define bfin_read_SPORT0_RCR1()              bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)          bfin_write16(SPORT0_RCR1,val)
+#define bfin_read_SPORT0_RCR2()              bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)          bfin_write16(SPORT0_RCR2,val)
+#define bfin_read_SPORT0_RCLKDIV()           bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)       bfin_write16(SPORT0_RCLKDIV,val)
+#define bfin_read_SPORT0_RFSDIV()            bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)        bfin_write16(SPORT0_RFSDIV,val)
+#define bfin_read_SPORT0_STAT()              bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)          bfin_write16(SPORT0_STAT,val)
+#define bfin_read_SPORT0_CHNL()              bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)          bfin_write16(SPORT0_CHNL,val)
+#define bfin_read_SPORT0_MCMC1()             bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)         bfin_write16(SPORT0_MCMC1,val)
+#define bfin_read_SPORT0_MCMC2()             bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)         bfin_write16(SPORT0_MCMC2,val)
+#define bfin_read_SPORT0_MTCS0()             bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)         bfin_write32(SPORT0_MTCS0,val)
+#define bfin_read_SPORT0_MTCS1()             bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)         bfin_write32(SPORT0_MTCS1,val)
+#define bfin_read_SPORT0_MTCS2()             bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)         bfin_write32(SPORT0_MTCS2,val)
+#define bfin_read_SPORT0_MTCS3()             bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)         bfin_write32(SPORT0_MTCS3,val)
+#define bfin_read_SPORT0_MRCS0()             bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)         bfin_write32(SPORT0_MRCS0,val)
+#define bfin_read_SPORT0_MRCS1()             bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)         bfin_write32(SPORT0_MRCS1,val)
+#define bfin_read_SPORT0_MRCS2()             bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)         bfin_write32(SPORT0_MRCS2,val)
+#define bfin_read_SPORT0_MRCS3()             bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)         bfin_write32(SPORT0_MRCS3,val)
+
+/* SPORT1 Controller */
+#define bfin_read_SPORT1_TCR1()              bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)          bfin_write16(SPORT1_TCR1,val)
+#define bfin_read_SPORT1_TCR2()              bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)          bfin_write16(SPORT1_TCR2,val)
+#define bfin_read_SPORT1_TCLKDIV()           bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)       bfin_write16(SPORT1_TCLKDIV,val)
+#define bfin_read_SPORT1_TFSDIV()            bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)        bfin_write16(SPORT1_TFSDIV,val)
+#define bfin_read_SPORT1_TX()                bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)            bfin_write32(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX()                bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)            bfin_write32(SPORT1_RX,val)
+#define bfin_read_SPORT1_TX32()              bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)          bfin_write32(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX32()              bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)          bfin_write32(SPORT1_RX,val)
+#define bfin_read_SPORT1_TX16()              bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)          bfin_write16(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX16()              bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)          bfin_write16(SPORT1_RX,val)
+#define bfin_read_SPORT1_RCR1()              bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)          bfin_write16(SPORT1_RCR1,val)
+#define bfin_read_SPORT1_RCR2()              bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)          bfin_write16(SPORT1_RCR2,val)
+#define bfin_read_SPORT1_RCLKDIV()           bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)       bfin_write16(SPORT1_RCLKDIV,val)
+#define bfin_read_SPORT1_RFSDIV()            bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)        bfin_write16(SPORT1_RFSDIV,val)
+#define bfin_read_SPORT1_STAT()              bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)          bfin_write16(SPORT1_STAT,val)
+#define bfin_read_SPORT1_CHNL()              bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)          bfin_write16(SPORT1_CHNL,val)
+#define bfin_read_SPORT1_MCMC1()             bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)         bfin_write16(SPORT1_MCMC1,val)
+#define bfin_read_SPORT1_MCMC2()             bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)         bfin_write16(SPORT1_MCMC2,val)
+#define bfin_read_SPORT1_MTCS0()             bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)         bfin_write32(SPORT1_MTCS0,val)
+#define bfin_read_SPORT1_MTCS1()             bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)         bfin_write32(SPORT1_MTCS1,val)
+#define bfin_read_SPORT1_MTCS2()             bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)         bfin_write32(SPORT1_MTCS2,val)
+#define bfin_read_SPORT1_MTCS3()             bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)         bfin_write32(SPORT1_MTCS3,val)
+#define bfin_read_SPORT1_MRCS0()             bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)         bfin_write32(SPORT1_MRCS0,val)
+#define bfin_read_SPORT1_MRCS1()             bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)         bfin_write32(SPORT1_MRCS1,val)
+#define bfin_read_SPORT1_MRCS2()             bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)         bfin_write32(SPORT1_MRCS2,val)
+#define bfin_read_SPORT1_MRCS3()             bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)         bfin_write32(SPORT1_MRCS3,val)
+
+/* Parallel Peripheral Interface (PPI) */
+#define bfin_read_PPI_CONTROL()              bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val)          bfin_write16(PPI_CONTROL,val)
+#define bfin_read_PPI_STATUS()               bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val)           bfin_write16(PPI_STATUS,val)
+#define bfin_clear_PPI_STATUS()              bfin_read_PPI_STATUS()
+#define bfin_read_PPI_DELAY()                bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val)            bfin_write16(PPI_DELAY,val)
+#define bfin_read_PPI_COUNT()                bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val)            bfin_write16(PPI_COUNT,val)
+#define bfin_read_PPI_FRAME()                bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val)            bfin_write16(PPI_FRAME,val)
+
+#endif                         /* _CDEF_BF532_H */
diff --git a/include/asm-blackfin/mach-bf533/defBF532.h b/include/asm-blackfin/mach-bf533/defBF532.h
new file mode 100644 (file)
index 0000000..b240a08
--- /dev/null
@@ -0,0 +1,1175 @@
+/************************************************************************
+ *
+ * This file is subject to the terms and conditions of the GNU Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Non-GPL License also available as part of VisualDSP++
+ * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html
+ *
+ * (c) Copyright 2001-2005 Analog Devices, Inc. All rights reserved
+ *
+ * This file under source code control, please send bugs or changes to:
+ * dsptools.support@analog.com
+ *
+ ************************************************************************/
+/*
+ * File:         include/asm-blackfin/mach-bf533/defBF532.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* SYSTEM & MM REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF532 */
+
+#ifndef _DEF_BF532_H
+#define _DEF_BF532_H
+/*
+#if !defined(__ADSPLPBLACKFIN__)
+#warning defBF532.h should only be included for 532 compatible chips
+#endif
+*/
+/* include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/*********************************************************************************** */
+/* System MMR Register Map */
+/*********************************************************************************** */
+/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+
+#define PLL_CTL                0xFFC00000      /* PLL Control register (16-bit) */
+#define PLL_DIV                         0xFFC00004     /* PLL Divide Register (16-bit) */
+#define VR_CTL                  0xFFC00008     /* Voltage Regulator Control Register (16-bit) */
+#define PLL_STAT               0xFFC0000C      /* PLL Status register (16-bit) */
+#define PLL_LOCKCNT            0xFFC00010      /* PLL Lock Count register (16-bit) */
+#define CHIPID                 0xFFC00014       /* Chip ID Register */
+#define SWRST                  0xFFC00100      /* Software Reset Register (16-bit) */
+#define SYSCR                  0xFFC00104      /* System Configuration registe */
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
+#define SIC_RVECT                      0xFFC00108      /* Interrupt Reset Vector Address Register */
+#define SIC_IMASK                      0xFFC0010C      /* Interrupt Mask Register */
+#define SIC_IAR0                               0xFFC00110      /* Interrupt Assignment Register 0 */
+#define SIC_IAR1                               0xFFC00114      /* Interrupt Assignment Register 1 */
+#define SIC_IAR2                       0xFFC00118      /* Interrupt Assignment Register 2 */
+#define SIC_ISR                                0xFFC00120      /* Interrupt Status Register */
+#define SIC_IWR                                0xFFC00124      /* Interrupt Wakeup Register */
+
+/* Watchdog Timer (0xFFC00200 - 0xFFC002FF) */
+#define WDOG_CTL                       0xFFC00200      /* Watchdog Control Register */
+#define WDOG_CNT                       0xFFC00204      /* Watchdog Count Register */
+#define WDOG_STAT                      0xFFC00208      /* Watchdog Status Register */
+
+/* Real Time Clock (0xFFC00300 - 0xFFC003FF) */
+#define RTC_STAT                       0xFFC00300      /* RTC Status Register */
+#define RTC_ICTL                       0xFFC00304      /* RTC Interrupt Control Register */
+#define RTC_ISTAT                      0xFFC00308      /* RTC Interrupt Status Register */
+#define RTC_SWCNT                      0xFFC0030C      /* RTC Stopwatch Count Register */
+#define RTC_ALARM                      0xFFC00310      /* RTC Alarm Time Register */
+#define RTC_FAST                       0xFFC00314      /* RTC Prescaler Enable Register */
+#define RTC_PREN                       0xFFC00314      /* RTC Prescaler Enable Register (alternate macro) */
+
+/* UART Controller (0xFFC00400 - 0xFFC004FF) */
+#define UART_THR                        0xFFC00400     /* Transmit Holding register */
+#define UART_RBR                        0xFFC00400     /* Receive Buffer register */
+#define UART_DLL                        0xFFC00400     /* Divisor Latch (Low-Byte) */
+#define UART_IER                        0xFFC00404     /* Interrupt Enable Register */
+#define UART_DLH                        0xFFC00404     /* Divisor Latch (High-Byte) */
+#define UART_IIR                        0xFFC00408     /* Interrupt Identification Register */
+#define UART_LCR                        0xFFC0040C     /* Line Control Register */
+#define UART_MCR                        0xFFC00410     /* Modem Control Register */
+#define UART_LSR                        0xFFC00414     /* Line Status Register */
+#if 0
+#define UART_MSR                        0xFFC00418   /* Modem Status Register (UNUSED in ADSP-BF532) */
+#endif
+#define UART_SCR                        0xFFC0041C     /* SCR Scratch Register */
+#define UART_GCTL                               0xFFC00424     /* Global Control Register */
+
+/* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+#define SPI_CTL                        0xFFC00500      /* SPI Control Register */
+#define SPI_FLG                        0xFFC00504      /* SPI Flag register */
+#define SPI_STAT                       0xFFC00508      /* SPI Status register */
+#define SPI_TDBR                       0xFFC0050C      /* SPI Transmit Data Buffer Register */
+#define SPI_RDBR                       0xFFC00510      /* SPI Receive Data Buffer Register */
+#define SPI_BAUD                       0xFFC00514      /* SPI Baud rate Register */
+#define SPI_SHADOW                     0xFFC00518      /* SPI_RDBR Shadow Register */
+
+/* TIMER 0, 1, 2 Registers (0xFFC00600 - 0xFFC006FF) */
+
+#define TIMER0_CONFIG                          0xFFC00600      /* Timer 0 Configuration Register */
+#define TIMER0_COUNTER                 0xFFC00604      /* Timer 0 Counter Register */
+#define TIMER0_PERIOD                  0xFFC00608      /* Timer 0 Period Register */
+#define TIMER0_WIDTH                   0xFFC0060C      /* Timer 0 Width Register */
+
+#define TIMER1_CONFIG                          0xFFC00610      /*  Timer 1 Configuration Register   */
+#define TIMER1_COUNTER                         0xFFC00614      /*  Timer 1 Counter Register         */
+#define TIMER1_PERIOD                          0xFFC00618      /*  Timer 1 Period Register          */
+#define TIMER1_WIDTH                           0xFFC0061C      /*  Timer 1 Width Register           */
+
+#define TIMER2_CONFIG                          0xFFC00620      /* Timer 2 Configuration Register   */
+#define TIMER2_COUNTER                         0xFFC00624      /* Timer 2 Counter Register         */
+#define TIMER2_PERIOD                          0xFFC00628      /* Timer 2 Period Register          */
+#define TIMER2_WIDTH                           0xFFC0062C      /* Timer 2 Width Register           */
+
+#define TIMER_ENABLE                   0xFFC00640      /* Timer Enable Register */
+#define TIMER_DISABLE                  0xFFC00644      /* Timer Disable Register */
+#define TIMER_STATUS                   0xFFC00648      /* Timer Status Register */
+
+/* General Purpose IO (0xFFC00700 - 0xFFC007FF) */
+
+#define FIO_FLAG_D                     0xFFC00700      /* Flag Mask to directly specify state of pins */
+#define FIO_FLAG_C                             0xFFC00704      /* Peripheral Interrupt Flag Register (clear) */
+#define FIO_FLAG_S                             0xFFC00708      /* Peripheral Interrupt Flag Register (set) */
+#define FIO_FLAG_T                     0xFFC0070C      /* Flag Mask to directly toggle state of pins */
+#define FIO_MASKA_D                            0xFFC00710      /* Flag Mask Interrupt A Register (set directly) */
+#define FIO_MASKA_C                            0xFFC00714      /* Flag Mask Interrupt A Register (clear) */
+#define FIO_MASKA_S                            0xFFC00718      /* Flag Mask Interrupt A Register (set) */
+#define FIO_MASKA_T                            0xFFC0071C      /* Flag Mask Interrupt A Register (toggle) */
+#define FIO_MASKB_D                            0xFFC00720      /* Flag Mask Interrupt B Register (set directly) */
+#define FIO_MASKB_C                            0xFFC00724      /* Flag Mask Interrupt B Register (clear) */
+#define FIO_MASKB_S                            0xFFC00728      /* Flag Mask Interrupt B Register (set) */
+#define FIO_MASKB_T                            0xFFC0072C      /* Flag Mask Interrupt B Register (toggle) */
+#define FIO_DIR                                0xFFC00730      /* Peripheral Flag Direction Register */
+#define FIO_POLAR                              0xFFC00734      /* Flag Source Polarity Register */
+#define FIO_EDGE                               0xFFC00738      /* Flag Source Sensitivity Register */
+#define FIO_BOTH                               0xFFC0073C      /* Flag Set on BOTH Edges Register */
+#define FIO_INEN                                       0xFFC00740      /* Flag Input Enable Register  */
+
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define SPORT0_TCR1                    0xFFC00800      /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_TCR2                    0xFFC00804      /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_TCLKDIV                 0xFFC00808      /* SPORT0 Transmit Clock Divider */
+#define SPORT0_TFSDIV                          0xFFC0080C      /* SPORT0 Transmit Frame Sync Divider */
+#define SPORT0_TX                      0xFFC00810      /* SPORT0 TX Data Register */
+#define SPORT0_RX                      0xFFC00818      /* SPORT0 RX Data Register */
+#define SPORT0_RCR1                    0xFFC00820      /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_RCR2                    0xFFC00824      /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_RCLKDIV                 0xFFC00828      /* SPORT0 Receive Clock Divider */
+#define SPORT0_RFSDIV                          0xFFC0082C      /* SPORT0 Receive Frame Sync Divider */
+#define SPORT0_STAT                            0xFFC00830      /* SPORT0 Status Register */
+#define SPORT0_CHNL                            0xFFC00834      /* SPORT0 Current Channel Register */
+#define SPORT0_MCMC1                           0xFFC00838      /* SPORT0 Multi-Channel Configuration Register 1 */
+#define SPORT0_MCMC2                           0xFFC0083C      /* SPORT0 Multi-Channel Configuration Register 2 */
+#define SPORT0_MTCS0                           0xFFC00840      /* SPORT0 Multi-Channel Transmit Select Register 0 */
+#define SPORT0_MTCS1                           0xFFC00844      /* SPORT0 Multi-Channel Transmit Select Register 1 */
+#define SPORT0_MTCS2                           0xFFC00848      /* SPORT0 Multi-Channel Transmit Select Register 2 */
+#define SPORT0_MTCS3                           0xFFC0084C      /* SPORT0 Multi-Channel Transmit Select Register 3 */
+#define SPORT0_MRCS0                           0xFFC00850      /* SPORT0 Multi-Channel Receive Select Register 0 */
+#define SPORT0_MRCS1                           0xFFC00854      /* SPORT0 Multi-Channel Receive Select Register 1 */
+#define SPORT0_MRCS2                           0xFFC00858      /* SPORT0 Multi-Channel Receive Select Register 2 */
+#define SPORT0_MRCS3                           0xFFC0085C      /* SPORT0 Multi-Channel Receive Select Register 3 */
+
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define SPORT1_TCR1                    0xFFC00900      /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_TCR2                    0xFFC00904      /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_TCLKDIV                 0xFFC00908      /* SPORT1 Transmit Clock Divider */
+#define SPORT1_TFSDIV                          0xFFC0090C      /* SPORT1 Transmit Frame Sync Divider */
+#define SPORT1_TX                      0xFFC00910      /* SPORT1 TX Data Register */
+#define SPORT1_RX                      0xFFC00918      /* SPORT1 RX Data Register */
+#define SPORT1_RCR1                    0xFFC00920      /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_RCR2                    0xFFC00924      /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_RCLKDIV                 0xFFC00928      /* SPORT1 Receive Clock Divider */
+#define SPORT1_RFSDIV                          0xFFC0092C      /* SPORT1 Receive Frame Sync Divider */
+#define SPORT1_STAT                            0xFFC00930      /* SPORT1 Status Register */
+#define SPORT1_CHNL                            0xFFC00934      /* SPORT1 Current Channel Register */
+#define SPORT1_MCMC1                           0xFFC00938      /* SPORT1 Multi-Channel Configuration Register 1 */
+#define SPORT1_MCMC2                           0xFFC0093C      /* SPORT1 Multi-Channel Configuration Register 2 */
+#define SPORT1_MTCS0                           0xFFC00940      /* SPORT1 Multi-Channel Transmit Select Register 0 */
+#define SPORT1_MTCS1                           0xFFC00944      /* SPORT1 Multi-Channel Transmit Select Register 1 */
+#define SPORT1_MTCS2                           0xFFC00948      /* SPORT1 Multi-Channel Transmit Select Register 2 */
+#define SPORT1_MTCS3                           0xFFC0094C      /* SPORT1 Multi-Channel Transmit Select Register 3 */
+#define SPORT1_MRCS0                           0xFFC00950      /* SPORT1 Multi-Channel Receive Select Register 0 */
+#define SPORT1_MRCS1                           0xFFC00954      /* SPORT1 Multi-Channel Receive Select Register 1 */
+#define SPORT1_MRCS2                           0xFFC00958      /* SPORT1 Multi-Channel Receive Select Register 2 */
+#define SPORT1_MRCS3                           0xFFC0095C      /* SPORT1 Multi-Channel Receive Select Register 3 */
+
+/* Asynchronous Memory Controller - External Bus Interface Unit  */
+#define EBIU_AMGCTL                    0xFFC00A00      /* Asynchronous Memory Global Control Register */
+#define EBIU_AMBCTL0                   0xFFC00A04      /* Asynchronous Memory Bank Control Register 0 */
+#define EBIU_AMBCTL1                   0xFFC00A08      /* Asynchronous Memory Bank Control Register 1 */
+
+/* SDRAM Controller External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+
+#define EBIU_SDGCTL                    0xFFC00A10      /* SDRAM Global Control Register */
+#define EBIU_SDBCTL                    0xFFC00A14      /* SDRAM Bank Control Register */
+#define EBIU_SDRRC                     0xFFC00A18      /* SDRAM Refresh Rate Control Register */
+#define EBIU_SDSTAT                    0xFFC00A1C      /* SDRAM Status Register */
+
+/* DMA Traffic controls */
+#define DMA_TCPER 0xFFC00B0C   /* Traffic Control Periods Register */
+#define DMA_TCCNT 0xFFC00B10   /* Traffic Control Current Counts Register */
+#define DMA_TC_PER 0xFFC00B0C  /* Traffic Control Periods Register */
+#define DMA_TC_CNT 0xFFC00B10  /* Traffic Control Current Counts Register */
+
+/* DMA Controller (0xFFC00C00 - 0xFFC00FFF) */
+#define DMA0_CONFIG            0xFFC00C08      /* DMA Channel 0 Configuration Register */
+#define DMA0_NEXT_DESC_PTR     0xFFC00C00      /* DMA Channel 0 Next Descriptor Pointer Register */
+#define DMA0_START_ADDR                0xFFC00C04      /* DMA Channel 0 Start Address Register */
+#define DMA0_X_COUNT           0xFFC00C10      /* DMA Channel 0 X Count Register */
+#define DMA0_Y_COUNT           0xFFC00C18      /* DMA Channel 0 Y Count Register */
+#define DMA0_X_MODIFY          0xFFC00C14      /* DMA Channel 0 X Modify Register */
+#define DMA0_Y_MODIFY          0xFFC00C1C      /* DMA Channel 0 Y Modify Register */
+#define DMA0_CURR_DESC_PTR     0xFFC00C20      /* DMA Channel 0 Current Descriptor Pointer Register */
+#define DMA0_CURR_ADDR         0xFFC00C24      /* DMA Channel 0 Current Address Register */
+#define DMA0_CURR_X_COUNT      0xFFC00C30      /* DMA Channel 0 Current X Count Register */
+#define DMA0_CURR_Y_COUNT      0xFFC00C38      /* DMA Channel 0 Current Y Count Register */
+#define DMA0_IRQ_STATUS                0xFFC00C28      /* DMA Channel 0 Interrupt/Status Register */
+#define DMA0_PERIPHERAL_MAP    0xFFC00C2C      /* DMA Channel 0 Peripheral Map Register */
+
+#define DMA1_CONFIG            0xFFC00C48      /* DMA Channel 1 Configuration Register */
+#define DMA1_NEXT_DESC_PTR     0xFFC00C40      /* DMA Channel 1 Next Descriptor Pointer Register */
+#define DMA1_START_ADDR                0xFFC00C44      /* DMA Channel 1 Start Address Register */
+#define DMA1_X_COUNT           0xFFC00C50      /* DMA Channel 1 X Count Register */
+#define DMA1_Y_COUNT           0xFFC00C58      /* DMA Channel 1 Y Count Register */
+#define DMA1_X_MODIFY          0xFFC00C54      /* DMA Channel 1 X Modify Register */
+#define DMA1_Y_MODIFY          0xFFC00C5C      /* DMA Channel 1 Y Modify Register */
+#define DMA1_CURR_DESC_PTR     0xFFC00C60      /* DMA Channel 1 Current Descriptor Pointer Register */
+#define DMA1_CURR_ADDR         0xFFC00C64      /* DMA Channel 1 Current Address Register */
+#define DMA1_CURR_X_COUNT      0xFFC00C70      /* DMA Channel 1 Current X Count Register */
+#define DMA1_CURR_Y_COUNT      0xFFC00C78      /* DMA Channel 1 Current Y Count Register */
+#define DMA1_IRQ_STATUS                0xFFC00C68      /* DMA Channel 1 Interrupt/Status Register */
+#define DMA1_PERIPHERAL_MAP    0xFFC00C6C      /* DMA Channel 1 Peripheral Map Register */
+
+#define DMA2_CONFIG            0xFFC00C88      /* DMA Channel 2 Configuration Register */
+#define DMA2_NEXT_DESC_PTR     0xFFC00C80      /* DMA Channel 2 Next Descriptor Pointer Register */
+#define DMA2_START_ADDR                0xFFC00C84      /* DMA Channel 2 Start Address Register */
+#define DMA2_X_COUNT           0xFFC00C90      /* DMA Channel 2 X Count Register */
+#define DMA2_Y_COUNT           0xFFC00C98      /* DMA Channel 2 Y Count Register */
+#define DMA2_X_MODIFY          0xFFC00C94      /* DMA Channel 2 X Modify Register */
+#define DMA2_Y_MODIFY          0xFFC00C9C      /* DMA Channel 2 Y Modify Register */
+#define DMA2_CURR_DESC_PTR     0xFFC00CA0      /* DMA Channel 2 Current Descriptor Pointer Register */
+#define DMA2_CURR_ADDR         0xFFC00CA4      /* DMA Channel 2 Current Address Register */
+#define DMA2_CURR_X_COUNT      0xFFC00CB0      /* DMA Channel 2 Current X Count Register */
+#define DMA2_CURR_Y_COUNT      0xFFC00CB8      /* DMA Channel 2 Current Y Count Register */
+#define DMA2_IRQ_STATUS                0xFFC00CA8      /* DMA Channel 2 Interrupt/Status Register */
+#define DMA2_PERIPHERAL_MAP    0xFFC00CAC      /* DMA Channel 2 Peripheral Map Register */
+
+#define DMA3_CONFIG            0xFFC00CC8      /* DMA Channel 3 Configuration Register */
+#define DMA3_NEXT_DESC_PTR     0xFFC00CC0      /* DMA Channel 3 Next Descriptor Pointer Register */
+#define DMA3_START_ADDR                0xFFC00CC4      /* DMA Channel 3 Start Address Register */
+#define DMA3_X_COUNT           0xFFC00CD0      /* DMA Channel 3 X Count Register */
+#define DMA3_Y_COUNT           0xFFC00CD8      /* DMA Channel 3 Y Count Register */
+#define DMA3_X_MODIFY          0xFFC00CD4      /* DMA Channel 3 X Modify Register */
+#define DMA3_Y_MODIFY          0xFFC00CDC      /* DMA Channel 3 Y Modify Register */
+#define DMA3_CURR_DESC_PTR     0xFFC00CE0      /* DMA Channel 3 Current Descriptor Pointer Register */
+#define DMA3_CURR_ADDR         0xFFC00CE4      /* DMA Channel 3 Current Address Register */
+#define DMA3_CURR_X_COUNT      0xFFC00CF0      /* DMA Channel 3 Current X Count Register */
+#define DMA3_CURR_Y_COUNT      0xFFC00CF8      /* DMA Channel 3 Current Y Count Register */
+#define DMA3_IRQ_STATUS                0xFFC00CE8      /* DMA Channel 3 Interrupt/Status Register */
+#define DMA3_PERIPHERAL_MAP    0xFFC00CEC      /* DMA Channel 3 Peripheral Map Register */
+
+#define DMA4_CONFIG            0xFFC00D08      /* DMA Channel 4 Configuration Register */
+#define DMA4_NEXT_DESC_PTR     0xFFC00D00      /* DMA Channel 4 Next Descriptor Pointer Register */
+#define DMA4_START_ADDR                0xFFC00D04      /* DMA Channel 4 Start Address Register */
+#define DMA4_X_COUNT           0xFFC00D10      /* DMA Channel 4 X Count Register */
+#define DMA4_Y_COUNT           0xFFC00D18      /* DMA Channel 4 Y Count Register */
+#define DMA4_X_MODIFY          0xFFC00D14      /* DMA Channel 4 X Modify Register */
+#define DMA4_Y_MODIFY          0xFFC00D1C      /* DMA Channel 4 Y Modify Register */
+#define DMA4_CURR_DESC_PTR     0xFFC00D20      /* DMA Channel 4 Current Descriptor Pointer Register */
+#define DMA4_CURR_ADDR         0xFFC00D24      /* DMA Channel 4 Current Address Register */
+#define DMA4_CURR_X_COUNT      0xFFC00D30      /* DMA Channel 4 Current X Count Register */
+#define DMA4_CURR_Y_COUNT      0xFFC00D38      /* DMA Channel 4 Current Y Count Register */
+#define DMA4_IRQ_STATUS                0xFFC00D28      /* DMA Channel 4 Interrupt/Status Register */
+#define DMA4_PERIPHERAL_MAP    0xFFC00D2C      /* DMA Channel 4 Peripheral Map Register */
+
+#define DMA5_CONFIG            0xFFC00D48      /* DMA Channel 5 Configuration Register */
+#define DMA5_NEXT_DESC_PTR     0xFFC00D40      /* DMA Channel 5 Next Descriptor Pointer Register */
+#define DMA5_START_ADDR                0xFFC00D44      /* DMA Channel 5 Start Address Register */
+#define DMA5_X_COUNT           0xFFC00D50      /* DMA Channel 5 X Count Register */
+#define DMA5_Y_COUNT           0xFFC00D58      /* DMA Channel 5 Y Count Register */
+#define DMA5_X_MODIFY          0xFFC00D54      /* DMA Channel 5 X Modify Register */
+#define DMA5_Y_MODIFY          0xFFC00D5C      /* DMA Channel 5 Y Modify Register */
+#define DMA5_CURR_DESC_PTR     0xFFC00D60      /* DMA Channel 5 Current Descriptor Pointer Register */
+#define DMA5_CURR_ADDR         0xFFC00D64      /* DMA Channel 5 Current Address Register */
+#define DMA5_CURR_X_COUNT      0xFFC00D70      /* DMA Channel 5 Current X Count Register */
+#define DMA5_CURR_Y_COUNT      0xFFC00D78      /* DMA Channel 5 Current Y Count Register */
+#define DMA5_IRQ_STATUS                0xFFC00D68      /* DMA Channel 5 Interrupt/Status Register */
+#define DMA5_PERIPHERAL_MAP    0xFFC00D6C      /* DMA Channel 5 Peripheral Map Register */
+
+#define DMA6_CONFIG            0xFFC00D88      /* DMA Channel 6 Configuration Register */
+#define DMA6_NEXT_DESC_PTR     0xFFC00D80      /* DMA Channel 6 Next Descriptor Pointer Register */
+#define DMA6_START_ADDR                0xFFC00D84      /* DMA Channel 6 Start Address Register */
+#define DMA6_X_COUNT           0xFFC00D90      /* DMA Channel 6 X Count Register */
+#define DMA6_Y_COUNT           0xFFC00D98      /* DMA Channel 6 Y Count Register */
+#define DMA6_X_MODIFY          0xFFC00D94      /* DMA Channel 6 X Modify Register */
+#define DMA6_Y_MODIFY          0xFFC00D9C      /* DMA Channel 6 Y Modify Register */
+#define DMA6_CURR_DESC_PTR     0xFFC00DA0      /* DMA Channel 6 Current Descriptor Pointer Register */
+#define DMA6_CURR_ADDR         0xFFC00DA4      /* DMA Channel 6 Current Address Register */
+#define DMA6_CURR_X_COUNT      0xFFC00DB0      /* DMA Channel 6 Current X Count Register */
+#define DMA6_CURR_Y_COUNT      0xFFC00DB8      /* DMA Channel 6 Current Y Count Register */
+#define DMA6_IRQ_STATUS                0xFFC00DA8      /* DMA Channel 6 Interrupt/Status Register */
+#define DMA6_PERIPHERAL_MAP    0xFFC00DAC      /* DMA Channel 6 Peripheral Map Register */
+
+#define DMA7_CONFIG            0xFFC00DC8      /* DMA Channel 7 Configuration Register */
+#define DMA7_NEXT_DESC_PTR     0xFFC00DC0      /* DMA Channel 7 Next Descriptor Pointer Register */
+#define DMA7_START_ADDR                0xFFC00DC4      /* DMA Channel 7 Start Address Register */
+#define DMA7_X_COUNT           0xFFC00DD0      /* DMA Channel 7 X Count Register */
+#define DMA7_Y_COUNT           0xFFC00DD8      /* DMA Channel 7 Y Count Register */
+#define DMA7_X_MODIFY          0xFFC00DD4      /* DMA Channel 7 X Modify Register */
+#define DMA7_Y_MODIFY          0xFFC00DDC      /* DMA Channel 7 Y Modify Register */
+#define DMA7_CURR_DESC_PTR     0xFFC00DE0      /* DMA Channel 7 Current Descriptor Pointer Register */
+#define DMA7_CURR_ADDR         0xFFC00DE4      /* DMA Channel 7 Current Address Register */
+#define DMA7_CURR_X_COUNT      0xFFC00DF0      /* DMA Channel 7 Current X Count Register */
+#define DMA7_CURR_Y_COUNT      0xFFC00DF8      /* DMA Channel 7 Current Y Count Register */
+#define DMA7_IRQ_STATUS                0xFFC00DE8      /* DMA Channel 7 Interrupt/Status Register */
+#define DMA7_PERIPHERAL_MAP    0xFFC00DEC      /* DMA Channel 7 Peripheral Map Register */
+
+#define MDMA_D1_CONFIG         0xFFC00E88      /* MemDMA Stream 1 Destination Configuration Register */
+#define MDMA_D1_NEXT_DESC_PTR  0xFFC00E80      /* MemDMA Stream 1 Destination Next Descriptor Pointer Register */
+#define MDMA_D1_START_ADDR     0xFFC00E84      /* MemDMA Stream 1 Destination Start Address Register */
+#define MDMA_D1_X_COUNT                0xFFC00E90      /* MemDMA Stream 1 Destination X Count Register */
+#define MDMA_D1_Y_COUNT                0xFFC00E98      /* MemDMA Stream 1 Destination Y Count Register */
+#define MDMA_D1_X_MODIFY       0xFFC00E94      /* MemDMA Stream 1 Destination X Modify Register */
+#define MDMA_D1_Y_MODIFY       0xFFC00E9C      /* MemDMA Stream 1 Destination Y Modify Register */
+#define MDMA_D1_CURR_DESC_PTR  0xFFC00EA0      /* MemDMA Stream 1 Destination Current Descriptor Pointer Register */
+#define MDMA_D1_CURR_ADDR      0xFFC00EA4      /* MemDMA Stream 1 Destination Current Address Register */
+#define MDMA_D1_CURR_X_COUNT   0xFFC00EB0      /* MemDMA Stream 1 Destination Current X Count Register */
+#define MDMA_D1_CURR_Y_COUNT   0xFFC00EB8      /* MemDMA Stream 1 Destination Current Y Count Register */
+#define MDMA_D1_IRQ_STATUS     0xFFC00EA8      /* MemDMA Stream 1 Destination Interrupt/Status Register */
+#define MDMA_D1_PERIPHERAL_MAP 0xFFC00EAC      /* MemDMA Stream 1 Destination Peripheral Map Register */
+
+#define MDMA_S1_CONFIG         0xFFC00EC8      /* MemDMA Stream 1 Source Configuration Register */
+#define MDMA_S1_NEXT_DESC_PTR  0xFFC00EC0      /* MemDMA Stream 1 Source Next Descriptor Pointer Register */
+#define MDMA_S1_START_ADDR     0xFFC00EC4      /* MemDMA Stream 1 Source Start Address Register */
+#define MDMA_S1_X_COUNT                0xFFC00ED0      /* MemDMA Stream 1 Source X Count Register */
+#define MDMA_S1_Y_COUNT                0xFFC00ED8      /* MemDMA Stream 1 Source Y Count Register */
+#define MDMA_S1_X_MODIFY       0xFFC00ED4      /* MemDMA Stream 1 Source X Modify Register */
+#define MDMA_S1_Y_MODIFY       0xFFC00EDC      /* MemDMA Stream 1 Source Y Modify Register */
+#define MDMA_S1_CURR_DESC_PTR  0xFFC00EE0      /* MemDMA Stream 1 Source Current Descriptor Pointer Register */
+#define MDMA_S1_CURR_ADDR      0xFFC00EE4      /* MemDMA Stream 1 Source Current Address Register */
+#define MDMA_S1_CURR_X_COUNT   0xFFC00EF0      /* MemDMA Stream 1 Source Current X Count Register */
+#define MDMA_S1_CURR_Y_COUNT   0xFFC00EF8      /* MemDMA Stream 1 Source Current Y Count Register */
+#define MDMA_S1_IRQ_STATUS     0xFFC00EE8      /* MemDMA Stream 1 Source Interrupt/Status Register */
+#define MDMA_S1_PERIPHERAL_MAP 0xFFC00EEC      /* MemDMA Stream 1 Source Peripheral Map Register */
+
+#define MDMA_D0_CONFIG         0xFFC00E08      /* MemDMA Stream 0 Destination Configuration Register */
+#define MDMA_D0_NEXT_DESC_PTR  0xFFC00E00      /* MemDMA Stream 0 Destination Next Descriptor Pointer Register */
+#define MDMA_D0_START_ADDR     0xFFC00E04      /* MemDMA Stream 0 Destination Start Address Register */
+#define MDMA_D0_X_COUNT                0xFFC00E10      /* MemDMA Stream 0 Destination X Count Register */
+#define MDMA_D0_Y_COUNT                0xFFC00E18      /* MemDMA Stream 0 Destination Y Count Register */
+#define MDMA_D0_X_MODIFY       0xFFC00E14      /* MemDMA Stream 0 Destination X Modify Register */
+#define MDMA_D0_Y_MODIFY       0xFFC00E1C      /* MemDMA Stream 0 Destination Y Modify Register */
+#define MDMA_D0_CURR_DESC_PTR  0xFFC00E20      /* MemDMA Stream 0 Destination Current Descriptor Pointer Register */
+#define MDMA_D0_CURR_ADDR      0xFFC00E24      /* MemDMA Stream 0 Destination Current Address Register */
+#define MDMA_D0_CURR_X_COUNT   0xFFC00E30      /* MemDMA Stream 0 Destination Current X Count Register */
+#define MDMA_D0_CURR_Y_COUNT   0xFFC00E38      /* MemDMA Stream 0 Destination Current Y Count Register */
+#define MDMA_D0_IRQ_STATUS     0xFFC00E28      /* MemDMA Stream 0 Destination Interrupt/Status Register */
+#define MDMA_D0_PERIPHERAL_MAP 0xFFC00E2C      /* MemDMA Stream 0 Destination Peripheral Map Register */
+
+#define MDMA_S0_CONFIG         0xFFC00E48      /* MemDMA Stream 0 Source Configuration Register */
+#define MDMA_S0_NEXT_DESC_PTR  0xFFC00E40      /* MemDMA Stream 0 Source Next Descriptor Pointer Register */
+#define MDMA_S0_START_ADDR     0xFFC00E44      /* MemDMA Stream 0 Source Start Address Register */
+#define MDMA_S0_X_COUNT                0xFFC00E50      /* MemDMA Stream 0 Source X Count Register */
+#define MDMA_S0_Y_COUNT                0xFFC00E58      /* MemDMA Stream 0 Source Y Count Register */
+#define MDMA_S0_X_MODIFY       0xFFC00E54      /* MemDMA Stream 0 Source X Modify Register */
+#define MDMA_S0_Y_MODIFY       0xFFC00E5C      /* MemDMA Stream 0 Source Y Modify Register */
+#define MDMA_S0_CURR_DESC_PTR  0xFFC00E60      /* MemDMA Stream 0 Source Current Descriptor Pointer Register */
+#define MDMA_S0_CURR_ADDR      0xFFC00E64      /* MemDMA Stream 0 Source Current Address Register */
+#define MDMA_S0_CURR_X_COUNT   0xFFC00E70      /* MemDMA Stream 0 Source Current X Count Register */
+#define MDMA_S0_CURR_Y_COUNT   0xFFC00E78      /* MemDMA Stream 0 Source Current Y Count Register */
+#define MDMA_S0_IRQ_STATUS     0xFFC00E68      /* MemDMA Stream 0 Source Interrupt/Status Register */
+#define MDMA_S0_PERIPHERAL_MAP 0xFFC00E6C      /* MemDMA Stream 0 Source Peripheral Map Register */
+
+/* Parallel Peripheral Interface (PPI) (0xFFC01000 - 0xFFC010FF) */
+
+#define PPI_CONTROL                    0xFFC01000      /* PPI Control Register */
+#define PPI_STATUS                     0xFFC01004      /* PPI Status Register */
+#define PPI_COUNT                      0xFFC01008      /* PPI Transfer Count Register */
+#define PPI_DELAY                      0xFFC0100C      /* PPI Delay Count Register */
+#define PPI_FRAME                      0xFFC01010      /* PPI Frame Length Register */
+
+/*********************************************************************************** */
+/* System MMR Register Bits */
+/******************************************************************************* */
+
+/* ********************* PLL AND RESET MASKS ************************ */
+
+/* PLL_CTL Masks */
+#define PLL_CLKIN              0x00000000      /* Pass CLKIN to PLL */
+#define PLL_CLKIN_DIV2         0x00000001      /* Pass CLKIN/2 to PLL */
+#define PLL_OFF                0x00000002      /* Shut off PLL clocks */
+#define STOPCK_OFF             0x00000008      /* Core clock off */
+#define PDWN                   0x00000020      /* Put the PLL in a Deep Sleep state */
+#define BYPASS                 0x00000100      /* Bypass the PLL */
+
+/* PLL_DIV Masks */
+
+#define SCLK_DIV(x)  (x)       /* SCLK = VCO / x */
+
+#define CCLK_DIV1              0x00000000      /* CCLK = VCO / 1 */
+#define CCLK_DIV2              0x00000010      /* CCLK = VCO / 2 */
+#define CCLK_DIV4              0x00000020      /* CCLK = VCO / 4 */
+#define CCLK_DIV8              0x00000030      /* CCLK = VCO / 8 */
+
+/* PLL_STAT Masks                                                                                                                                      */
+#define ACTIVE_PLLENABLED      0x0001  /* Processor In Active Mode With PLL Enabled    */
+#define        FULL_ON                         0x0002  /* Processor In Full On Mode                                    */
+#define ACTIVE_PLLDISABLED     0x0004  /* Processor In Active Mode With PLL Disabled   */
+#define        PLL_LOCKED                      0x0020  /* PLL_LOCKCNT Has Been Reached                                 */
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* SWRST Mask */
+#define SYSTEM_RESET           0x00000007      /* Initiates a system software reset */
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS ***************** */
+
+    /* SIC_IAR0 Masks */
+
+#define P0_IVG(x)    ((x)-7)   /* Peripheral #0 assigned IVG #x  */
+#define P1_IVG(x)    ((x)-7) << 0x4    /* Peripheral #1 assigned IVG #x  */
+#define P2_IVG(x)    ((x)-7) << 0x8    /* Peripheral #2 assigned IVG #x  */
+#define P3_IVG(x)    ((x)-7) << 0xC    /* Peripheral #3 assigned IVG #x  */
+#define P4_IVG(x)    ((x)-7) << 0x10   /* Peripheral #4 assigned IVG #x  */
+#define P5_IVG(x)    ((x)-7) << 0x14   /* Peripheral #5 assigned IVG #x  */
+#define P6_IVG(x)    ((x)-7) << 0x18   /* Peripheral #6 assigned IVG #x  */
+#define P7_IVG(x)    ((x)-7) << 0x1C   /* Peripheral #7 assigned IVG #x  */
+
+/* SIC_IAR1 Masks */
+
+#define P8_IVG(x)     ((x)-7)  /* Peripheral #8 assigned IVG #x  */
+#define P9_IVG(x)     ((x)-7) << 0x4   /* Peripheral #9 assigned IVG #x  */
+#define P10_IVG(x)    ((x)-7) << 0x8   /* Peripheral #10 assigned IVG #x  */
+#define P11_IVG(x)    ((x)-7) << 0xC   /* Peripheral #11 assigned IVG #x  */
+#define P12_IVG(x)    ((x)-7) << 0x10  /* Peripheral #12 assigned IVG #x  */
+#define P13_IVG(x)    ((x)-7) << 0x14  /* Peripheral #13 assigned IVG #x  */
+#define P14_IVG(x)    ((x)-7) << 0x18  /* Peripheral #14 assigned IVG #x  */
+#define P15_IVG(x)    ((x)-7) << 0x1C  /* Peripheral #15 assigned IVG #x  */
+
+/* SIC_IAR2 Masks */
+#define P16_IVG(x)    ((x)-7)  /* Peripheral #16 assigned IVG #x  */
+#define P17_IVG(x)    ((x)-7) << 0x4   /* Peripheral #17 assigned IVG #x  */
+#define P18_IVG(x)    ((x)-7) << 0x8   /* Peripheral #18 assigned IVG #x  */
+#define P19_IVG(x)    ((x)-7) << 0xC   /* Peripheral #19 assigned IVG #x  */
+#define P20_IVG(x)    ((x)-7) << 0x10  /* Peripheral #20 assigned IVG #x  */
+#define P21_IVG(x)    ((x)-7) << 0x14  /* Peripheral #21 assigned IVG #x  */
+#define P22_IVG(x)    ((x)-7) << 0x18  /* Peripheral #22 assigned IVG #x  */
+#define P23_IVG(x)    ((x)-7) << 0x1C  /* Peripheral #23 assigned IVG #x  */
+
+/* SIC_IMASK Masks */
+#define SIC_UNMASK_ALL         0x00000000      /* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL           0xFFFFFFFF      /* Mask all peripheral interrupts */
+#define SIC_MASK(x)           (1 << (x))       /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << (x)))        /* Unmask Peripheral #x interrupt */
+
+/* SIC_IWR Masks */
+#define IWR_DISABLE_ALL        0x00000000      /* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL         0xFFFFFFFF      /* Wakeup Enable all peripherals */
+#define IWR_ENABLE(x)         (1 << (x))       /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))       /* Wakeup Disable Peripheral #x */
+
+/* *********  WATCHDOG TIMER MASKS  ********************8 */
+
+/* Watchdog Timer WDOG_CTL Register */
+#define ICTL(x) ((x<<1) & 0x0006)
+#define ENABLE_RESET     0x00000000    /* Set Watchdog Timer to generate reset */
+#define ENABLE_NMI       0x00000002    /* Set Watchdog Timer to generate non-maskable interrupt */
+#define ENABLE_GPI       0x00000004    /* Set Watchdog Timer to generate general-purpose interrupt */
+#define DISABLE_EVT      0x00000006    /* Disable Watchdog Timer interrupts */
+
+#define TMR_EN         0x0000
+#define TMR_DIS                0x0AD0
+#define TRO            0x8000
+
+#define ICTL_P0                0x01
+#define ICTL_P1                0x02
+#define TRO_P          0x0F
+
+/* ***************************** UART CONTROLLER MASKS ********************** */
+
+/* UART_LCR Register */
+
+#define DLAB   0x80
+#define SB      0x40
+#define STP      0x20
+#define EPS     0x10
+#define PEN    0x08
+#define STB    0x04
+#define WLS(x) ((x-5) & 0x03)
+
+#define DLAB_P 0x07
+#define SB_P   0x06
+#define STP_P  0x05
+#define EPS_P  0x04
+#define PEN_P  0x03
+#define STB_P  0x02
+#define WLS_P1 0x01
+#define WLS_P0 0x00
+
+/* UART_MCR Register */
+#define LOOP_ENA       0x10
+#define LOOP_ENA_P     0x04
+
+/* UART_LSR Register */
+#define TEMT   0x40
+#define THRE   0x20
+#define BI     0x10
+#define FE     0x08
+#define PE     0x04
+#define OE     0x02
+#define DR     0x01
+
+#define TEMP_P 0x06
+#define THRE_P 0x05
+#define BI_P   0x04
+#define FE_P   0x03
+#define PE_P   0x02
+#define OE_P   0x01
+#define DR_P   0x00
+
+/* UART_IER Register */
+#define ELSI   0x04
+#define ETBEI  0x02
+#define ERBFI  0x01
+
+#define ELSI_P 0x02
+#define ETBEI_P        0x01
+#define ERBFI_P        0x00
+
+/* UART_IIR Register */
+#define STATUS(x)      ((x << 1) & 0x06)
+#define NINT           0x01
+#define STATUS_P1      0x02
+#define STATUS_P0      0x01
+#define NINT_P         0x00
+#define IIR_TX_READY    0x02   /* UART_THR empty                               */
+#define IIR_RX_READY    0x04   /* Receive data ready                           */
+#define IIR_LINE_CHANGE 0x06   /* Receive line status                          */
+#define IIR_STATUS     0x06
+
+/* UART_GCTL Register */
+#define FFE    0x20
+#define FPE    0x10
+#define RPOLC  0x08
+#define TPOLC  0x04
+#define IREN   0x02
+#define UCEN   0x01
+
+#define FFE_P  0x05
+#define FPE_P  0x04
+#define RPOLC_P        0x03
+#define TPOLC_P        0x02
+#define IREN_P 0x01
+#define UCEN_P 0x00
+
+/* **********  SERIAL PORT MASKS  ********************** */
+
+/* SPORTx_TCR1 Masks */
+#define TSPEN    0x0001                /* TX enable  */
+#define ITCLK    0x0002                /* Internal TX Clock Select  */
+#define TDTYPE   0x000C                /* TX Data Formatting Select */
+#define TLSBIT   0x0010                /* TX Bit Order */
+#define ITFS     0x0200                /* Internal TX Frame Sync Select  */
+#define TFSR     0x0400                /* TX Frame Sync Required Select  */
+#define DITFS    0x0800                /* Data Independent TX Frame Sync Select  */
+#define LTFS     0x1000                /* Low TX Frame Sync Select  */
+#define LATFS    0x2000                /* Late TX Frame Sync Select  */
+#define TCKFE    0x4000                /* TX Clock Falling Edge Select  */
+
+/* SPORTx_TCR2 Masks */
+#define SLEN       0x001F      /*TX Word Length  */
+#define TXSE        0x0100     /*TX Secondary Enable */
+#define TSFSE       0x0200     /*TX Stereo Frame Sync Enable */
+#define TRFST       0x0400     /*TX Right-First Data Order  */
+
+/* SPORTx_RCR1 Masks */
+#define RSPEN    0x0001                /* RX enable  */
+#define IRCLK    0x0002                /* Internal RX Clock Select  */
+#define RDTYPE   0x000C                /* RX Data Formatting Select */
+#define RULAW    0x0008                /* u-Law enable  */
+#define RALAW    0x000C                /* A-Law enable  */
+#define RLSBIT   0x0010                /* RX Bit Order */
+#define IRFS     0x0200                /* Internal RX Frame Sync Select  */
+#define RFSR     0x0400                /* RX Frame Sync Required Select  */
+#define LRFS     0x1000                /* Low RX Frame Sync Select  */
+#define LARFS    0x2000                /* Late RX Frame Sync Select  */
+#define RCKFE    0x4000                /* RX Clock Falling Edge Select  */
+
+/* SPORTx_RCR2 Masks */
+#define SLEN       0x001F      /*RX Word Length  */
+#define RXSE        0x0100     /*RX Secondary Enable */
+#define RSFSE       0x0200     /*RX Stereo Frame Sync Enable */
+#define RRFST       0x0400     /*Right-First Data Order  */
+
+/*SPORTx_STAT Masks */
+#define RXNE           0x0001  /*RX FIFO Not Empty Status */
+#define RUVF           0x0002  /*RX Underflow Status */
+#define ROVF           0x0004  /*RX Overflow Status */
+#define TXF            0x0008  /*TX FIFO Full Status */
+#define TUVF           0x0010  /*TX Underflow Status */
+#define TOVF           0x0020  /*TX Overflow Status */
+#define TXHRE          0x0040  /*TX Hold Register Empty */
+
+/*SPORTx_MCMC1 Masks */
+#define SP_WSIZE               0x0000F000      /*Multichannel Window Size Field */
+#define SP_WOFF                0x000003FF      /*Multichannel Window Offset Field */
+
+/*SPORTx_MCMC2 Masks */
+#define MCCRM          0x00000003      /*Multichannel Clock Recovery Mode */
+#define MCDTXPE                0x00000004      /*Multichannel DMA Transmit Packing */
+#define MCDRXPE                0x00000008      /*Multichannel DMA Receive Packing */
+#define MCMEN          0x00000010      /*Multichannel Frame Mode Enable */
+#define FSDR           0x00000080      /*Multichannel Frame Sync to Data Relationship */
+#define MFD            0x0000F000      /*Multichannel Frame Delay    */
+
+/*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
+
+/*  PPI_CONTROL Masks         */
+#define PORT_EN              0x00000001        /* PPI Port Enable  */
+#define PORT_DIR             0x00000002        /* PPI Port Direction       */
+#define XFR_TYPE             0x0000000C        /* PPI Transfer Type  */
+#define PORT_CFG             0x00000030        /* PPI Port Configuration */
+#define FLD_SEL              0x00000040        /* PPI Active Field Select */
+#define PACK_EN              0x00000080        /* PPI Packing Mode */
+#define DMA32                0x00000100        /* PPI 32-bit DMA Enable */
+#define SKIP_EN              0x00000200        /* PPI Skip Element Enable */
+#define SKIP_EO              0x00000400        /* PPI Skip Even/Odd Elements */
+#define DLENGTH              0x00003800        /* PPI Data Length  */
+#define DLEN_8                 0x0000  /* Data Length = 8 Bits                         */
+#define DLEN_10                        0x0800  /* Data Length = 10 Bits                        */
+#define DLEN_11                        0x1000  /* Data Length = 11 Bits                        */
+#define DLEN_12                        0x1800  /* Data Length = 12 Bits                        */
+#define DLEN_13                        0x2000  /* Data Length = 13 Bits                        */
+#define DLEN_14                        0x2800  /* Data Length = 14 Bits                        */
+#define DLEN_15                        0x3000  /* Data Length = 15 Bits                        */
+#define DLEN_16                        0x3800  /* Data Length = 16 Bits                        */
+#define DLEN(x)        (((x-9) & 0x07) << 11)  /* PPI Data Length (only works for x=10-->x=16) */
+#define POL                  0x0000C000        /* PPI Signal Polarities       */
+
+/* PPI_STATUS Masks                                          */
+#define FLD                 0x00000400 /* Field Indicator   */
+#define FT_ERR              0x00000800 /* Frame Track Error */
+#define OVR                 0x00001000 /* FIFO Overflow Error */
+#define UNDR                0x00002000 /* FIFO Underrun Error */
+#define ERR_DET                     0x00004000 /* Error Detected Indicator */
+#define ERR_NCOR            0x00008000 /* Error Not Corrected Indicator */
+
+/* **********  DMA CONTROLLER MASKS  *********************8 */
+
+/*DMAx_CONFIG, MDMA_yy_CONFIG Masks */
+#define DMAEN          0x00000001      /* Channel Enable */
+#define WNR            0x00000002      /* Channel Direction (W/R*) */
+#define WDSIZE_8       0x00000000      /* Word Size 8 bits */
+#define WDSIZE_16      0x00000004      /* Word Size 16 bits */
+#define WDSIZE_32      0x00000008      /* Word Size 32 bits */
+#define DMA2D          0x00000010      /* 2D/1D* Mode */
+#define RESTART         0x00000020     /* Restart */
+#define DI_SEL         0x00000040      /* Data Interrupt Select */
+#define DI_EN          0x00000080      /* Data Interrupt Enable */
+#define NDSIZE_0               0x0000  /* Next Descriptor Size = 0 (Stop/Autobuffer)   */
+#define NDSIZE_1               0x0100  /* Next Descriptor Size = 1                                             */
+#define NDSIZE_2               0x0200  /* Next Descriptor Size = 2                                             */
+#define NDSIZE_3               0x0300  /* Next Descriptor Size = 3                                             */
+#define NDSIZE_4               0x0400  /* Next Descriptor Size = 4                                             */
+#define NDSIZE_5               0x0500  /* Next Descriptor Size = 5                                             */
+#define NDSIZE_6               0x0600  /* Next Descriptor Size = 6                                             */
+#define NDSIZE_7               0x0700  /* Next Descriptor Size = 7                                             */
+#define NDSIZE_8               0x0800  /* Next Descriptor Size = 8                                             */
+#define NDSIZE_9               0x0900  /* Next Descriptor Size = 9                                             */
+#define NDSIZE         0x00000900      /* Next Descriptor Size */
+#define DMAFLOW                0x00007000      /* Flow Control */
+#define DMAFLOW_STOP           0x0000  /* Stop Mode */
+#define DMAFLOW_AUTO           0x1000  /* Autobuffer Mode */
+#define DMAFLOW_ARRAY          0x4000  /* Descriptor Array Mode */
+#define DMAFLOW_SMALL          0x6000  /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE          0x7000  /* Large Model Descriptor List Mode */
+
+#define DMAEN_P                        0       /* Channel Enable */
+#define WNR_P                  1       /* Channel Direction (W/R*) */
+#define DMA2D_P                        4       /* 2D/1D* Mode */
+#define RESTART_P              5       /* Restart */
+#define DI_SEL_P               6       /* Data Interrupt Select */
+#define DI_EN_P                        7       /* Data Interrupt Enable */
+
+/*DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks */
+
+#define DMA_DONE               0x00000001      /* DMA Done Indicator */
+#define DMA_ERR                        0x00000002      /* DMA Error Indicator */
+#define DFETCH                 0x00000004      /* Descriptor Fetch Indicator */
+#define DMA_RUN                        0x00000008      /* DMA Running Indicator */
+
+#define DMA_DONE_P             0       /* DMA Done Indicator */
+#define DMA_ERR_P              1       /* DMA Error Indicator */
+#define DFETCH_P               2       /* Descriptor Fetch Indicator */
+#define DMA_RUN_P              3       /* DMA Running Indicator */
+
+/*DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */
+
+#define CTYPE              0x00000040  /* DMA Channel Type Indicator */
+#define CTYPE_P             6  /* DMA Channel Type Indicator BIT POSITION */
+#define PCAP8              0x00000080  /* DMA 8-bit Operation Indicator   */
+#define PCAP16             0x00000100  /* DMA 16-bit Operation Indicator */
+#define PCAP32             0x00000200  /* DMA 32-bit Operation Indicator */
+#define PCAPWR             0x00000400  /* DMA Write Operation Indicator */
+#define PCAPRD             0x00000800  /* DMA Read Operation Indicator */
+#define PMAP               0x00007000  /* DMA Peripheral Map Field */
+
+/*  *************  GENERAL PURPOSE TIMER MASKS  ******************** */
+
+/* PWM Timer bit definitions */
+
+/* TIMER_ENABLE Register */
+#define TIMEN0 0x0001
+#define TIMEN1 0x0002
+#define TIMEN2 0x0004
+
+#define TIMEN0_P       0x00
+#define TIMEN1_P       0x01
+#define TIMEN2_P       0x02
+
+/* TIMER_DISABLE Register */
+#define TIMDIS0        0x0001
+#define TIMDIS1        0x0002
+#define TIMDIS2        0x0004
+
+#define TIMDIS0_P      0x00
+#define TIMDIS1_P      0x01
+#define TIMDIS2_P      0x02
+
+/* TIMER_STATUS Register */
+#define TIMIL0         0x0001
+#define TIMIL1         0x0002
+#define TIMIL2         0x0004
+#define TOVL_ERR0      0x0010
+#define TOVL_ERR1      0x0020
+#define TOVL_ERR2      0x0040
+#define TRUN0          0x1000
+#define TRUN1          0x2000
+#define TRUN2          0x4000
+
+#define TIMIL0_P       0x00
+#define TIMIL1_P       0x01
+#define TIMIL2_P       0x02
+#define TOVL_ERR0_P    0x04
+#define TOVL_ERR1_P    0x05
+#define TOVL_ERR2_P    0x06
+#define TRUN0_P                0x0C
+#define TRUN1_P                0x0D
+#define TRUN2_P                0x0E
+
+/* TIMERx_CONFIG Registers */
+#define PWM_OUT                0x0001
+#define WDTH_CAP       0x0002
+#define EXT_CLK                0x0003
+#define PULSE_HI       0x0004
+#define PERIOD_CNT     0x0008
+#define IRQ_ENA                0x0010
+#define TIN_SEL                0x0020
+#define OUT_DIS                0x0040
+#define CLK_SEL                0x0080
+#define TOGGLE_HI      0x0100
+#define EMU_RUN                0x0200
+#define ERR_TYP(x)     ((x & 0x03) << 14)
+
+#define TMODE_P0               0x00
+#define TMODE_P1               0x01
+#define PULSE_HI_P             0x02
+#define PERIOD_CNT_P           0x03
+#define IRQ_ENA_P              0x04
+#define TIN_SEL_P              0x05
+#define OUT_DIS_P              0x06
+#define CLK_SEL_P              0x07
+#define TOGGLE_HI_P            0x08
+#define EMU_RUN_P              0x09
+#define ERR_TYP_P0             0x0E
+#define ERR_TYP_P1             0x0F
+
+/*/ ******************   PROGRAMMABLE FLAG MASKS  ********************* */
+
+/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks */
+#define PF0         0x0001
+#define PF1         0x0002
+#define PF2         0x0004
+#define PF3         0x0008
+#define PF4         0x0010
+#define PF5         0x0020
+#define PF6         0x0040
+#define PF7         0x0080
+#define PF8         0x0100
+#define PF9         0x0200
+#define PF10        0x0400
+#define PF11        0x0800
+#define PF12        0x1000
+#define PF13        0x2000
+#define PF14        0x4000
+#define PF15        0x8000
+
+/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  BIT POSITIONS */
+#define PF0_P         0
+#define PF1_P         1
+#define PF2_P         2
+#define PF3_P         3
+#define PF4_P         4
+#define PF5_P         5
+#define PF6_P         6
+#define PF7_P         7
+#define PF8_P         8
+#define PF9_P         9
+#define PF10_P        10
+#define PF11_P        11
+#define PF12_P        12
+#define PF13_P        13
+#define PF14_P        14
+#define PF15_P        15
+
+/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  **************** */
+
+/* SPI_CTL Masks */
+#define TIMOD                  0x00000003      /* Transfer initiation mode and interrupt generation */
+#define SZ                     0x00000004      /* Send Zero (=0) or last (=1) word when TDBR empty. */
+#define GM                     0x00000008      /* When RDBR full, get more (=1) data or discard (=0) incoming Data */
+#define PSSE                   0x00000010      /* Enable (=1) Slave-Select input for Master. */
+#define EMISO                  0x00000020      /* Enable (=1) MISO pin as an output. */
+#define SPI_LEN                0x00000100      /* Word length (0 => 8 bits, 1 => 16 bits) */
+#define LSBF                   0x00000200      /* Data format (0 => MSB sent/received first 1 => LSB sent/received first) */
+#define CPHA                   0x00000400      /* Clock phase (0 => SPICLK starts toggling in middle of xfer, 1 => SPICLK toggles at the beginning of xfer. */
+#define CPOL                   0x00000800      /* Clock polarity (0 => active-high, 1 => active-low) */
+#define MSTR                   0x00001000      /* Configures SPI as master (=1) or slave (=0) */
+#define WOM                    0x00002000      /* Open drain (=1) data output enable (for MOSI and MISO) */
+#define SPE                    0x00004000      /* SPI module enable (=1), disable (=0) */
+
+/* SPI_FLG Masks */
+#define FLS1                   0x00000002      /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLS2                   0x00000004      /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLS3                   0x00000008      /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLS4                   0x00000010      /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLS5                   0x00000020      /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLS6                   0x00000040      /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLS7                   0x00000080      /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
+#define FLG1                   0x00000200      /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
+#define FLG2                   0x00000400      /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLG3                   0x00000800      /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
+#define FLG4                   0x00001000      /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
+#define FLG5                   0x00002000      /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
+#define FLG6                   0x00004000      /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
+#define FLG7                   0x00008000      /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+/* SPI_FLG Bit Positions */
+#define FLS1_P                 0x00000001      /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLS2_P                 0x00000002      /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLS3_P                 0x00000003      /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLS4_P                 0x00000004      /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLS5_P                 0x00000005      /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLS6_P                 0x00000006      /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLS7_P                 0x00000007      /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
+#define FLG1_P                 0x00000009      /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
+#define FLG2_P                 0x0000000A      /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLG3_P                 0x0000000B      /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
+#define FLG4_P                 0x0000000C      /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
+#define FLG5_P                 0x0000000D      /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
+#define FLG6_P                 0x0000000E      /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
+#define FLG7_P                 0x0000000F      /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+/* SPI_STAT Masks */
+#define SPIF                   0x00000001      /* Set (=1) when SPI single-word transfer complete */
+#define MODF                   0x00000002      /* Set (=1) in a master device when some other device tries to become master */
+#define TXE                    0x00000004      /* Set (=1) when transmission occurs with no new data in SPI_TDBR */
+#define TXS                    0x00000008      /* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
+#define RBSY                   0x00000010      /* Set (=1) when data is received with RDBR full */
+#define RXS                    0x00000020      /* SPI_RDBR Data Buffer Status (0=Empty, 1=Full)  */
+#define TXCOL                  0x00000040      /* When set (=1), corrupt data may have been transmitted  */
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
+
+/* AMGCTL Masks */
+#define AMCKEN                 0x00000001      /* Enable CLKOUT */
+#define AMBEN_B0               0x00000002      /* Enable Asynchronous Memory Bank 0 only */
+#define AMBEN_B0_B1            0x00000004      /* Enable Asynchronous Memory Banks 0 & 1 only */
+#define AMBEN_B0_B1_B2         0x00000006      /* Enable Asynchronous Memory Banks 0, 1, and 2 */
+#define AMBEN_ALL              0x00000008      /* Enable Asynchronous Memory Banks (all) 0, 1, 2, and 3 */
+
+/* AMGCTL Bit Positions */
+#define AMCKEN_P               0x00000000      /* Enable CLKOUT */
+#define AMBEN_P0               0x00000001      /* Asynchronous Memory Enable, 000 - banks 0-3 disabled, 001 - Bank 0 enabled */
+#define AMBEN_P1               0x00000002      /* Asynchronous Memory Enable, 010 - banks 0&1 enabled,  011 - banks 0-3 enabled */
+#define AMBEN_P2               0x00000003      /* Asynchronous Memory Enable, 1xx - All banks (bank 0, 1, 2, and 3) enabled */
+
+/* AMBCTL0 Masks */
+#define B0RDYEN        0x00000001      /* Bank 0 RDY Enable, 0=disable, 1=enable */
+#define B0RDYPOL 0x00000002    /* Bank 0 RDY Active high, 0=active low, 1=active high */
+#define B0TT_1 0x00000004      /* Bank 0 Transition Time from Read to Write = 1 cycle */
+#define B0TT_2 0x00000008      /* Bank 0 Transition Time from Read to Write = 2 cycles */
+#define B0TT_3 0x0000000C      /* Bank 0 Transition Time from Read to Write = 3 cycles */
+#define B0TT_4 0x00000000      /* Bank 0 Transition Time from Read to Write = 4 cycles */
+#define B0ST_1 0x00000010      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=1 cycle */
+#define B0ST_2 0x00000020      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=2 cycles */
+#define B0ST_3 0x00000030      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=3 cycles */
+#define B0ST_4 0x00000000      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=4 cycles */
+#define B0HT_1 0x00000040      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 1 cycle */
+#define B0HT_2 0x00000080      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 2 cycles */
+#define B0HT_3 0x000000C0      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 3 cycles */
+#define B0HT_0 0x00000000      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 0 cycles */
+#define B0RAT_1                        0x00000100      /* Bank 0 Read Access Time = 1 cycle */
+#define B0RAT_2                        0x00000200      /* Bank 0 Read Access Time = 2 cycles */
+#define B0RAT_3                        0x00000300      /* Bank 0 Read Access Time = 3 cycles */
+#define B0RAT_4                        0x00000400      /* Bank 0 Read Access Time = 4 cycles */
+#define B0RAT_5                        0x00000500      /* Bank 0 Read Access Time = 5 cycles */
+#define B0RAT_6                        0x00000600      /* Bank 0 Read Access Time = 6 cycles */
+#define B0RAT_7                        0x00000700      /* Bank 0 Read Access Time = 7 cycles */
+#define B0RAT_8                        0x00000800      /* Bank 0 Read Access Time = 8 cycles */
+#define B0RAT_9                        0x00000900      /* Bank 0 Read Access Time = 9 cycles */
+#define B0RAT_10               0x00000A00      /* Bank 0 Read Access Time = 10 cycles */
+#define B0RAT_11               0x00000B00      /* Bank 0 Read Access Time = 11 cycles */
+#define B0RAT_12               0x00000C00      /* Bank 0 Read Access Time = 12 cycles */
+#define B0RAT_13               0x00000D00      /* Bank 0 Read Access Time = 13 cycles */
+#define B0RAT_14               0x00000E00      /* Bank 0 Read Access Time = 14 cycles */
+#define B0RAT_15               0x00000F00      /* Bank 0 Read Access Time = 15 cycles */
+#define B0WAT_1                        0x00001000      /* Bank 0 Write Access Time = 1 cycle */
+#define B0WAT_2                        0x00002000      /* Bank 0 Write Access Time = 2 cycles */
+#define B0WAT_3                        0x00003000      /* Bank 0 Write Access Time = 3 cycles */
+#define B0WAT_4                        0x00004000      /* Bank 0 Write Access Time = 4 cycles */
+#define B0WAT_5                        0x00005000      /* Bank 0 Write Access Time = 5 cycles */
+#define B0WAT_6                        0x00006000      /* Bank 0 Write Access Time = 6 cycles */
+#define B0WAT_7                        0x00007000      /* Bank 0 Write Access Time = 7 cycles */
+#define B0WAT_8                        0x00008000      /* Bank 0 Write Access Time = 8 cycles */
+#define B0WAT_9                        0x00009000      /* Bank 0 Write Access Time = 9 cycles */
+#define B0WAT_10               0x0000A000      /* Bank 0 Write Access Time = 10 cycles */
+#define B0WAT_11               0x0000B000      /* Bank 0 Write Access Time = 11 cycles */
+#define B0WAT_12               0x0000C000      /* Bank 0 Write Access Time = 12 cycles */
+#define B0WAT_13               0x0000D000      /* Bank 0 Write Access Time = 13 cycles */
+#define B0WAT_14               0x0000E000      /* Bank 0 Write Access Time = 14 cycles */
+#define B0WAT_15               0x0000F000      /* Bank 0 Write Access Time = 15 cycles */
+#define B1RDYEN                        0x00010000      /* Bank 1 RDY enable, 0=disable, 1=enable */
+#define B1RDYPOL               0x00020000      /* Bank 1 RDY Active high, 0=active low, 1=active high */
+#define B1TT_1                 0x00040000      /* Bank 1 Transition Time from Read to Write = 1 cycle */
+#define B1TT_2                 0x00080000      /* Bank 1 Transition Time from Read to Write = 2 cycles */
+#define B1TT_3                 0x000C0000      /* Bank 1 Transition Time from Read to Write = 3 cycles */
+#define B1TT_4                 0x00000000      /* Bank 1 Transition Time from Read to Write = 4 cycles */
+#define B1ST_1                 0x00100000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B1ST_2                 0x00200000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B1ST_3                 0x00300000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B1ST_4                 0x00000000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B1HT_1                 0x00400000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B1HT_2                 0x00800000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B1HT_3                 0x00C00000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B1HT_0                 0x00000000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B1RAT_1                        0x01000000      /* Bank 1 Read Access Time = 1 cycle */
+#define B1RAT_2                        0x02000000      /* Bank 1 Read Access Time = 2 cycles */
+#define B1RAT_3                        0x03000000      /* Bank 1 Read Access Time = 3 cycles */
+#define B1RAT_4                        0x04000000      /* Bank 1 Read Access Time = 4 cycles */
+#define B1RAT_5                        0x05000000      /* Bank 1 Read Access Time = 5 cycles */
+#define B1RAT_6                        0x06000000      /* Bank 1 Read Access Time = 6 cycles */
+#define B1RAT_7                        0x07000000      /* Bank 1 Read Access Time = 7 cycles */
+#define B1RAT_8                        0x08000000      /* Bank 1 Read Access Time = 8 cycles */
+#define B1RAT_9                        0x09000000      /* Bank 1 Read Access Time = 9 cycles */
+#define B1RAT_10               0x0A000000      /* Bank 1 Read Access Time = 10 cycles */
+#define B1RAT_11               0x0B000000      /* Bank 1 Read Access Time = 11 cycles */
+#define B1RAT_12               0x0C000000      /* Bank 1 Read Access Time = 12 cycles */
+#define B1RAT_13               0x0D000000      /* Bank 1 Read Access Time = 13 cycles */
+#define B1RAT_14               0x0E000000      /* Bank 1 Read Access Time = 14 cycles */
+#define B1RAT_15               0x0F000000      /* Bank 1 Read Access Time = 15 cycles */
+#define B1WAT_1                        0x10000000      /* Bank 1 Write Access Time = 1 cycle */
+#define B1WAT_2                        0x20000000      /* Bank 1 Write Access Time = 2 cycles */
+#define B1WAT_3                        0x30000000      /* Bank 1 Write Access Time = 3 cycles */
+#define B1WAT_4                        0x40000000      /* Bank 1 Write Access Time = 4 cycles */
+#define B1WAT_5                        0x50000000      /* Bank 1 Write Access Time = 5 cycles */
+#define B1WAT_6                        0x60000000      /* Bank 1 Write Access Time = 6 cycles */
+#define B1WAT_7                        0x70000000      /* Bank 1 Write Access Time = 7 cycles */
+#define B1WAT_8                        0x80000000      /* Bank 1 Write Access Time = 8 cycles */
+#define B1WAT_9                        0x90000000      /* Bank 1 Write Access Time = 9 cycles */
+#define B1WAT_10               0xA0000000      /* Bank 1 Write Access Time = 10 cycles */
+#define B1WAT_11               0xB0000000      /* Bank 1 Write Access Time = 11 cycles */
+#define B1WAT_12               0xC0000000      /* Bank 1 Write Access Time = 12 cycles */
+#define B1WAT_13               0xD0000000      /* Bank 1 Write Access Time = 13 cycles */
+#define B1WAT_14               0xE0000000      /* Bank 1 Write Access Time = 14 cycles */
+#define B1WAT_15               0xF0000000      /* Bank 1 Write Access Time = 15 cycles */
+
+/* AMBCTL1 Masks */
+#define B2RDYEN                        0x00000001      /* Bank 2 RDY Enable, 0=disable, 1=enable */
+#define B2RDYPOL               0x00000002      /* Bank 2 RDY Active high, 0=active low, 1=active high */
+#define B2TT_1                 0x00000004      /* Bank 2 Transition Time from Read to Write = 1 cycle */
+#define B2TT_2                 0x00000008      /* Bank 2 Transition Time from Read to Write = 2 cycles */
+#define B2TT_3                 0x0000000C      /* Bank 2 Transition Time from Read to Write = 3 cycles */
+#define B2TT_4                 0x00000000      /* Bank 2 Transition Time from Read to Write = 4 cycles */
+#define B2ST_1                 0x00000010      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B2ST_2                 0x00000020      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B2ST_3                 0x00000030      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B2ST_4                 0x00000000      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B2HT_1                 0x00000040      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B2HT_2                 0x00000080      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B2HT_3                 0x000000C0      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B2HT_0                 0x00000000      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B2RAT_1                        0x00000100      /* Bank 2 Read Access Time = 1 cycle */
+#define B2RAT_2                        0x00000200      /* Bank 2 Read Access Time = 2 cycles */
+#define B2RAT_3                        0x00000300      /* Bank 2 Read Access Time = 3 cycles */
+#define B2RAT_4                        0x00000400      /* Bank 2 Read Access Time = 4 cycles */
+#define B2RAT_5                        0x00000500      /* Bank 2 Read Access Time = 5 cycles */
+#define B2RAT_6                        0x00000600      /* Bank 2 Read Access Time = 6 cycles */
+#define B2RAT_7                        0x00000700      /* Bank 2 Read Access Time = 7 cycles */
+#define B2RAT_8                        0x00000800      /* Bank 2 Read Access Time = 8 cycles */
+#define B2RAT_9                        0x00000900      /* Bank 2 Read Access Time = 9 cycles */
+#define B2RAT_10               0x00000A00      /* Bank 2 Read Access Time = 10 cycles */
+#define B2RAT_11               0x00000B00      /* Bank 2 Read Access Time = 11 cycles */
+#define B2RAT_12               0x00000C00      /* Bank 2 Read Access Time = 12 cycles */
+#define B2RAT_13               0x00000D00      /* Bank 2 Read Access Time = 13 cycles */
+#define B2RAT_14               0x00000E00      /* Bank 2 Read Access Time = 14 cycles */
+#define B2RAT_15               0x00000F00      /* Bank 2 Read Access Time = 15 cycles */
+#define B2WAT_1                        0x00001000      /* Bank 2 Write Access Time = 1 cycle */
+#define B2WAT_2                        0x00002000      /* Bank 2 Write Access Time = 2 cycles */
+#define B2WAT_3                        0x00003000      /* Bank 2 Write Access Time = 3 cycles */
+#define B2WAT_4                        0x00004000      /* Bank 2 Write Access Time = 4 cycles */
+#define B2WAT_5                        0x00005000      /* Bank 2 Write Access Time = 5 cycles */
+#define B2WAT_6                        0x00006000      /* Bank 2 Write Access Time = 6 cycles */
+#define B2WAT_7                        0x00007000      /* Bank 2 Write Access Time = 7 cycles */
+#define B2WAT_8                        0x00008000      /* Bank 2 Write Access Time = 8 cycles */
+#define B2WAT_9                        0x00009000      /* Bank 2 Write Access Time = 9 cycles */
+#define B2WAT_10               0x0000A000      /* Bank 2 Write Access Time = 10 cycles */
+#define B2WAT_11               0x0000B000      /* Bank 2 Write Access Time = 11 cycles */
+#define B2WAT_12               0x0000C000      /* Bank 2 Write Access Time = 12 cycles */
+#define B2WAT_13               0x0000D000      /* Bank 2 Write Access Time = 13 cycles */
+#define B2WAT_14               0x0000E000      /* Bank 2 Write Access Time = 14 cycles */
+#define B2WAT_15               0x0000F000      /* Bank 2 Write Access Time = 15 cycles */
+#define B3RDYEN                        0x00010000      /* Bank 3 RDY enable, 0=disable, 1=enable */
+#define B3RDYPOL               0x00020000      /* Bank 3 RDY Active high, 0=active low, 1=active high */
+#define B3TT_1                 0x00040000      /* Bank 3 Transition Time from Read to Write = 1 cycle */
+#define B3TT_2                 0x00080000      /* Bank 3 Transition Time from Read to Write = 2 cycles */
+#define B3TT_3                 0x000C0000      /* Bank 3 Transition Time from Read to Write = 3 cycles */
+#define B3TT_4                 0x00000000      /* Bank 3 Transition Time from Read to Write = 4 cycles */
+#define B3ST_1                 0x00100000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B3ST_2                 0x00200000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B3ST_3                 0x00300000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B3ST_4                 0x00000000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B3HT_1                 0x00400000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B3HT_2                 0x00800000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B3HT_3                 0x00C00000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B3HT_0                 0x00000000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B3RAT_1                        0x01000000      /* Bank 3 Read Access Time = 1 cycle */
+#define B3RAT_2                        0x02000000      /* Bank 3 Read Access Time = 2 cycles */
+#define B3RAT_3                        0x03000000      /* Bank 3 Read Access Time = 3 cycles */
+#define B3RAT_4                        0x04000000      /* Bank 3 Read Access Time = 4 cycles */
+#define B3RAT_5                        0x05000000      /* Bank 3 Read Access Time = 5 cycles */
+#define B3RAT_6                        0x06000000      /* Bank 3 Read Access Time = 6 cycles */
+#define B3RAT_7                        0x07000000      /* Bank 3 Read Access Time = 7 cycles */
+#define B3RAT_8                        0x08000000      /* Bank 3 Read Access Time = 8 cycles */
+#define B3RAT_9                        0x09000000      /* Bank 3 Read Access Time = 9 cycles */
+#define B3RAT_10               0x0A000000      /* Bank 3 Read Access Time = 10 cycles */
+#define B3RAT_11               0x0B000000      /* Bank 3 Read Access Time = 11 cycles */
+#define B3RAT_12               0x0C000000      /* Bank 3 Read Access Time = 12 cycles */
+#define B3RAT_13               0x0D000000      /* Bank 3 Read Access Time = 13 cycles */
+#define B3RAT_14               0x0E000000      /* Bank 3 Read Access Time = 14 cycles */
+#define B3RAT_15               0x0F000000      /* Bank 3 Read Access Time = 15 cycles */
+#define B3WAT_1                        0x10000000      /* Bank 3 Write Access Time = 1 cycle */
+#define B3WAT_2                        0x20000000      /* Bank 3 Write Access Time = 2 cycles */
+#define B3WAT_3                        0x30000000      /* Bank 3 Write Access Time = 3 cycles */
+#define B3WAT_4                        0x40000000      /* Bank 3 Write Access Time = 4 cycles */
+#define B3WAT_5                        0x50000000      /* Bank 3 Write Access Time = 5 cycles */
+#define B3WAT_6                        0x60000000      /* Bank 3 Write Access Time = 6 cycles */
+#define B3WAT_7                        0x70000000      /* Bank 3 Write Access Time = 7 cycles */
+#define B3WAT_8                        0x80000000      /* Bank 3 Write Access Time = 8 cycles */
+#define B3WAT_9                        0x90000000      /* Bank 3 Write Access Time = 9 cycles */
+#define B3WAT_10               0xA0000000      /* Bank 3 Write Access Time = 10 cycles */
+#define B3WAT_11               0xB0000000      /* Bank 3 Write Access Time = 11 cycles */
+#define B3WAT_12               0xC0000000      /* Bank 3 Write Access Time = 12 cycles */
+#define B3WAT_13               0xD0000000      /* Bank 3 Write Access Time = 13 cycles */
+#define B3WAT_14               0xE0000000      /* Bank 3 Write Access Time = 14 cycles */
+#define B3WAT_15               0xF0000000      /* Bank 3 Write Access Time = 15 cycles */
+
+/* **********************  SDRAM CONTROLLER MASKS  *************************** */
+
+/* SDGCTL Masks */
+#define SCTLE                  0x00000001      /* Enable SCLK[0], /SRAS, /SCAS, /SWE, SDQM[3:0] */
+#define CL_2                   0x00000008      /* SDRAM CAS latency = 2 cycles */
+#define CL_3                   0x0000000C      /* SDRAM CAS latency = 3 cycles */
+#define PFE                    0x00000010      /* Enable SDRAM prefetch */
+#define PFP                    0x00000020      /* Prefetch has priority over AMC requests */
+#define TRAS_1                 0x00000040      /* SDRAM tRAS = 1 cycle */
+#define TRAS_2                 0x00000080      /* SDRAM tRAS = 2 cycles */
+#define TRAS_3                 0x000000C0      /* SDRAM tRAS = 3 cycles */
+#define TRAS_4                 0x00000100      /* SDRAM tRAS = 4 cycles */
+#define TRAS_5                 0x00000140      /* SDRAM tRAS = 5 cycles */
+#define TRAS_6                 0x00000180      /* SDRAM tRAS = 6 cycles */
+#define TRAS_7                 0x000001C0      /* SDRAM tRAS = 7 cycles */
+#define TRAS_8                 0x00000200      /* SDRAM tRAS = 8 cycles */
+#define TRAS_9                 0x00000240      /* SDRAM tRAS = 9 cycles */
+#define TRAS_10                        0x00000280      /* SDRAM tRAS = 10 cycles */
+#define TRAS_11                        0x000002C0      /* SDRAM tRAS = 11 cycles */
+#define TRAS_12                        0x00000300      /* SDRAM tRAS = 12 cycles */
+#define TRAS_13                        0x00000340      /* SDRAM tRAS = 13 cycles */
+#define TRAS_14                        0x00000380      /* SDRAM tRAS = 14 cycles */
+#define TRAS_15                        0x000003C0      /* SDRAM tRAS = 15 cycles */
+#define TRP_1                  0x00000800      /* SDRAM tRP = 1 cycle */
+#define TRP_2                  0x00001000      /* SDRAM tRP = 2 cycles */
+#define TRP_3                  0x00001800      /* SDRAM tRP = 3 cycles */
+#define TRP_4                  0x00002000      /* SDRAM tRP = 4 cycles */
+#define TRP_5                  0x00002800      /* SDRAM tRP = 5 cycles */
+#define TRP_6                  0x00003000      /* SDRAM tRP = 6 cycles */
+#define TRP_7                  0x00003800      /* SDRAM tRP = 7 cycles */
+#define TRCD_1                 0x00008000      /* SDRAM tRCD = 1 cycle */
+#define TRCD_2                 0x00010000      /* SDRAM tRCD = 2 cycles */
+#define TRCD_3                 0x00018000      /* SDRAM tRCD = 3 cycles */
+#define TRCD_4                 0x00020000      /* SDRAM tRCD = 4 cycles */
+#define TRCD_5                 0x00028000      /* SDRAM tRCD = 5 cycles */
+#define TRCD_6                 0x00030000      /* SDRAM tRCD = 6 cycles */
+#define TRCD_7                 0x00038000      /* SDRAM tRCD = 7 cycles */
+#define TWR_1                  0x00080000      /* SDRAM tWR = 1 cycle */
+#define TWR_2                  0x00100000      /* SDRAM tWR = 2 cycles */
+#define TWR_3                  0x00180000      /* SDRAM tWR = 3 cycles */
+#define PUPSD                  0x00200000      /*Power-up start delay */
+#define PSM                    0x00400000      /* SDRAM power-up sequence = Precharge, mode register set, 8 CBR refresh cycles */
+#define PSS                            0x00800000      /* enable SDRAM power-up sequence on next SDRAM access */
+#define SRFS                   0x01000000      /* Start SDRAM self-refresh mode */
+#define EBUFE                  0x02000000      /* Enable external buffering timing */
+#define FBBRW                  0x04000000      /* Fast back-to-back read write enable */
+#define EMREN                  0x10000000      /* Extended mode register enable */
+#define TCSR                   0x20000000      /* Temp compensated self refresh value 85 deg C */
+#define CDDBG                  0x40000000      /* Tristate SDRAM controls during bus grant */
+
+/* EBIU_SDBCTL Masks */
+#define EBE                    0x00000001      /* Enable SDRAM external bank */
+#define EBSZ_16                        0x00000000      /* SDRAM external bank size = 16MB */
+#define EBSZ_32                        0x00000002      /* SDRAM external bank size = 32MB */
+#define EBSZ_64                        0x00000004      /* SDRAM external bank size = 64MB */
+#define EBSZ_128                       0x00000006      /* SDRAM external bank size = 128MB */
+#define EBCAW_8                        0x00000000      /* SDRAM external bank column address width = 8 bits */
+#define EBCAW_9                        0x00000010      /* SDRAM external bank column address width = 9 bits */
+#define EBCAW_10                       0x00000020      /* SDRAM external bank column address width = 9 bits */
+#define EBCAW_11                       0x00000030      /* SDRAM external bank column address width = 9 bits */
+
+/* EBIU_SDSTAT Masks */
+#define SDCI                   0x00000001      /* SDRAM controller is idle  */
+#define SDSRA                  0x00000002      /* SDRAM SDRAM self refresh is active */
+#define SDPUA                  0x00000004      /* SDRAM power up active  */
+#define SDRS                   0x00000008      /* SDRAM is in reset state */
+#define SDEASE               0x00000010        /* SDRAM EAB sticky error status - W1C */
+#define BGSTAT                 0x00000020      /* Bus granted */
+
+/*VR_CTL Masks*/
+#define WAKE                    0x100
+#define VLEV_6                  0x60
+#define VLEV_7                  0x70
+#define VLEV_8                  0x80
+#define VLEV_9                  0x90
+#define VLEV_10                 0xA0
+#define VLEV_11                 0xB0
+#define VLEV_12                 0xC0
+#define VLEV_13                 0xD0
+#define VLEV_14                 0xE0
+#define VLEV_15                 0xF0
+#define FREQ_3                  0x03
+
+#endif                         /* _DEF_BF532_H */
diff --git a/include/asm-blackfin/mach-bf533/dma.h b/include/asm-blackfin/mach-bf533/dma.h
new file mode 100644 (file)
index 0000000..bd9d5e9
--- /dev/null
@@ -0,0 +1,54 @@
+/*****************************************************************************
+*
+*        BF-533/2/1 Specific Declarations
+*
+****************************************************************************/
+/*
+ * File:         include/asm-blackfin/mach-bf533/dma.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define MAX_BLACKFIN_DMA_CHANNEL 12
+
+#define CH_PPI          0
+#define CH_SPORT0_RX    1
+#define CH_SPORT0_TX    2
+#define CH_SPORT1_RX    3
+#define CH_SPORT1_TX    4
+#define CH_SPI          5
+#define CH_UART_RX      6
+#define CH_UART_TX      7
+#define CH_MEM_STREAM0_DEST     8       /* TX */
+#define CH_MEM_STREAM0_SRC      9       /* RX */
+#define CH_MEM_STREAM1_DEST     10      /* TX */
+#define CH_MEM_STREAM1_SRC      11      /* RX */
+
+#endif
diff --git a/include/asm-blackfin/mach-bf533/irq.h b/include/asm-blackfin/mach-bf533/irq.h
new file mode 100644 (file)
index 0000000..9879e68
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * File:         include/asm-blackfin/mach-bf533/defBF532.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BF533_IRQ_H_
+#define _BF533_IRQ_H_
+
+/*
+ * Interrupt source definitions
+             Event Source    Core Event Name
+Core        Emulation               **
+ Events         (highest priority)  EMU         0
+            Reset                   RST         1
+            NMI                     NMI         2
+            Exception               EVX         3
+            Reserved                --          4
+            Hardware Error          IVHW        5
+            Core Timer              IVTMR       6 *
+           PLL Wakeup Interrupt    IVG7        7
+           DMA Error (generic)     IVG7        8
+           PPI Error Interrupt     IVG7        9
+           SPORT0 Error Interrupt  IVG7        10
+           SPORT1 Error Interrupt  IVG7        11
+           SPI Error Interrupt     IVG7        12
+           UART Error Interrupt    IVG7        13
+           RTC Interrupt           IVG8        14
+           DMA0 Interrupt (PPI)    IVG8        15
+           DMA1 (SPORT0 RX)        IVG9        16
+           DMA2 (SPORT0 TX)        IVG9        17
+           DMA3 (SPORT1 RX)        IVG9        18
+           DMA4 (SPORT1 TX)        IVG9        19
+           DMA5 (PPI)              IVG10       20
+           DMA6 (UART RX)          IVG10       21
+           DMA7 (UART TX)          IVG10       22
+           Timer0                  IVG11       23
+           Timer1                  IVG11       24
+           Timer2                  IVG11       25
+           PF Interrupt A          IVG12       26
+           PF Interrupt B          IVG12       27
+           DMA8/9 Interrupt        IVG13       28
+           DMA10/11 Interrupt      IVG13       29
+           Watchdog Timer          IVG13       30
+            Software Interrupt 1    IVG14       31
+            Software Interrupt 2    --
+                 (lowest priority)  IVG15       32 *
+ */
+#define SYS_IRQS               32
+#define NR_PERI_INTS    24
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define        IRQ_EMU                 0       /*Emulation */
+#define        IRQ_RST                 1       /*reset */
+#define        IRQ_NMI                 2       /*Non Maskable */
+#define        IRQ_EVX                 3       /*Exception */
+#define        IRQ_UNUSED              4       /*- unused interrupt*/
+#define        IRQ_HWERR               5       /*Hardware Error */
+#define        IRQ_CORETMR             6       /*Core timer */
+
+#define        IRQ_PLL_WAKEUP          7       /*PLL Wakeup Interrupt */
+#define        IRQ_DMA_ERROR           8       /*DMA Error (general) */
+#define        IRQ_PPI_ERROR           9       /*PPI Error Interrupt */
+#define        IRQ_SPORT0_ERROR        10      /*SPORT0 Error Interrupt */
+#define        IRQ_SPORT1_ERROR        11      /*SPORT1 Error Interrupt */
+#define        IRQ_SPI_ERROR           12      /*SPI Error Interrupt */
+#define        IRQ_UART_ERROR          13      /*UART Error Interrupt */
+#define        IRQ_RTC                 14      /*RTC Interrupt */
+#define        IRQ_PPI                 15      /*DMA0 Interrupt (PPI) */
+#define        IRQ_SPORT0_RX           16      /*DMA1 Interrupt (SPORT0 RX) */
+#define        IRQ_SPORT0_TX           17      /*DMA2 Interrupt (SPORT0 TX) */
+#define        IRQ_SPORT1_RX           18      /*DMA3 Interrupt (SPORT1 RX) */
+#define        IRQ_SPORT1_TX           19      /*DMA4 Interrupt (SPORT1 TX) */
+#define IRQ_SPI                        20      /*DMA5 Interrupt (SPI) */
+#define        IRQ_UART_RX             21      /*DMA6 Interrupt (UART RX) */
+#define        IRQ_UART_TX             22      /*DMA7 Interrupt (UART TX) */
+#define        IRQ_TMR0                23      /*Timer 0 */
+#define        IRQ_TMR1                24      /*Timer 1 */
+#define        IRQ_TMR2                25      /*Timer 2 */
+#define        IRQ_PROG_INTA           26      /*Programmable Flags A (8) */
+#define        IRQ_PROG_INTB           27      /*Programmable Flags B (8) */
+#define        IRQ_MEM_DMA0            28      /*DMA8/9 Interrupt (Memory DMA Stream 0) */
+#define        IRQ_MEM_DMA1            29      /*DMA10/11 Interrupt (Memory DMA Stream 1) */
+#define        IRQ_WATCH               30      /*Watch Dog Timer */
+
+#define        IRQ_SW_INT1             31      /*Software Int 1 */
+#define        IRQ_SW_INT2             32      /*Software Int 2 (reserved for SYSCALL) */
+
+#define IRQ_PF0                        33
+#define IRQ_PF1                        34
+#define IRQ_PF2                        35
+#define IRQ_PF3                        36
+#define IRQ_PF4                        37
+#define IRQ_PF5                        38
+#define IRQ_PF6                        39
+#define IRQ_PF7                        40
+#define IRQ_PF8                        41
+#define IRQ_PF9                        42
+#define IRQ_PF10               43
+#define IRQ_PF11               44
+#define IRQ_PF12               45
+#define IRQ_PF13               46
+#define IRQ_PF14               47
+#define IRQ_PF15               48
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define        NR_IRQS         (IRQ_PF15+1)
+#else
+#define        NR_IRQS         SYS_IRQS
+#endif
+
+#define IVG7                   7
+#define IVG8                   8
+#define IVG9                   9
+#define IVG10                  10
+#define IVG11                  11
+#define IVG12                  12
+#define IVG13                  13
+#define IVG14                  14
+#define IVG15                  15
+
+/* IAR0 BIT FIELDS*/
+#define RTC_ERROR_POS                  28
+#define UART_ERROR_POS                 24
+#define SPORT1_ERROR_POS               20
+#define SPI_ERROR_POS                  16
+#define SPORT0_ERROR_POS               12
+#define PPI_ERROR_POS                  8
+#define DMA_ERROR_POS                  4
+#define PLLWAKE_ERROR_POS              0
+
+/* IAR1 BIT FIELDS*/
+#define DMA7_UARTTX_POS                        28
+#define DMA6_UARTRX_POS                        24
+#define DMA5_SPI_POS                   20
+#define DMA4_SPORT1TX_POS              16
+#define DMA3_SPORT1RX_POS              12
+#define DMA2_SPORT0TX_POS              8
+#define DMA1_SPORT0RX_POS              4
+#define DMA0_PPI_POS                   0
+
+/* IAR2 BIT FIELDS*/
+#define WDTIMER_POS                    28
+#define MEMDMA1_POS                    24
+#define MEMDMA0_POS                    20
+#define PFB_POS                                16
+#define PFA_POS                                12
+#define TIMER2_POS                     8
+#define TIMER1_POS                     4
+#define TIMER0_POS                     0
+
+#endif                         /* _BF533_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf533/mem_init.h b/include/asm-blackfin/mach-bf533/mem_init.h
new file mode 100644 (file)
index 0000000..1620dae
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * File:         include/asm-blackfin/mach-bf533/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_GENERIC_BOARD)
+#if (CONFIG_SCLK_HZ > 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_7
+#define SDRAM_tRAS_num  7
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_6
+#define SDRAM_tRAS_num  6
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 8955223) && (CONFIG_SCLK_HZ <= 104477612)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_5
+#define SDRAM_tRAS_num  5
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  4
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_2
+#define SDRAM_tRAS_num  2
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ <= 29850746)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_1
+#define SDRAM_tRAS_num  1
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#endif
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_GENERIC_BOARD)
+  /*SDRAM INFORMATION: Modify this for your board */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_SIZE == 128)
+#define SDRAM_SIZE      EBSZ_128
+#endif
+#if (CONFIG_MEM_SIZE == 64)
+#define SDRAM_SIZE      EBSZ_64
+#endif
+#if (CONFIG_MEM_SIZE == 32)
+#define SDRAM_SIZE      EBSZ_32
+#endif
+#if (CONFIG_MEM_SIZE == 16)
+#define SDRAM_SIZE      EBSZ_16
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 11)
+#define SDRAM_WIDTH     EBCAW_11
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 10)
+#define SDRAM_WIDTH     EBCAW_10
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 9)
+#define SDRAM_WIDTH     EBCAW_9
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 8)
+#define SDRAM_WIDTH     EBCAW_8
+#endif
+
+#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EBE)
+
+/* Equation from section 17 (p17-46) of BF533 HRM */
+#define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref)  / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
+
+/* Enable SCLK Out */
+#define mem_SDGCTL        (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF       1
+#else
+#define CLKIN_HALF       0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS      1
+#else
+#define PLL_BYPASS       0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT  ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT  ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT   ((CONFIG_FLASH_SPEED_BHT  * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST   ((CONFIG_FLASH_SPEED_BST  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT   ((CONFIG_FLASH_SPEED_BTT  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0  \
+       (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+        flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf533/mem_map.h b/include/asm-blackfin/mach-bf533/mem_map.h
new file mode 100644 (file)
index 0000000..e84baa3
--- /dev/null
@@ -0,0 +1,168 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf533/mem_map.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MEM_MAP_533_H_
+#define _MEM_MAP_533_H_
+
+#define COREMMR_BASE           0xFFE00000       /* Core MMRs */
+#define SYSMMR_BASE            0xFFC00000       /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE       0x20300000       /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE       0x00100000      /* 1M */
+#define ASYNC_BANK2_BASE       0x20200000       /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE       0x00100000      /* 1M */
+#define ASYNC_BANK1_BASE       0x20100000       /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE       0x00100000      /* 1M */
+#define ASYNC_BANK0_BASE       0x20000000       /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE       0x00100000      /* 1M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START         0xEF000000
+
+/* Level 1 Memory */
+
+#ifdef CONFIG_BLKFIN_CACHE
+#define BLKFIN_ICACHESIZE      (16*1024)
+#else
+#define BLKFIN_ICACHESIZE      (0*1024)
+#endif
+
+/* Memory Map for ADSP-BF533 processors */
+
+#ifdef CONFIG_BF533
+#define L1_CODE_START       0xFFA00000
+#define L1_DATA_A_START     0xFF800000
+#define L1_DATA_B_START     0xFF900000
+
+#ifdef CONFIG_BLKFIN_CACHE
+#define L1_CODE_LENGTH      (0x14000 - 0x4000)
+#else
+#define L1_CODE_LENGTH      0x14000
+#endif
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x8000
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+#endif
+
+/* Memory Map for ADSP-BF532 processors */
+
+#ifdef CONFIG_BF532
+#define L1_CODE_START       0xFFA08000
+#define L1_DATA_A_START     0xFF804000
+#define L1_DATA_B_START     0xFF904000
+
+#ifdef CONFIG_BLKFIN_CACHE
+#define L1_CODE_LENGTH      (0xC000 - 0x4000)
+#else
+#define L1_CODE_LENGTH      0xC000
+#endif
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x4000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x4000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x4000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x4000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x4000
+#define L1_DATA_B_LENGTH      0x4000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+#endif
+
+/* Memory Map for ADSP-BF531 processors */
+
+#ifdef CONFIG_BF531
+#define L1_CODE_START       0xFFA08000
+#define L1_DATA_A_START     0xFF804000
+#define L1_DATA_B_START     0xFF904000
+#define L1_CODE_LENGTH      0x4000
+#define L1_DATA_B_LENGTH      0x0000
+
+
+#ifdef CONFIG_BLKFIN_DCACHE
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB  | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x4000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB  | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x4000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif
+
+#endif
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF533) || defined(CONFIG_BF532) || defined(CONFIG_BF531)
+#define L1_SCRATCH_START       0xFFB00000
+#define L1_SCRATCH_LENGTH      0x1000
+#endif
+
+#endif                         /* _MEM_MAP_533_H_ */
diff --git a/include/asm-blackfin/mach-bf537/anomaly.h b/include/asm-blackfin/mach-bf537/anomaly.h
new file mode 100644 (file)
index 0000000..7f040f5
--- /dev/null
@@ -0,0 +1,120 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf537/anomaly.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This file shoule be up to date with:
+ *  - Revision J, June 1, 2006; ADSP-BF537 Blackfin Processor Anomaly List
+ *  - Revision I, June 1, 2006; ADSP-BF536 Blackfin Processor Anomaly List
+ *  - Revision J, June 1, 2006; ADSP-BF534 Blackfin Processor Anomaly List
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+
+/* We do not support 0.1 silicon - sorry */
+#if (defined(CONFIG_BF_REV_0_1))
+#error Kernel will not work on BF537/6/4 Version 0.1
+#endif
+
+#if (defined(CONFIG_BF_REV_0_3) || defined(CONFIG_BF_REV_0_2))
+#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
+                            slot1 and store of a P register in slot 2 is not
+                            supported */
+#define ANOMALY_05000119 /* DMA_RUN bit is not valid after a Peripheral Receive
+                            Channel DMA stops */
+#define ANOMALY_05000122 /* Rx.H can not be used to access 16-bit System MMR
+                            registers. */
+#define ANOMALY_05000166 /* PPI Data Lengths Between 8 and 16 do not zero out
+                            upper bits*/
+#define ANOMALY_05000180 /* PPI_DELAY not functional in PPI modes with 0 frame
+                            syncs */
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
+#define ANOMALY_05000247 /* CLKIN Buffer Output Enable Reset Behavior Is
+                            Changed */
+#endif
+#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on
+                            SPORT external receive and transmit clocks. */
+#define ANOMALY_05000272 /* Certain data cache write through modes fail for
+                            VDDint <=0.9V */
+#define ANOMALY_05000273 /* Writes to Synchronous SDRAM memory may be lost */
+#define ANOMALY_05000277 /* Writes to a flag data register one SCLK cycle after
+                            an edge is detected may clear interrupt */
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context is
+                            not restored */
+#define ANOMALY_05000282 /* Memory DMA corruption with 32-bit data and traffic
+                            control */
+#define ANOMALY_05000283 /* A system MMR write is stalled indefinitely when
+                            killed in a particular stage*/
+#define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
+                           registers are interrupted */
+#endif
+
+#if defined(CONFIG_BF_REV_0_2)
+#define ANOMALY_05000244 /* With instruction cache enabled, a CSYNC or SSYNC or
+                            IDLE around a Change of Control causes
+                            unpredictable results */
+#define ANOMALY_05000250 /* Incorrect Bit-Shift of Data Word in Multichannel
+                            (TDM) */
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
+#define ANOMALY_05000252 /* EMAC Tx DMA error after an early frame abort */
+#endif
+#define ANOMALY_05000253 /* Maximum external clock speed for Timers */
+#define ANOMALY_05000255 /* Entering Hibernate Mode with RTC Seconds event
+                            interrupt not functional */
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
+#define ANOMALY_05000256 /* EMAC MDIO input latched on wrong MDC edge */
+#endif
+#define ANOMALY_05000257 /* An interrupt or exception during short Hardware
+                            loops may cause the instruction fetch unit to
+                            malfunction */
+#define ANOMALY_05000258 /* Instruction Cache is corrupted when bit 9 and 12 of
+                            the ICPLB Data registers differ */
+#define ANOMALY_05000260 /* ICPLB_STATUS MMR register may be corrupted */
+#define ANOMALY_05000261 /* DCPLB_FAULT_ADDR MMR register may be corrupted */
+#define ANOMALY_05000262 /* Stores to data cache may be lost */
+#define ANOMALY_05000263 /* Hardware loop corrupted when taking an ICPLB exception */
+#define ANOMALY_05000264 /* A Sync instruction (CSYNC, SSYNC) or an IDLE
+                            instruction will cause an infinite stall in the
+                            second to last instruction in a hardware loop */
+#define ANOMALY_05000268 /* Memory DMA error when peripheral DMA is running
+                            and non-zero DEB_TRAFFIC_PERIOD value */
+#define ANOMALY_05000270 /* High I/O activity causes the output voltage of the
+                            internal voltage regulator (VDDint) to decrease */
+#define ANOMALY_05000277 /* Writes to a flag data register one SCLK cycle after
+                            an edge is detected may clear interrupt */
+#define ANOMALY_05000278 /* Disabling Peripherals with DMA running may cause
+                            DMA system instability */
+#define ANOMALY_05000280 /* SPI Master boot mode does not work well with
+                            Atmel Dataflash devices */
+
+#endif  /* CONFIG_BF_REV_0_2 */
+
+#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf537/bf537.h b/include/asm-blackfin/mach-bf537/bf537.h
new file mode 100644 (file)
index 0000000..b8924cd
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * File:         include/asm-blackfin/mach-bf537/bf537.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF537
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __MACH_BF537_H__
+#define __MACH_BF537_H__
+
+#define SUPPORTED_REVID 2
+
+/* Masks for generic ERROR IRQ demultiplexing used in int-priority-sc.c */
+
+#define SPI_ERR_MASK (TXCOL | RBSY | MODF | TXE)       /* SPI_STAT */
+#define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF)     /* SPORTx_STAT */
+#define PPI_ERR_MASK (0xFFFF & ~FLD)   /* PPI_STATUS */
+#define EMAC_ERR_MASK (PHYINT | MMCINT | RXFSINT | TXFSINT | WAKEDET | RXDMAERR | TXDMAERR | STMDONE)  /* EMAC_SYSTAT */
+#define UART_ERR_MASK_STAT1 (0x4)      /* UARTx_IIR */
+#define UART_ERR_MASK_STAT0 (0x2)      /* UARTx_IIR */
+#define CAN_ERR_MASK  (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | RMLIF | UCEIF | EXTIF | ADIF)       /* CAN_GIF */
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15            0x8000
+#define IMASK_IVG14            0x4000
+#define IMASK_IVG13            0x2000
+#define IMASK_IVG12            0x1000
+
+#define IMASK_IVG11            0x0800
+#define IMASK_IVG10            0x0400
+#define IMASK_IVG9             0x0200
+#define IMASK_IVG8             0x0100
+
+#define IMASK_IVG7             0x0080
+#define IMASK_IVGTMR   0x0040
+#define IMASK_IVGHW            0x0020
+
+/***************************/
+
+
+#define BLKFIN_DSUBBANKS       4
+#define BLKFIN_DWAYS           2
+#define BLKFIN_DLINES          64
+#define BLKFIN_ISUBBANKS       4
+#define BLKFIN_IWAYS           4
+#define BLKFIN_ILINES          32
+
+#define WAY0_L                 0x1
+#define WAY1_L                 0x2
+#define WAY01_L                        0x3
+#define WAY2_L                 0x4
+#define WAY02_L                        0x5
+#define        WAY12_L                 0x6
+#define        WAY012_L                0x7
+
+#define        WAY3_L                  0x8
+#define        WAY03_L                 0x9
+#define        WAY13_L                 0xA
+#define        WAY013_L                0xB
+
+#define        WAY32_L                 0xC
+#define        WAY320_L                0xD
+#define        WAY321_L                0xE
+#define        WAYALL_L                0xF
+
+#define DMC_ENABLE (2<<2)      /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL     ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL     ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+#ifdef CONFIG_C_CDPRIO
+#define V_CDPRIO 0x100
+#else
+#define V_CDPRIO 0x0
+#endif
+
+#define AMGCTLVAL      (V_AMBEN | V_AMCKEN | V_CDPRIO)
+
+#define MAX_VC 650000000
+#define MIN_VC 50000000
+
+/********************************PLL Settings **************************************/
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
+#if (CONFIG_VCO_MULT < 0)
+#error "VCO Multiplier is less than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT == 0)
+#error "VCO Multiplier should be greater than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT > 64)
+#error "VCO Multiplier is more than 64. Please select a different value"
+#endif
+
+#ifndef CONFIG_CLKIN_HALF
+#define CONFIG_VCO_HZ  (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)
+#else
+#define CONFIG_VCO_HZ  ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2)
+#endif
+
+#ifndef CONFIG_PLL_BYPASS
+#define CONFIG_CCLK_HZ (CONFIG_VCO_HZ/CONFIG_CCLK_DIV)
+#define CONFIG_SCLK_HZ (CONFIG_VCO_HZ/CONFIG_SCLK_DIV)
+#else
+#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ
+#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ
+#endif
+
+#if (CONFIG_SCLK_DIV < 1)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_SCLK_DIV > 15)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_CCLK_DIV != 1)
+#if (CONFIG_CCLK_DIV != 2)
+#if (CONFIG_CCLK_DIV != 4)
+#if (CONFIG_CCLK_DIV != 8)
+#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value"
+#endif
+#endif
+#endif
+#endif
+
+#if (CONFIG_VCO_HZ > MAX_VC)
+#error "VCO selected is more than maximum value. Please change the VCO multipler"
+#endif
+
+#if (CONFIG_SCLK_HZ > 133000000)
+#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ < 27000000)
+#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ >= CONFIG_CCLK_HZ)
+#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ)
+#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ)
+#error "Please select sclk less than cclk"
+#endif
+#endif
+#endif
+
+#if (CONFIG_CCLK_DIV == 1)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV1
+#endif
+#if (CONFIG_CCLK_DIV == 2)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV2
+#endif
+#if (CONFIG_CCLK_DIV == 4)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV4
+#endif
+#if (CONFIG_CCLK_DIV == 8)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV8
+#endif
+#ifndef CONFIG_CCLK_ACT_DIV
+#define CONFIG_CCLK_ACT_DIV   CONFIG_CCLK_DIV_not_defined_properly
+#endif
+
+#if defined(ANOMALY_05000273) && (CONFIG_CCLK_DIV == 1)
+#error ANOMALY 05000273, please make sure CCLK is at least 2x SCLK
+#endif
+
+#endif                         /* CONFIG_BFIN_KERNEL_CLOCK */
+
+#ifdef CONFIG_BF537
+#define CPU "BF537"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF536
+#define CPU "BF536"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF534
+#define CPU "BF534"
+#define CPUID 0x027c6000
+#endif
+#ifndef CPU
+#define        CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#if (CONFIG_MEM_SIZE % 4)
+#error "SDRAM mem size must be multible of 4MB"
+#endif
+
+#define SDRAM_IGENERIC    (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
+#define SDRAM_IKERNEL     (SDRAM_IGENERIC | CPLB_LOCK)
+#define L1_IMEMORY        (               CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
+#define SDRAM_INON_CHBL   (               CPLB_USER_RD | CPLB_VALID)
+
+/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/
+
+#define ANOMALY_05000158_WORKAROUND            0x200
+#ifdef CONFIG_BLKFIN_WB                /*Write Back Policy */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_DIRTY \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#else                          /*Write Through */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#endif
+
+
+#define L1_DMEMORY       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+#define SDRAM_DNON_CHBL  (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_EBIU       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_OOPS      (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+
+#define SIZE_1K 0x00000400     /* 1K */
+#define SIZE_4K 0x00001000     /* 4K */
+#define SIZE_1M 0x00100000     /* 1M */
+#define SIZE_4M 0x00400000     /* 4M */
+
+#define MAX_CPLBS (16 * 2)
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 1 for ASYNC Memory
+*/
+
+
+#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+
+#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1) * 2)
+
+#endif                         /* __MACH_BF537_H__  */
diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
new file mode 100644 (file)
index 0000000..8f5d9c4
--- /dev/null
@@ -0,0 +1,147 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+
+#define NR_PORTS               2
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
+
+#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+#define UART_GET_DLH(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
+#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
+#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
+#define UART_PUT_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER),v)
+#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
+#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+#  define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+#  define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+#  define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+#  define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+        struct uart_port        port;
+        unsigned int            old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       int                     tx_done;
+       int                     tx_count;
+       struct circ_buf         rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+       struct work_struct      tx_dma_workqueue;
+#else
+       struct work_struct      cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int             cts_pin;
+       int             rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+       unsigned long   uart_base_addr;
+       int             uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       unsigned int    uart_tx_dma_channel;
+       unsigned int    uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int     uart_cts_pin;
+       int     uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       {
+       0xFFC00400,
+       IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART0_TX,
+       CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+       CONFIG_UART0_CTS_PIN,
+       CONFIG_UART0_RTS_PIN,
+#endif
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       {
+       0xFFC02000,
+       IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART1_TX,
+       CH_UART1_RX,
+#endif
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+       CONFIG_UART1_CTS_PIN,
+       CONFIG_UART1_RTS_PIN,
+#endif
+       },
+#endif
+};
+
+int nr_ports = ARRAY_SIZE(bfin_serial_resource);
+
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+       unsigned short val;
+       val = bfin_read16(BFIN_PORT_MUX);
+       val &= ~(PFDE | PFTE);
+       bfin_write16(BFIN_PORT_MUX, val);
+
+       val = bfin_read16(PORTF_FER);
+       val |= 0xF;
+       bfin_write16(PORTF_FER, val);
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       if (uart->cts_pin >= 0) {
+               gpio_request(uart->cts_pin, NULL);
+               gpio_direction_input(uart->cts_pin);
+       }
+
+       if (uart->rts_pin >= 0) {
+               gpio_request(uart->rts_pin, NULL);
+               gpio_direction_output(uart->rts_pin);
+       }
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf537/blackfin.h b/include/asm-blackfin/mach-bf537/blackfin.h
new file mode 100644 (file)
index 0000000..bbd9705
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * File:         include/asm-blackfin/mach-bf537/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF537_FAMILY
+
+#include "bf537.h"
+#include "mem_map.h"
+#include "defBF534.h"
+#include "anomaly.h"
+
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536)
+#include "defBF537.h"
+#endif
+
+#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY))
+#include "cdefBF534.h"
+
+/* UART 0*/
+#define bfin_read_UART_THR() bfin_read_UART0_THR()
+#define bfin_write_UART_THR(val) bfin_write_UART0_THR(val)
+#define bfin_read_UART_RBR() bfin_read_UART0_RBR()
+#define bfin_write_UART_RBR(val) bfin_write_UART0_RBR(val)
+#define bfin_read_UART_DLL() bfin_read_UART0_DLL()
+#define bfin_write_UART_DLL(val) bfin_write_UART0_DLL(val)
+#define bfin_read_UART_IER() bfin_read_UART0_IER()
+#define bfin_write_UART_IER(val) bfin_write_UART0_IER(val)
+#define bfin_read_UART_DLH() bfin_read_UART0_DLH()
+#define bfin_write_UART_DLH(val) bfin_write_UART0_DLH(val)
+#define bfin_read_UART_IIR() bfin_read_UART0_IIR()
+#define bfin_write_UART_IIR(val) bfin_write_UART0_IIR(val)
+#define bfin_read_UART_LCR() bfin_read_UART0_LCR()
+#define bfin_write_UART_LCR(val) bfin_write_UART0_LCR(val)
+#define bfin_read_UART_MCR() bfin_read_UART0_MCR()
+#define bfin_write_UART_MCR(val) bfin_write_UART0_MCR(val)
+#define bfin_read_UART_LSR() bfin_read_UART0_LSR()
+#define bfin_write_UART_LSR(val) bfin_write_UART0_LSR(val)
+#define bfin_read_UART_SCR() bfin_read_UART0_SCR()
+#define bfin_write_UART_SCR(val) bfin_write_UART0_SCR(val)
+#define bfin_read_UART_GCTL() bfin_read_UART0_GCTL()
+#define bfin_write_UART_GCTL(val) bfin_write_UART0_GCTL(val)
+
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536)
+#include "cdefBF537.h"
+#endif
+#endif
+
+/* MAP used DEFINES from BF533 to BF537 - so we don't need to change them in the driver, kernel, etc. */
+
+/* UART_IIR Register */
+#define STATUS(x)      ((x << 1) & 0x06)
+#define STATUS_P1      0x02
+#define STATUS_P0      0x01
+
+/* UART 0*/
+
+/* DMA Channnel */
+#define bfin_read_CH_UART_RX() bfin_read_CH_UART0_RX()
+#define bfin_write_CH_UART_RX(val) bfin_write_CH_UART0_RX(val)
+#define CH_UART_RX CH_UART0_RX
+#define bfin_read_CH_UART_TX() bfin_read_CH_UART0_TX()
+#define bfin_write_CH_UART_TX(val) bfin_write_CH_UART0_TX(val)
+#define CH_UART_TX CH_UART0_TX
+
+/* System Interrupt Controller */
+#define bfin_read_IRQ_UART_RX() bfin_read_IRQ_UART0_RX()
+#define bfin_write_IRQ_UART_RX(val) bfin_write_IRQ_UART0_RX(val)
+#define IRQ_UART_RX IRQ_UART0_RX
+#define bfin_read_IRQ_UART_TX() bfin_read_IRQ_UART0_TX()
+#define bfin_write_IRQ_UART_TX(val) bfin_write_IRQ_UART0_TX(val)
+#define        IRQ_UART_TX IRQ_UART0_TX
+#define bfin_read_IRQ_UART_ERROR() bfin_read_IRQ_UART0_ERROR()
+#define bfin_write_IRQ_UART_ERROR(val) bfin_write_IRQ_UART0_ERROR(val)
+#define        IRQ_UART_ERROR IRQ_UART0_ERROR
+
+/* MMR Registers*/
+#define bfin_read_UART_THR() bfin_read_UART0_THR()
+#define bfin_write_UART_THR(val) bfin_write_UART0_THR(val)
+#define UART_THR UART0_THR
+#define bfin_read_UART_RBR() bfin_read_UART0_RBR()
+#define bfin_write_UART_RBR(val) bfin_write_UART0_RBR(val)
+#define UART_RBR UART0_RBR
+#define bfin_read_UART_DLL() bfin_read_UART0_DLL()
+#define bfin_write_UART_DLL(val) bfin_write_UART0_DLL(val)
+#define UART_DLL UART0_DLL
+#define bfin_read_UART_IER() bfin_read_UART0_IER()
+#define bfin_write_UART_IER(val) bfin_write_UART0_IER(val)
+#define UART_IER UART0_IER
+#define bfin_read_UART_DLH() bfin_read_UART0_DLH()
+#define bfin_write_UART_DLH(val) bfin_write_UART0_DLH(val)
+#define UART_DLH UART0_DLH
+#define bfin_read_UART_IIR() bfin_read_UART0_IIR()
+#define bfin_write_UART_IIR(val) bfin_write_UART0_IIR(val)
+#define UART_IIR UART0_IIR
+#define bfin_read_UART_LCR() bfin_read_UART0_LCR()
+#define bfin_write_UART_LCR(val) bfin_write_UART0_LCR(val)
+#define UART_LCR UART0_LCR
+#define bfin_read_UART_MCR() bfin_read_UART0_MCR()
+#define bfin_write_UART_MCR(val) bfin_write_UART0_MCR(val)
+#define UART_MCR UART0_MCR
+#define bfin_read_UART_LSR() bfin_read_UART0_LSR()
+#define bfin_write_UART_LSR(val) bfin_write_UART0_LSR(val)
+#define UART_LSR UART0_LSR
+#define bfin_read_UART_SCR() bfin_read_UART0_SCR()
+#define bfin_write_UART_SCR(val) bfin_write_UART0_SCR(val)
+#define UART_SCR  UART0_SCR
+#define bfin_read_UART_GCTL() bfin_read_UART0_GCTL()
+#define bfin_write_UART_GCTL(val) bfin_write_UART0_GCTL(val)
+#define UART_GCTL UART0_GCTL
+
+/* DPMC*/
+#define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+#define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
+#define STOPCK_OFF STOPCK
+
+/* FIO USE PORT F*/
+#ifdef CONFIG_BF537_PORT_F
+#define bfin_read_PORT_FER() bfin_read_PORTF_FER()
+#define bfin_write_PORT_FER(val) bfin_write_PORTF_FER(val)
+#define bfin_read_FIO_FLAG_D() bfin_read_PORTFIO()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_PORTFIO(val)
+#define bfin_read_FIO_FLAG_C() bfin_read_PORTFIO_CLEAR()
+#define bfin_write_FIO_FLAG_C(val) bfin_write_PORTFIO_CLEAR(val)
+#define bfin_read_FIO_FLAG_S() bfin_read_PORTFIO_SET()
+#define bfin_write_FIO_FLAG_S(val) bfin_write_PORTFIO_SET(val)
+#define bfin_read_FIO_FLAG_T() bfin_read_PORTFIO_TOGGLE()
+#define bfin_write_FIO_FLAG_T(val) bfin_write_PORTFIO_TOGGLE(val)
+#define bfin_read_FIO_MASKA_D() bfin_read_PORTFIO_MASKA()
+#define bfin_write_FIO_MASKA_D(val) bfin_write_PORTFIO_MASKA(val)
+#define bfin_read_FIO_MASKA_C() bfin_read_PORTFIO_MASKA_CLEAR()
+#define bfin_write_FIO_MASKA_C(val) bfin_write_PORTFIO_MASKA_CLEAR(val)
+#define bfin_read_FIO_MASKA_S() bfin_read_PORTFIO_MASKA_SET()
+#define bfin_write_FIO_MASKA_S(val) bfin_write_PORTFIO_MASKA_SET(val)
+#define bfin_read_FIO_MASKA_T() bfin_read_PORTFIO_MASKA_TOGGLE()
+#define bfin_write_FIO_MASKA_T(val) bfin_write_PORTFIO_MASKA_TOGGLE(val)
+#define bfin_read_FIO_MASKB_D() bfin_read_PORTFIO_MASKB()
+#define bfin_write_FIO_MASKB_D(val) bfin_write_PORTFIO_MASKB(val)
+#define bfin_read_FIO_MASKB_C() bfin_read_PORTFIO_MASKB_CLEAR()
+#define bfin_write_FIO_MASKB_C(val) bfin_write_PORTFIO_MASKB_CLEAR(val)
+#define bfin_read_FIO_MASKB_S() bfin_read_PORTFIO_MASKB_SET()
+#define bfin_write_FIO_MASKB_S(val) bfin_write_PORTFIO_MASKB_SET(val)
+#define bfin_read_FIO_MASKB_T() bfin_read_PORTFIO_MASKB_TOGGLE()
+#define bfin_write_FIO_MASKB_T(val) bfin_write_PORTFIO_MASKB_TOGGLE(val)
+#define bfin_read_FIO_DIR() bfin_read_PORTFIO_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_PORTFIO_DIR(val)
+#define bfin_read_FIO_POLAR() bfin_read_PORTFIO_POLAR()
+#define bfin_write_FIO_POLAR(val) bfin_write_PORTFIO_POLAR(val)
+#define bfin_read_FIO_EDGE() bfin_read_PORTFIO_EDGE()
+#define bfin_write_FIO_EDGE(val) bfin_write_PORTFIO_EDGE(val)
+#define bfin_read_FIO_BOTH() bfin_read_PORTFIO_BOTH()
+#define bfin_write_FIO_BOTH(val) bfin_write_PORTFIO_BOTH(val)
+#define bfin_read_FIO_INEN() bfin_read_PORTFIO_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_PORTFIO_INEN(val)
+
+#define bfin_read_FIO_FLAG_D() bfin_read_PORTFIO()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_PORTFIO(val)
+#define FIO_FLAG_D             PORTFIO
+#define bfin_read_FIO_FLAG_C() bfin_read_PORTFIO_CLEAR()
+#define bfin_write_FIO_FLAG_C(val) bfin_write_PORTFIO_CLEAR(val)
+#define FIO_FLAG_C             PORTFIO_CLEAR
+#define bfin_read_FIO_FLAG_S() bfin_read_PORTFIO_SET()
+#define bfin_write_FIO_FLAG_S(val) bfin_write_PORTFIO_SET(val)
+#define FIO_FLAG_S             PORTFIO_SET
+#define bfin_read_FIO_FLAG_T() bfin_read_PORTFIO_TOGGLE()
+#define bfin_write_FIO_FLAG_T(val) bfin_write_PORTFIO_TOGGLE(val)
+#define FIO_FLAG_T             PORTFIO_TOGGLE
+#define bfin_read_FIO_MASKA_D() bfin_read_PORTFIO_MASKA()
+#define bfin_write_FIO_MASKA_D(val) bfin_write_PORTFIO_MASKA(val)
+#define FIO_MASKA_D        PORTFIO_MASKA
+#define bfin_read_FIO_MASKA_C() bfin_read_PORTFIO_MASKA_CLEAR()
+#define bfin_write_FIO_MASKA_C(val) bfin_write_PORTFIO_MASKA_CLEAR(val)
+#define FIO_MASKA_C     PORTFIO_MASKA_CLEAR
+#define bfin_read_FIO_MASKA_S() bfin_read_PORTFIO_MASKA_SET()
+#define bfin_write_FIO_MASKA_S(val) bfin_write_PORTFIO_MASKA_SET(val)
+#define FIO_MASKA_S     PORTFIO_MASKA_SET
+#define bfin_read_FIO_MASKA_T() bfin_read_PORTFIO_MASKA_TOGGLE()
+#define bfin_write_FIO_MASKA_T(val) bfin_write_PORTFIO_MASKA_TOGGLE(val)
+#define FIO_MASKA_T     PORTFIO_MASKA_TOGGLE
+#define bfin_read_FIO_MASKB_D() bfin_read_PORTFIO_MASKB()
+#define bfin_write_FIO_MASKB_D(val) bfin_write_PORTFIO_MASKB(val)
+#define FIO_MASKB_D     PORTFIO_MASKB
+#define bfin_read_FIO_MASKB_C() bfin_read_PORTFIO_MASKB_CLEAR()
+#define bfin_write_FIO_MASKB_C(val) bfin_write_PORTFIO_MASKB_CLEAR(val)
+#define FIO_MASKB_C     PORTFIO_MASKB_CLEAR
+#define bfin_read_FIO_MASKB_S() bfin_read_PORTFIO_MASKB_SET()
+#define bfin_write_FIO_MASKB_S(val) bfin_write_PORTFIO_MASKB_SET(val)
+#define FIO_MASKB_S     PORTFIO_MASKB_SET
+#define bfin_read_FIO_MASKB_T() bfin_read_PORTFIO_MASKB_TOGGLE()
+#define bfin_write_FIO_MASKB_T(val) bfin_write_PORTFIO_MASKB_TOGGLE(val)
+#define FIO_MASKB_T     PORTFIO_MASKB_TOGGLE
+#define bfin_read_FIO_DIR() bfin_read_PORTFIO_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_PORTFIO_DIR(val)
+#define FIO_DIR                    PORTFIO_DIR
+#define bfin_read_FIO_POLAR() bfin_read_PORTFIO_POLAR()
+#define bfin_write_FIO_POLAR(val) bfin_write_PORTFIO_POLAR(val)
+#define FIO_POLAR              PORTFIO_POLAR
+#define bfin_read_FIO_EDGE() bfin_read_PORTFIO_EDGE()
+#define bfin_write_FIO_EDGE(val) bfin_write_PORTFIO_EDGE(val)
+#define FIO_EDGE               PORTFIO_EDGE
+#define bfin_read_FIO_BOTH() bfin_read_PORTFIO_BOTH()
+#define bfin_write_FIO_BOTH(val) bfin_write_PORTFIO_BOTH(val)
+#define FIO_BOTH               PORTFIO_BOTH
+#define bfin_read_FIO_INEN() bfin_read_PORTFIO_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_PORTFIO_INEN(val)
+#define FIO_INEN               PORTFIO_INEN
+#endif
+
+/* FIO USE PORT G*/
+#ifdef CONFIG_BF537_PORT_G
+#define bfin_read_PORT_FER() bfin_read_PORTG_FER()
+#define bfin_write_PORT_FER(val) bfin_write_PORTG_FER(val)
+#define bfin_read_FIO_FLAG_D() bfin_read_PORTGIO()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_PORTGIO(val)
+#define bfin_read_FIO_FLAG_C() bfin_read_PORTGIO_CLEAR()
+#define bfin_write_FIO_FLAG_C(val) bfin_write_PORTGIO_CLEAR(val)
+#define bfin_read_FIO_FLAG_S() bfin_read_PORTGIO_SET()
+#define bfin_write_FIO_FLAG_S(val) bfin_write_PORTGIO_SET(val)
+#define bfin_read_FIO_FLAG_T() bfin_read_PORTGIO_TOGGLE()
+#define bfin_write_FIO_FLAG_T(val) bfin_write_PORTGIO_TOGGLE(val)
+#define bfin_read_FIO_MASKA_D() bfin_read_PORTGIO_MASKA()
+#define bfin_write_FIO_MASKA_D(val) bfin_write_PORTGIO_MASKA(val)
+#define bfin_read_FIO_MASKA_C() bfin_read_PORTGIO_MASKA_CLEAR()
+#define bfin_write_FIO_MASKA_C(val) bfin_write_PORTGIO_MASKA_CLEAR(val)
+#define bfin_read_FIO_MASKA_S() bfin_read_PORTGIO_MASKA_SET()
+#define bfin_write_FIO_MASKA_S(val) bfin_write_PORTGIO_MASKA_SET(val)
+#define bfin_read_FIO_MASKA_T() bfin_read_PORTGIO_MASKA_TOGGLE()
+#define bfin_write_FIO_MASKA_T(val) bfin_write_PORTGIO_MASKA_TOGGLE(val)
+#define bfin_read_FIO_MASKB_D() bfin_read_PORTGIO_MASKB()
+#define bfin_write_FIO_MASKB_D(val) bfin_write_PORTGIO_MASKB(val)
+#define bfin_read_FIO_MASKB_C() bfin_read_PORTGIO_MASKB_CLEAR()
+#define bfin_write_FIO_MASKB_C(val) bfin_write_PORTGIO_MASKB_CLEAR(val)
+#define bfin_read_FIO_MASKB_S() bfin_read_PORTGIO_MASKB_SET()
+#define bfin_write_FIO_MASKB_S(val) bfin_write_PORTGIO_MASKB_SET(val)
+#define bfin_read_FIO_MASKB_T() bfin_read_PORTGIO_MASKB_TOGGLE()
+#define bfin_write_FIO_MASKB_T(val) bfin_write_PORTGIO_MASKB_TOGGLE(val)
+#define bfin_read_FIO_DIR() bfin_read_PORTGIO_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_PORTGIO_DIR(val)
+#define bfin_read_FIO_POLAR() bfin_read_PORTGIO_POLAR()
+#define bfin_write_FIO_POLAR(val) bfin_write_PORTGIO_POLAR(val)
+#define bfin_read_FIO_EDGE() bfin_read_PORTGIO_EDGE()
+#define bfin_write_FIO_EDGE(val) bfin_write_PORTGIO_EDGE(val)
+#define bfin_read_FIO_BOTH() bfin_read_PORTGIO_BOTH()
+#define bfin_write_FIO_BOTH(val) bfin_write_PORTGIO_BOTH(val)
+#define bfin_read_FIO_INEN() bfin_read_PORTGIO_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_PORTGIO_INEN(val)
+
+#define bfin_read_FIO_FLAG_D() bfin_read_PORTGIO()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_PORTGIO(val)
+#define FIO_FLAG_D             PORTGIO
+#define bfin_read_FIO_FLAG_C() bfin_read_PORTGIO_CLEAR()
+#define bfin_write_FIO_FLAG_C(val) bfin_write_PORTGIO_CLEAR(val)
+#define FIO_FLAG_C             PORTGIO_CLEAR
+#define bfin_read_FIO_FLAG_S() bfin_read_PORTGIO_SET()
+#define bfin_write_FIO_FLAG_S(val) bfin_write_PORTGIO_SET(val)
+#define FIO_FLAG_S             PORTGIO_SET
+#define bfin_read_FIO_FLAG_T() bfin_read_PORTGIO_TOGGLE()
+#define bfin_write_FIO_FLAG_T(val) bfin_write_PORTGIO_TOGGLE(val)
+#define FIO_FLAG_T             PORTGIO_TOGGLE
+#define bfin_read_FIO_MASKA_D() bfin_read_PORTGIO_MASKA()
+#define bfin_write_FIO_MASKA_D(val) bfin_write_PORTGIO_MASKA(val)
+#define FIO_MASKA_D        PORTGIO_MASKA
+#define bfin_read_FIO_MASKA_C() bfin_read_PORTGIO_MASKA_CLEAR()
+#define bfin_write_FIO_MASKA_C(val) bfin_write_PORTGIO_MASKA_CLEAR(val)
+#define FIO_MASKA_C        PORTGIO_MASKA_CLEAR
+#define bfin_read_FIO_MASKA_S() bfin_read_PORTGIO_MASKA_SET()
+#define bfin_write_FIO_MASKA_S(val) bfin_write_PORTGIO_MASKA_SET(val)
+#define FIO_MASKA_S        PORTGIO_MASKA_SET
+#define bfin_read_FIO_MASKA_T() bfin_read_PORTGIO_MASKA_TOGGLE()
+#define bfin_write_FIO_MASKA_T(val) bfin_write_PORTGIO_MASKA_TOGGLE(val)
+#define FIO_MASKA_T        PORTGIO_MASKA_TOGGLE
+#define bfin_read_FIO_MASKB_D() bfin_read_PORTGIO_MASKB()
+#define bfin_write_FIO_MASKB_D(val) bfin_write_PORTGIO_MASKB(val)
+#define FIO_MASKB_D        PORTGIO_MASKB
+#define bfin_read_FIO_MASKB_C() bfin_read_PORTGIO_MASKB_CLEAR()
+#define bfin_write_FIO_MASKB_C(val) bfin_write_PORTGIO_MASKB_CLEAR(val)
+#define FIO_MASKB_C        PORTGIO_MASKB_CLEAR
+#define bfin_read_FIO_MASKB_S() bfin_read_PORTGIO_MASKB_SET()
+#define bfin_write_FIO_MASKB_S(val) bfin_write_PORTGIO_MASKB_SET(val)
+#define FIO_MASKB_S        PORTGIO_MASKB_SET
+#define bfin_read_FIO_MASKB_T() bfin_read_PORTGIO_MASKB_TOGGLE()
+#define bfin_write_FIO_MASKB_T(val) bfin_write_PORTGIO_MASKB_TOGGLE(val)
+#define FIO_MASKB_T        PORTGIO_MASKB_TOGGLE
+#define bfin_read_FIO_DIR() bfin_read_PORTGIO_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_PORTGIO_DIR(val)
+#define FIO_DIR                    PORTGIO_DIR
+#define bfin_read_FIO_POLAR() bfin_read_PORTGIO_POLAR()
+#define bfin_write_FIO_POLAR(val) bfin_write_PORTGIO_POLAR(val)
+#define FIO_POLAR              PORTGIO_POLAR
+#define bfin_read_FIO_EDGE() bfin_read_PORTGIO_EDGE()
+#define bfin_write_FIO_EDGE(val) bfin_write_PORTGIO_EDGE(val)
+#define FIO_EDGE               PORTGIO_EDGE
+#define bfin_read_FIO_BOTH() bfin_read_PORTGIO_BOTH()
+#define bfin_write_FIO_BOTH(val) bfin_write_PORTGIO_BOTH(val)
+#define FIO_BOTH               PORTGIO_BOTH
+#define bfin_read_FIO_INEN() bfin_read_PORTGIO_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_PORTGIO_INEN(val)
+#define FIO_INEN               PORTGIO_INEN
+
+#endif
+
+/* FIO USE PORT H*/
+#ifdef CONFIG_BF537_PORT_H
+#define bfin_read_PORT_FER() bfin_read_PORTH_FER()
+#define bfin_write_PORT_FER(val) bfin_write_PORTH_FER(val)
+#define bfin_read_FIO_FLAG_D() bfin_read_PORTHIO()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_PORTHIO(val)
+#define bfin_read_FIO_FLAG_C() bfin_read_PORTHIO_CLEAR()
+#define bfin_write_FIO_FLAG_C(val) bfin_write_PORTHIO_CLEAR(val)
+#define bfin_read_FIO_FLAG_S() bfin_read_PORTHIO_SET()
+#define bfin_write_FIO_FLAG_S(val) bfin_write_PORTHIO_SET(val)
+#define bfin_read_FIO_FLAG_T() bfin_read_PORTHIO_TOGGLE()
+#define bfin_write_FIO_FLAG_T(val) bfin_write_PORTHIO_TOGGLE(val)
+#define bfin_read_FIO_MASKA_D() bfin_read_PORTHIO_MASKA()
+#define bfin_write_FIO_MASKA_D(val) bfin_write_PORTHIO_MASKA(val)
+#define bfin_read_FIO_MASKA_C() bfin_read_PORTHIO_MASKA_CLEAR()
+#define bfin_write_FIO_MASKA_C(val) bfin_write_PORTHIO_MASKA_CLEAR(val)
+#define bfin_read_FIO_MASKA_S() bfin_read_PORTHIO_MASKA_SET()
+#define bfin_write_FIO_MASKA_S(val) bfin_write_PORTHIO_MASKA_SET(val)
+#define bfin_read_FIO_MASKA_T() bfin_read_PORTHIO_MASKA_TOGGLE()
+#define bfin_write_FIO_MASKA_T(val) bfin_write_PORTHIO_MASKA_TOGGLE(val)
+#define bfin_read_FIO_MASKB_D() bfin_read_PORTHIO_MASKB()
+#define bfin_write_FIO_MASKB_D(val) bfin_write_PORTHIO_MASKB(val)
+#define bfin_read_FIO_MASKB_C() bfin_read_PORTHIO_MASKB_CLEAR()
+#define bfin_write_FIO_MASKB_C(val) bfin_write_PORTHIO_MASKB_CLEAR(val)
+#define bfin_read_FIO_MASKB_S() bfin_read_PORTHIO_MASKB_SET()
+#define bfin_write_FIO_MASKB_S(val) bfin_write_PORTHIO_MASKB_SET(val)
+#define bfin_read_FIO_MASKB_T() bfin_read_PORTHIO_MASKB_TOGGLE()
+#define bfin_write_FIO_MASKB_T(val) bfin_write_PORTHIO_MASKB_TOGGLE(val)
+#define bfin_read_FIO_DIR() bfin_read_PORTHIO_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_PORTHIO_DIR(val)
+#define bfin_read_FIO_POLAR() bfin_read_PORTHIO_POLAR()
+#define bfin_write_FIO_POLAR(val) bfin_write_PORTHIO_POLAR(val)
+#define bfin_read_FIO_EDGE() bfin_read_PORTHIO_EDGE()
+#define bfin_write_FIO_EDGE(val) bfin_write_PORTHIO_EDGE(val)
+#define bfin_read_FIO_BOTH() bfin_read_PORTHIO_BOTH()
+#define bfin_write_FIO_BOTH(val) bfin_write_PORTHIO_BOTH(val)
+#define bfin_read_FIO_INEN() bfin_read_PORTHIO_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_PORTHIO_INEN(val)
+
+#define bfin_read_FIO_FLAG_D() bfin_read_PORTHIO()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_PORTHIO(val)
+#define FIO_FLAG_D             PORTHIO
+#define bfin_read_FIO_FLAG_C() bfin_read_PORTHIO_CLEAR()
+#define bfin_write_FIO_FLAG_C(val) bfin_write_PORTHIO_CLEAR(val)
+#define FIO_FLAG_C             PORTHIO_CLEAR
+#define bfin_read_FIO_FLAG_S() bfin_read_PORTHIO_SET()
+#define bfin_write_FIO_FLAG_S(val) bfin_write_PORTHIO_SET(val)
+#define FIO_FLAG_S             PORTHIO_SET
+#define bfin_read_FIO_FLAG_T() bfin_read_PORTHIO_TOGGLE()
+#define bfin_write_FIO_FLAG_T(val) bfin_write_PORTHIO_TOGGLE(val)
+#define FIO_FLAG_T             PORTHIO_TOGGLE
+#define bfin_read_FIO_MASKA_D() bfin_read_PORTHIO_MASKA()
+#define bfin_write_FIO_MASKA_D(val) bfin_write_PORTHIO_MASKA(val)
+#define FIO_MASKA_D        PORTHIO_MASKA
+#define bfin_read_FIO_MASKA_C() bfin_read_PORTHIO_MASKA_CLEAR()
+#define bfin_write_FIO_MASKA_C(val) bfin_write_PORTHIO_MASKA_CLEAR(val)
+#define FIO_MASKA_C        PORTHIO_MASKA_CLEAR
+#define bfin_read_FIO_MASKA_S() bfin_read_PORTHIO_MASKA_SET()
+#define bfin_write_FIO_MASKA_S(val) bfin_write_PORTHIO_MASKA_SET(val)
+#define FIO_MASKA_S        PORTHIO_MASKA_SET
+#define bfin_read_FIO_MASKA_T() bfin_read_PORTHIO_MASKA_TOGGLE()
+#define bfin_write_FIO_MASKA_T(val) bfin_write_PORTHIO_MASKA_TOGGLE(val)
+#define FIO_MASKA_T        PORTHIO_MASKA_TOGGLE
+#define bfin_read_FIO_MASKB_D() bfin_read_PORTHIO_MASKB()
+#define bfin_write_FIO_MASKB_D(val) bfin_write_PORTHIO_MASKB(val)
+#define FIO_MASKB_D        PORTHIO_MASKB
+#define bfin_read_FIO_MASKB_C() bfin_read_PORTHIO_MASKB_CLEAR()
+#define bfin_write_FIO_MASKB_C(val) bfin_write_PORTHIO_MASKB_CLEAR(val)
+#define FIO_MASKB_C        PORTHIO_MASKB_CLEAR
+#define bfin_read_FIO_MASKB_S() bfin_read_PORTHIO_MASKB_SET()
+#define bfin_write_FIO_MASKB_S(val) bfin_write_PORTHIO_MASKB_SET(val)
+#define FIO_MASKB_S        PORTHIO_MASKB_SET
+#define bfin_read_FIO_MASKB_T() bfin_read_PORTHIO_MASKB_TOGGLE()
+#define bfin_write_FIO_MASKB_T(val) bfin_write_PORTHIO_MASKB_TOGGLE(val)
+#define FIO_MASKB_T        PORTHIO_MASKB_TOGGLE
+#define bfin_read_FIO_DIR() bfin_read_PORTHIO_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_PORTHIO_DIR(val)
+#define FIO_DIR                    PORTHIO_DIR
+#define bfin_read_FIO_POLAR() bfin_read_PORTHIO_POLAR()
+#define bfin_write_FIO_POLAR(val) bfin_write_PORTHIO_POLAR(val)
+#define FIO_POLAR              PORTHIO_POLAR
+#define bfin_read_FIO_EDGE() bfin_read_PORTHIO_EDGE()
+#define bfin_write_FIO_EDGE(val) bfin_write_PORTHIO_EDGE(val)
+#define FIO_EDGE               PORTHIO_EDGE
+#define bfin_read_FIO_BOTH() bfin_read_PORTHIO_BOTH()
+#define bfin_write_FIO_BOTH(val) bfin_write_PORTHIO_BOTH(val)
+#define FIO_BOTH               PORTHIO_BOTH
+#define bfin_read_FIO_INEN() bfin_read_PORTHIO_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_PORTHIO_INEN(val)
+#define FIO_INEN               PORTHIO_INEN
+
+#endif
+
+/* PLL_DIV Masks                                                                                                       */
+#define CCLK_DIV1 CSEL_DIV1    /*          CCLK = VCO / 1                                  */
+#define CCLK_DIV2 CSEL_DIV2    /*          CCLK = VCO / 2                                  */
+#define CCLK_DIV4 CSEL_DIV4    /*          CCLK = VCO / 4                                  */
+#define CCLK_DIV8 CSEL_DIV8    /*          CCLK = VCO / 8                                  */
+
+#endif
diff --git a/include/asm-blackfin/mach-bf537/cdefBF534.h b/include/asm-blackfin/mach-bf537/cdefBF534.h
new file mode 100644 (file)
index 0000000..7b658c1
--- /dev/null
@@ -0,0 +1,1823 @@
+/*
+ * File:         include/asm-blackfin/mach-bf537/cdefbf534.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF534_H
+#define _CDEF_BF534_H
+
+/* Include all Core registers and bit definitions                                                                      */
+#include "defBF534.h"
+
+/* Include core specific register pointer definitions                                                          */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+#include <asm/system.h>
+
+/* Clock and System Control    (0xFFC00000 - 0xFFC000FF)                                                               */
+#define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
+#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+#define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
+#define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       bfin_write16(VR_CTL, val);
+       __builtin_bfin_ssync();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+       local_irq_save(flags);
+       asm("IDLE;");
+       local_irq_restore(flags);
+       bfin_write32(SIC_IWR, iwr);
+}
+#define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
+#define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)          bfin_write16(PLL_LOCKCNT,val)
+#define bfin_read_CHIPID()                   bfin_read32(CHIPID)
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)                                                       */
+#define bfin_read_SWRST()                    bfin_read16(SWRST)
+#define bfin_write_SWRST(val)                bfin_write16(SWRST,val)
+#define bfin_read_SYSCR()                    bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)                bfin_write16(SYSCR,val)
+#define        pSIC_RVECT                      ((void * volatile *)SIC_RVECT)
+#define bfin_read_SIC_RVECT()                bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val)            bfin_write32(SIC_RVECT,val)
+#define bfin_read_SIC_IMASK()                bfin_read32(SIC_IMASK)
+#define bfin_write_SIC_IMASK(val)            bfin_write32(SIC_IMASK,val)
+#define bfin_read_SIC_IAR0()                 bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)             bfin_write32(SIC_IAR0,val)
+#define bfin_read_SIC_IAR1()                 bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)             bfin_write32(SIC_IAR1,val)
+#define bfin_read_SIC_IAR2()                 bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)             bfin_write32(SIC_IAR2,val)
+#define bfin_read_SIC_IAR3()                 bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)             bfin_write32(SIC_IAR3,val)
+#define bfin_read_SIC_ISR()                  bfin_read32(SIC_ISR)
+#define bfin_write_SIC_ISR(val)              bfin_write32(SIC_ISR,val)
+#define bfin_read_SIC_IWR()                  bfin_read32(SIC_IWR)
+#define bfin_write_SIC_IWR(val)              bfin_write32(SIC_IWR,val)
+
+/* Watchdog Timer              (0xFFC00200 - 0xFFC002FF)                                                                       */
+#define bfin_read_WDOG_CTL()                 bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val)             bfin_write16(WDOG_CTL,val)
+#define bfin_read_WDOG_CNT()                 bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val)             bfin_write32(WDOG_CNT,val)
+#define bfin_read_WDOG_STAT()                bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val)            bfin_write32(WDOG_STAT,val)
+
+/* Real Time Clock             (0xFFC00300 - 0xFFC003FF)                                                                       */
+#define bfin_read_RTC_STAT()                 bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val)             bfin_write32(RTC_STAT,val)
+#define bfin_read_RTC_ICTL()                 bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val)             bfin_write16(RTC_ICTL,val)
+#define bfin_read_RTC_ISTAT()                bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val)            bfin_write16(RTC_ISTAT,val)
+#define bfin_read_RTC_SWCNT()                bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val)            bfin_write16(RTC_SWCNT,val)
+#define bfin_read_RTC_ALARM()                bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val)            bfin_write32(RTC_ALARM,val)
+#define bfin_read_RTC_FAST()                 bfin_read16(RTC_FAST)
+#define bfin_write_RTC_FAST(val)             bfin_write16(RTC_FAST,val)
+#define bfin_read_RTC_PREN()                 bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val)             bfin_write16(RTC_PREN,val)
+
+/* UART0 Controller            (0xFFC00400 - 0xFFC004FF)                                                                       */
+#define bfin_read_UART0_THR()                bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val)            bfin_write16(UART0_THR,val)
+#define bfin_read_UART0_RBR()                bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val)            bfin_write16(UART0_RBR,val)
+#define bfin_read_UART0_DLL()                bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val)            bfin_write16(UART0_DLL,val)
+#define bfin_read_UART0_IER()                bfin_read16(UART0_IER)
+#define bfin_write_UART0_IER(val)            bfin_write16(UART0_IER,val)
+#define bfin_read_UART0_DLH()                bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val)            bfin_write16(UART0_DLH,val)
+#define bfin_read_UART0_IIR()                bfin_read16(UART0_IIR)
+#define bfin_write_UART0_IIR(val)            bfin_write16(UART0_IIR,val)
+#define bfin_read_UART0_LCR()                bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val)            bfin_write16(UART0_LCR,val)
+#define bfin_read_UART0_MCR()                bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val)            bfin_write16(UART0_MCR,val)
+#define bfin_read_UART0_LSR()                bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val)            bfin_write16(UART0_LSR,val)
+#define bfin_read_UART0_MSR()                bfin_read16(UART0_MSR)
+#define bfin_write_UART0_MSR(val)            bfin_write16(UART0_MSR,val)
+#define bfin_read_UART0_SCR()                bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val)            bfin_write16(UART0_SCR,val)
+#define bfin_read_UART0_GCTL()               bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val)           bfin_write16(UART0_GCTL,val)
+
+/* SPI Controller              (0xFFC00500 - 0xFFC005FF)                                                                       */
+#define bfin_read_SPI_CTL()                  bfin_read16(SPI_CTL)
+#define bfin_write_SPI_CTL(val)              bfin_write16(SPI_CTL,val)
+#define bfin_read_SPI_FLG()                  bfin_read16(SPI_FLG)
+#define bfin_write_SPI_FLG(val)              bfin_write16(SPI_FLG,val)
+#define bfin_read_SPI_STAT()                 bfin_read16(SPI_STAT)
+#define bfin_write_SPI_STAT(val)             bfin_write16(SPI_STAT,val)
+#define bfin_read_SPI_TDBR()                 bfin_read16(SPI_TDBR)
+#define bfin_write_SPI_TDBR(val)             bfin_write16(SPI_TDBR,val)
+#define bfin_read_SPI_RDBR()                 bfin_read16(SPI_RDBR)
+#define bfin_write_SPI_RDBR(val)             bfin_write16(SPI_RDBR,val)
+#define bfin_read_SPI_BAUD()                 bfin_read16(SPI_BAUD)
+#define bfin_write_SPI_BAUD(val)             bfin_write16(SPI_BAUD,val)
+#define bfin_read_SPI_SHADOW()               bfin_read16(SPI_SHADOW)
+#define bfin_write_SPI_SHADOW(val)           bfin_write16(SPI_SHADOW,val)
+
+/* TIMER0-7 Registers          (0xFFC00600 - 0xFFC006FF)                                                               */
+#define bfin_read_TIMER0_CONFIG()            bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)        bfin_write16(TIMER0_CONFIG,val)
+#define bfin_read_TIMER0_COUNTER()           bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)       bfin_write32(TIMER0_COUNTER,val)
+#define bfin_read_TIMER0_PERIOD()            bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)        bfin_write32(TIMER0_PERIOD,val)
+#define bfin_read_TIMER0_WIDTH()             bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)         bfin_write32(TIMER0_WIDTH,val)
+
+#define bfin_read_TIMER1_CONFIG()            bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)        bfin_write16(TIMER1_CONFIG,val)
+#define bfin_read_TIMER1_COUNTER()           bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)       bfin_write32(TIMER1_COUNTER,val)
+#define bfin_read_TIMER1_PERIOD()            bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)        bfin_write32(TIMER1_PERIOD,val)
+#define bfin_read_TIMER1_WIDTH()             bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)         bfin_write32(TIMER1_WIDTH,val)
+
+#define bfin_read_TIMER2_CONFIG()            bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)        bfin_write16(TIMER2_CONFIG,val)
+#define bfin_read_TIMER2_COUNTER()           bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)       bfin_write32(TIMER2_COUNTER,val)
+#define bfin_read_TIMER2_PERIOD()            bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)        bfin_write32(TIMER2_PERIOD,val)
+#define bfin_read_TIMER2_WIDTH()             bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)         bfin_write32(TIMER2_WIDTH,val)
+
+#define bfin_read_TIMER3_CONFIG()            bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val)        bfin_write16(TIMER3_CONFIG,val)
+#define bfin_read_TIMER3_COUNTER()           bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val)       bfin_write32(TIMER3_COUNTER,val)
+#define bfin_read_TIMER3_PERIOD()            bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val)        bfin_write32(TIMER3_PERIOD,val)
+#define bfin_read_TIMER3_WIDTH()             bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val)         bfin_write32(TIMER3_WIDTH,val)
+
+#define bfin_read_TIMER4_CONFIG()            bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val)        bfin_write16(TIMER4_CONFIG,val)
+#define bfin_read_TIMER4_COUNTER()           bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val)       bfin_write32(TIMER4_COUNTER,val)
+#define bfin_read_TIMER4_PERIOD()            bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val)        bfin_write32(TIMER4_PERIOD,val)
+#define bfin_read_TIMER4_WIDTH()             bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val)         bfin_write32(TIMER4_WIDTH,val)
+
+#define bfin_read_TIMER5_CONFIG()            bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val)        bfin_write16(TIMER5_CONFIG,val)
+#define bfin_read_TIMER5_COUNTER()           bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val)       bfin_write32(TIMER5_COUNTER,val)
+#define bfin_read_TIMER5_PERIOD()            bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val)        bfin_write32(TIMER5_PERIOD,val)
+#define bfin_read_TIMER5_WIDTH()             bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val)         bfin_write32(TIMER5_WIDTH,val)
+
+#define bfin_read_TIMER6_CONFIG()            bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val)        bfin_write16(TIMER6_CONFIG,val)
+#define bfin_read_TIMER6_COUNTER()           bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val)       bfin_write32(TIMER6_COUNTER,val)
+#define bfin_read_TIMER6_PERIOD()            bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val)        bfin_write32(TIMER6_PERIOD,val)
+#define bfin_read_TIMER6_WIDTH()             bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val)         bfin_write32(TIMER6_WIDTH,val)
+
+#define bfin_read_TIMER7_CONFIG()            bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val)        bfin_write16(TIMER7_CONFIG,val)
+#define bfin_read_TIMER7_COUNTER()           bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val)       bfin_write32(TIMER7_COUNTER,val)
+#define bfin_read_TIMER7_PERIOD()            bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val)        bfin_write32(TIMER7_PERIOD,val)
+#define bfin_read_TIMER7_WIDTH()             bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val)         bfin_write32(TIMER7_WIDTH,val)
+
+#define bfin_read_TIMER_ENABLE()             bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val)         bfin_write16(TIMER_ENABLE,val)
+#define bfin_read_TIMER_DISABLE()            bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val)        bfin_write16(TIMER_DISABLE,val)
+#define bfin_read_TIMER_STATUS()             bfin_read32(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val)         bfin_write32(TIMER_STATUS,val)
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)                                                                */
+#define bfin_read_PORTFIO()                  bfin_read16(PORTFIO)
+#define bfin_write_PORTFIO(val)              bfin_write16(PORTFIO,val)
+#define bfin_read_PORTFIO_CLEAR()            bfin_read16(PORTFIO_CLEAR)
+#define bfin_write_PORTFIO_CLEAR(val)        bfin_write16(PORTFIO_CLEAR,val)
+#define bfin_read_PORTFIO_SET()              bfin_read16(PORTFIO_SET)
+#define bfin_write_PORTFIO_SET(val)          bfin_write16(PORTFIO_SET,val)
+#define bfin_read_PORTFIO_TOGGLE()           bfin_read16(PORTFIO_TOGGLE)
+#define bfin_write_PORTFIO_TOGGLE(val)       bfin_write16(PORTFIO_TOGGLE,val)
+#define bfin_read_PORTFIO_MASKA()            bfin_read16(PORTFIO_MASKA)
+#define bfin_write_PORTFIO_MASKA(val)        bfin_write16(PORTFIO_MASKA,val)
+#define bfin_read_PORTFIO_MASKA_CLEAR()      bfin_read16(PORTFIO_MASKA_CLEAR)
+#define bfin_write_PORTFIO_MASKA_CLEAR(val)  bfin_write16(PORTFIO_MASKA_CLEAR,val)
+#define bfin_read_PORTFIO_MASKA_SET()        bfin_read16(PORTFIO_MASKA_SET)
+#define bfin_write_PORTFIO_MASKA_SET(val)    bfin_write16(PORTFIO_MASKA_SET,val)
+#define bfin_read_PORTFIO_MASKA_TOGGLE()     bfin_read16(PORTFIO_MASKA_TOGGLE)
+#define bfin_write_PORTFIO_MASKA_TOGGLE(val) bfin_write16(PORTFIO_MASKA_TOGGLE,val)
+#define bfin_read_PORTFIO_MASKB()            bfin_read16(PORTFIO_MASKB)
+#define bfin_write_PORTFIO_MASKB(val)        bfin_write16(PORTFIO_MASKB,val)
+#define bfin_read_PORTFIO_MASKB_CLEAR()      bfin_read16(PORTFIO_MASKB_CLEAR)
+#define bfin_write_PORTFIO_MASKB_CLEAR(val)  bfin_write16(PORTFIO_MASKB_CLEAR,val)
+#define bfin_read_PORTFIO_MASKB_SET()        bfin_read16(PORTFIO_MASKB_SET)
+#define bfin_write_PORTFIO_MASKB_SET(val)    bfin_write16(PORTFIO_MASKB_SET,val)
+#define bfin_read_PORTFIO_MASKB_TOGGLE()     bfin_read16(PORTFIO_MASKB_TOGGLE)
+#define bfin_write_PORTFIO_MASKB_TOGGLE(val) bfin_write16(PORTFIO_MASKB_TOGGLE,val)
+#define bfin_read_PORTFIO_DIR()              bfin_read16(PORTFIO_DIR)
+#define bfin_write_PORTFIO_DIR(val)          bfin_write16(PORTFIO_DIR,val)
+#define bfin_read_PORTFIO_POLAR()            bfin_read16(PORTFIO_POLAR)
+#define bfin_write_PORTFIO_POLAR(val)        bfin_write16(PORTFIO_POLAR,val)
+#define bfin_read_PORTFIO_EDGE()             bfin_read16(PORTFIO_EDGE)
+#define bfin_write_PORTFIO_EDGE(val)         bfin_write16(PORTFIO_EDGE,val)
+#define bfin_read_PORTFIO_BOTH()             bfin_read16(PORTFIO_BOTH)
+#define bfin_write_PORTFIO_BOTH(val)         bfin_write16(PORTFIO_BOTH,val)
+#define bfin_read_PORTFIO_INEN()             bfin_read16(PORTFIO_INEN)
+#define bfin_write_PORTFIO_INEN(val)         bfin_write16(PORTFIO_INEN,val)
+
+/* SPORT0 Controller           (0xFFC00800 - 0xFFC008FF)                                                               */
+#define bfin_read_SPORT0_TCR1()              bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)          bfin_write16(SPORT0_TCR1,val)
+#define bfin_read_SPORT0_TCR2()              bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)          bfin_write16(SPORT0_TCR2,val)
+#define bfin_read_SPORT0_TCLKDIV()           bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)       bfin_write16(SPORT0_TCLKDIV,val)
+#define bfin_read_SPORT0_TFSDIV()            bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)        bfin_write16(SPORT0_TFSDIV,val)
+#define bfin_read_SPORT0_TX()                bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)            bfin_write32(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX()                bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)            bfin_write32(SPORT0_RX,val)
+#define bfin_read_SPORT0_TX32()              bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)          bfin_write32(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX32()              bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)          bfin_write32(SPORT0_RX,val)
+#define bfin_read_SPORT0_TX16()              bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)          bfin_write16(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX16()              bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)          bfin_write16(SPORT0_RX,val)
+#define bfin_read_SPORT0_RCR1()              bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)          bfin_write16(SPORT0_RCR1,val)
+#define bfin_read_SPORT0_RCR2()              bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)          bfin_write16(SPORT0_RCR2,val)
+#define bfin_read_SPORT0_RCLKDIV()           bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)       bfin_write16(SPORT0_RCLKDIV,val)
+#define bfin_read_SPORT0_RFSDIV()            bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)        bfin_write16(SPORT0_RFSDIV,val)
+#define bfin_read_SPORT0_STAT()              bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)          bfin_write16(SPORT0_STAT,val)
+#define bfin_read_SPORT0_CHNL()              bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)          bfin_write16(SPORT0_CHNL,val)
+#define bfin_read_SPORT0_MCMC1()             bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)         bfin_write16(SPORT0_MCMC1,val)
+#define bfin_read_SPORT0_MCMC2()             bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)         bfin_write16(SPORT0_MCMC2,val)
+#define bfin_read_SPORT0_MTCS0()             bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)         bfin_write32(SPORT0_MTCS0,val)
+#define bfin_read_SPORT0_MTCS1()             bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)         bfin_write32(SPORT0_MTCS1,val)
+#define bfin_read_SPORT0_MTCS2()             bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)         bfin_write32(SPORT0_MTCS2,val)
+#define bfin_read_SPORT0_MTCS3()             bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)         bfin_write32(SPORT0_MTCS3,val)
+#define bfin_read_SPORT0_MRCS0()             bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)         bfin_write32(SPORT0_MRCS0,val)
+#define bfin_read_SPORT0_MRCS1()             bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)         bfin_write32(SPORT0_MRCS1,val)
+#define bfin_read_SPORT0_MRCS2()             bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)         bfin_write32(SPORT0_MRCS2,val)
+#define bfin_read_SPORT0_MRCS3()             bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)         bfin_write32(SPORT0_MRCS3,val)
+
+/* SPORT1 Controller           (0xFFC00900 - 0xFFC009FF)                                                               */
+#define bfin_read_SPORT1_TCR1()              bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)          bfin_write16(SPORT1_TCR1,val)
+#define bfin_read_SPORT1_TCR2()              bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)          bfin_write16(SPORT1_TCR2,val)
+#define bfin_read_SPORT1_TCLKDIV()           bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)       bfin_write16(SPORT1_TCLKDIV,val)
+#define bfin_read_SPORT1_TFSDIV()            bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)        bfin_write16(SPORT1_TFSDIV,val)
+#define bfin_read_SPORT1_TX()                bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)            bfin_write32(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX()                bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)            bfin_write32(SPORT1_RX,val)
+#define bfin_read_SPORT1_TX32()              bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)          bfin_write32(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX32()              bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)          bfin_write32(SPORT1_RX,val)
+#define bfin_read_SPORT1_TX16()              bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)          bfin_write16(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX16()              bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)          bfin_write16(SPORT1_RX,val)
+#define bfin_read_SPORT1_RCR1()              bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)          bfin_write16(SPORT1_RCR1,val)
+#define bfin_read_SPORT1_RCR2()              bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)          bfin_write16(SPORT1_RCR2,val)
+#define bfin_read_SPORT1_RCLKDIV()           bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)       bfin_write16(SPORT1_RCLKDIV,val)
+#define bfin_read_SPORT1_RFSDIV()            bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)        bfin_write16(SPORT1_RFSDIV,val)
+#define bfin_read_SPORT1_STAT()              bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)          bfin_write16(SPORT1_STAT,val)
+#define bfin_read_SPORT1_CHNL()              bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)          bfin_write16(SPORT1_CHNL,val)
+#define bfin_read_SPORT1_MCMC1()             bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)         bfin_write16(SPORT1_MCMC1,val)
+#define bfin_read_SPORT1_MCMC2()             bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)         bfin_write16(SPORT1_MCMC2,val)
+#define bfin_read_SPORT1_MTCS0()             bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)         bfin_write32(SPORT1_MTCS0,val)
+#define bfin_read_SPORT1_MTCS1()             bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)         bfin_write32(SPORT1_MTCS1,val)
+#define bfin_read_SPORT1_MTCS2()             bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)         bfin_write32(SPORT1_MTCS2,val)
+#define bfin_read_SPORT1_MTCS3()             bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)         bfin_write32(SPORT1_MTCS3,val)
+#define bfin_read_SPORT1_MRCS0()             bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)         bfin_write32(SPORT1_MRCS0,val)
+#define bfin_read_SPORT1_MRCS1()             bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)         bfin_write32(SPORT1_MRCS1,val)
+#define bfin_read_SPORT1_MRCS2()             bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)         bfin_write32(SPORT1_MRCS2,val)
+#define bfin_read_SPORT1_MRCS3()             bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)         bfin_write32(SPORT1_MRCS3,val)
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)                                                       */
+#define bfin_read_EBIU_AMGCTL()              bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)          bfin_write16(EBIU_AMGCTL,val)
+#define bfin_read_EBIU_AMBCTL0()             bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)         bfin_write32(EBIU_AMBCTL0,val)
+#define bfin_read_EBIU_AMBCTL1()             bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)         bfin_write32(EBIU_AMBCTL1,val)
+#define bfin_read_EBIU_SDGCTL()              bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val)          bfin_write32(EBIU_SDGCTL,val)
+#define bfin_read_EBIU_SDBCTL()              bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val)          bfin_write16(EBIU_SDBCTL,val)
+#define bfin_read_EBIU_SDRRC()               bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val)           bfin_write16(EBIU_SDRRC,val)
+#define bfin_read_EBIU_SDSTAT()              bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val)          bfin_write16(EBIU_SDSTAT,val)
+
+/* DMA Traffic Control Registers                                                                                                       */
+#define        pDMA_TCPER                      ((volatile unsigned short *)DMA_TCPER)
+#define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
+#define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
+#define        pDMA_TCCNT                      ((volatile unsigned short *)DMA_TCCNT)
+#define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
+#define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
+
+/* DMA Controller                                                                                                                                      */
+#define bfin_read_DMA0_CONFIG()              bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val)          bfin_write16(DMA0_CONFIG,val)
+#define bfin_read_DMA0_NEXT_DESC_PTR()       bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val)   bfin_write32(DMA0_NEXT_DESC_PTR,val)
+#define bfin_read_DMA0_START_ADDR()          bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val)      bfin_write32(DMA0_START_ADDR,val)
+#define bfin_read_DMA0_X_COUNT()             bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val)         bfin_write16(DMA0_X_COUNT,val)
+#define bfin_read_DMA0_Y_COUNT()             bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val)         bfin_write16(DMA0_Y_COUNT,val)
+#define bfin_read_DMA0_X_MODIFY()            bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val)        bfin_write16(DMA0_X_MODIFY,val)
+#define bfin_read_DMA0_Y_MODIFY()            bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val)        bfin_write16(DMA0_Y_MODIFY,val)
+#define bfin_read_DMA0_CURR_DESC_PTR()       bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val)   bfin_write32(DMA0_CURR_DESC_PTR,val)
+#define bfin_read_DMA0_CURR_ADDR()           bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val)       bfin_write32(DMA0_CURR_ADDR,val)
+#define bfin_read_DMA0_CURR_X_COUNT()        bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val)    bfin_write16(DMA0_CURR_X_COUNT,val)
+#define bfin_read_DMA0_CURR_Y_COUNT()        bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val)    bfin_write16(DMA0_CURR_Y_COUNT,val)
+#define bfin_read_DMA0_IRQ_STATUS()          bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val)      bfin_write16(DMA0_IRQ_STATUS,val)
+#define bfin_read_DMA0_PERIPHERAL_MAP()      bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val)  bfin_write16(DMA0_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA1_CONFIG()              bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val)          bfin_write16(DMA1_CONFIG,val)
+#define bfin_read_DMA1_NEXT_DESC_PTR()       bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val)   bfin_write32(DMA1_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_START_ADDR()          bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val)      bfin_write32(DMA1_START_ADDR,val)
+#define bfin_read_DMA1_X_COUNT()             bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val)         bfin_write16(DMA1_X_COUNT,val)
+#define bfin_read_DMA1_Y_COUNT()             bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val)         bfin_write16(DMA1_Y_COUNT,val)
+#define bfin_read_DMA1_X_MODIFY()            bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val)        bfin_write16(DMA1_X_MODIFY,val)
+#define bfin_read_DMA1_Y_MODIFY()            bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val)        bfin_write16(DMA1_Y_MODIFY,val)
+#define bfin_read_DMA1_CURR_DESC_PTR()       bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val)   bfin_write32(DMA1_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_CURR_ADDR()           bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val)       bfin_write32(DMA1_CURR_ADDR,val)
+#define bfin_read_DMA1_CURR_X_COUNT()        bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val)    bfin_write16(DMA1_CURR_X_COUNT,val)
+#define bfin_read_DMA1_CURR_Y_COUNT()        bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val)    bfin_write16(DMA1_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_IRQ_STATUS()          bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val)      bfin_write16(DMA1_IRQ_STATUS,val)
+#define bfin_read_DMA1_PERIPHERAL_MAP()      bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val)  bfin_write16(DMA1_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA2_CONFIG()              bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val)          bfin_write16(DMA2_CONFIG,val)
+#define bfin_read_DMA2_NEXT_DESC_PTR()       bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val)   bfin_write32(DMA2_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_START_ADDR()          bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val)      bfin_write32(DMA2_START_ADDR,val)
+#define bfin_read_DMA2_X_COUNT()             bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val)         bfin_write16(DMA2_X_COUNT,val)
+#define bfin_read_DMA2_Y_COUNT()             bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val)         bfin_write16(DMA2_Y_COUNT,val)
+#define bfin_read_DMA2_X_MODIFY()            bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val)        bfin_write16(DMA2_X_MODIFY,val)
+#define bfin_read_DMA2_Y_MODIFY()            bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val)        bfin_write16(DMA2_Y_MODIFY,val)
+#define bfin_read_DMA2_CURR_DESC_PTR()       bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val)   bfin_write32(DMA2_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_CURR_ADDR()           bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val)       bfin_write32(DMA2_CURR_ADDR,val)
+#define bfin_read_DMA2_CURR_X_COUNT()        bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val)    bfin_write16(DMA2_CURR_X_COUNT,val)
+#define bfin_read_DMA2_CURR_Y_COUNT()        bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val)    bfin_write16(DMA2_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_IRQ_STATUS()          bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val)      bfin_write16(DMA2_IRQ_STATUS,val)
+#define bfin_read_DMA2_PERIPHERAL_MAP()      bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val)  bfin_write16(DMA2_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA3_CONFIG()              bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val)          bfin_write16(DMA3_CONFIG,val)
+#define bfin_read_DMA3_NEXT_DESC_PTR()       bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val)   bfin_write32(DMA3_NEXT_DESC_PTR,val)
+#define bfin_read_DMA3_START_ADDR()          bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val)      bfin_write32(DMA3_START_ADDR,val)
+#define bfin_read_DMA3_X_COUNT()             bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val)         bfin_write16(DMA3_X_COUNT,val)
+#define bfin_read_DMA3_Y_COUNT()             bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val)         bfin_write16(DMA3_Y_COUNT,val)
+#define bfin_read_DMA3_X_MODIFY()            bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val)        bfin_write16(DMA3_X_MODIFY,val)
+#define bfin_read_DMA3_Y_MODIFY()            bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val)        bfin_write16(DMA3_Y_MODIFY,val)
+#define bfin_read_DMA3_CURR_DESC_PTR()       bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val)   bfin_write32(DMA3_CURR_DESC_PTR,val)
+#define bfin_read_DMA3_CURR_ADDR()           bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val)       bfin_write32(DMA3_CURR_ADDR,val)
+#define bfin_read_DMA3_CURR_X_COUNT()        bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val)    bfin_write16(DMA3_CURR_X_COUNT,val)
+#define bfin_read_DMA3_CURR_Y_COUNT()        bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val)    bfin_write16(DMA3_CURR_Y_COUNT,val)
+#define bfin_read_DMA3_IRQ_STATUS()          bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val)      bfin_write16(DMA3_IRQ_STATUS,val)
+#define bfin_read_DMA3_PERIPHERAL_MAP()      bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val)  bfin_write16(DMA3_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA4_CONFIG()              bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val)          bfin_write16(DMA4_CONFIG,val)
+#define bfin_read_DMA4_NEXT_DESC_PTR()       bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val)   bfin_write32(DMA4_NEXT_DESC_PTR,val)
+#define bfin_read_DMA4_START_ADDR()          bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val)      bfin_write32(DMA4_START_ADDR,val)
+#define bfin_read_DMA4_X_COUNT()             bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val)         bfin_write16(DMA4_X_COUNT,val)
+#define bfin_read_DMA4_Y_COUNT()             bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val)         bfin_write16(DMA4_Y_COUNT,val)
+#define bfin_read_DMA4_X_MODIFY()            bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val)        bfin_write16(DMA4_X_MODIFY,val)
+#define bfin_read_DMA4_Y_MODIFY()            bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val)        bfin_write16(DMA4_Y_MODIFY,val)
+#define bfin_read_DMA4_CURR_DESC_PTR()       bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val)   bfin_write32(DMA4_CURR_DESC_PTR,val)
+#define bfin_read_DMA4_CURR_ADDR()           bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val)       bfin_write32(DMA4_CURR_ADDR,val)
+#define bfin_read_DMA4_CURR_X_COUNT()        bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val)    bfin_write16(DMA4_CURR_X_COUNT,val)
+#define bfin_read_DMA4_CURR_Y_COUNT()        bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val)    bfin_write16(DMA4_CURR_Y_COUNT,val)
+#define bfin_read_DMA4_IRQ_STATUS()          bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val)      bfin_write16(DMA4_IRQ_STATUS,val)
+#define bfin_read_DMA4_PERIPHERAL_MAP()      bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val)  bfin_write16(DMA4_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA5_CONFIG()              bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val)          bfin_write16(DMA5_CONFIG,val)
+#define bfin_read_DMA5_NEXT_DESC_PTR()       bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val)   bfin_write32(DMA5_NEXT_DESC_PTR,val)
+#define bfin_read_DMA5_START_ADDR()          bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val)      bfin_write32(DMA5_START_ADDR,val)
+#define bfin_read_DMA5_X_COUNT()             bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val)         bfin_write16(DMA5_X_COUNT,val)
+#define bfin_read_DMA5_Y_COUNT()             bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val)         bfin_write16(DMA5_Y_COUNT,val)
+#define bfin_read_DMA5_X_MODIFY()            bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val)        bfin_write16(DMA5_X_MODIFY,val)
+#define bfin_read_DMA5_Y_MODIFY()            bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val)        bfin_write16(DMA5_Y_MODIFY,val)
+#define bfin_read_DMA5_CURR_DESC_PTR()       bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val)   bfin_write32(DMA5_CURR_DESC_PTR,val)
+#define bfin_read_DMA5_CURR_ADDR()           bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val)       bfin_write32(DMA5_CURR_ADDR,val)
+#define bfin_read_DMA5_CURR_X_COUNT()        bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val)    bfin_write16(DMA5_CURR_X_COUNT,val)
+#define bfin_read_DMA5_CURR_Y_COUNT()        bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val)    bfin_write16(DMA5_CURR_Y_COUNT,val)
+#define bfin_read_DMA5_IRQ_STATUS()          bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val)      bfin_write16(DMA5_IRQ_STATUS,val)
+#define bfin_read_DMA5_PERIPHERAL_MAP()      bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val)  bfin_write16(DMA5_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA6_CONFIG()              bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val)          bfin_write16(DMA6_CONFIG,val)
+#define bfin_read_DMA6_NEXT_DESC_PTR()       bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val)   bfin_write32(DMA6_NEXT_DESC_PTR,val)
+#define bfin_read_DMA6_START_ADDR()          bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val)      bfin_write32(DMA6_START_ADDR,val)
+#define bfin_read_DMA6_X_COUNT()             bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val)         bfin_write16(DMA6_X_COUNT,val)
+#define bfin_read_DMA6_Y_COUNT()             bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val)         bfin_write16(DMA6_Y_COUNT,val)
+#define bfin_read_DMA6_X_MODIFY()            bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val)        bfin_write16(DMA6_X_MODIFY,val)
+#define bfin_read_DMA6_Y_MODIFY()            bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val)        bfin_write16(DMA6_Y_MODIFY,val)
+#define bfin_read_DMA6_CURR_DESC_PTR()       bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val)   bfin_write32(DMA6_CURR_DESC_PTR,val)
+#define bfin_read_DMA6_CURR_ADDR()           bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val)       bfin_write32(DMA6_CURR_ADDR,val)
+#define bfin_read_DMA6_CURR_X_COUNT()        bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val)    bfin_write16(DMA6_CURR_X_COUNT,val)
+#define bfin_read_DMA6_CURR_Y_COUNT()        bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val)    bfin_write16(DMA6_CURR_Y_COUNT,val)
+#define bfin_read_DMA6_IRQ_STATUS()          bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val)      bfin_write16(DMA6_IRQ_STATUS,val)
+#define bfin_read_DMA6_PERIPHERAL_MAP()      bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val)  bfin_write16(DMA6_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA7_CONFIG()              bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val)          bfin_write16(DMA7_CONFIG,val)
+#define bfin_read_DMA7_NEXT_DESC_PTR()       bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val)   bfin_write32(DMA7_NEXT_DESC_PTR,val)
+#define bfin_read_DMA7_START_ADDR()          bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val)      bfin_write32(DMA7_START_ADDR,val)
+#define bfin_read_DMA7_X_COUNT()             bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val)         bfin_write16(DMA7_X_COUNT,val)
+#define bfin_read_DMA7_Y_COUNT()             bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val)         bfin_write16(DMA7_Y_COUNT,val)
+#define bfin_read_DMA7_X_MODIFY()            bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val)        bfin_write16(DMA7_X_MODIFY,val)
+#define bfin_read_DMA7_Y_MODIFY()            bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val)        bfin_write16(DMA7_Y_MODIFY,val)
+#define bfin_read_DMA7_CURR_DESC_PTR()       bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val)   bfin_write32(DMA7_CURR_DESC_PTR,val)
+#define bfin_read_DMA7_CURR_ADDR()           bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val)       bfin_write32(DMA7_CURR_ADDR,val)
+#define bfin_read_DMA7_CURR_X_COUNT()        bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val)    bfin_write16(DMA7_CURR_X_COUNT,val)
+#define bfin_read_DMA7_CURR_Y_COUNT()        bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val)    bfin_write16(DMA7_CURR_Y_COUNT,val)
+#define bfin_read_DMA7_IRQ_STATUS()          bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val)      bfin_write16(DMA7_IRQ_STATUS,val)
+#define bfin_read_DMA7_PERIPHERAL_MAP()      bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val)  bfin_write16(DMA7_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA8_CONFIG()              bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val)          bfin_write16(DMA8_CONFIG,val)
+#define bfin_read_DMA8_NEXT_DESC_PTR()       bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val)   bfin_write32(DMA8_NEXT_DESC_PTR,val)
+#define bfin_read_DMA8_START_ADDR()          bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val)      bfin_write32(DMA8_START_ADDR,val)
+#define bfin_read_DMA8_X_COUNT()             bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val)         bfin_write16(DMA8_X_COUNT,val)
+#define bfin_read_DMA8_Y_COUNT()             bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val)         bfin_write16(DMA8_Y_COUNT,val)
+#define bfin_read_DMA8_X_MODIFY()            bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val)        bfin_write16(DMA8_X_MODIFY,val)
+#define bfin_read_DMA8_Y_MODIFY()            bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val)        bfin_write16(DMA8_Y_MODIFY,val)
+#define bfin_read_DMA8_CURR_DESC_PTR()       bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val)   bfin_write32(DMA8_CURR_DESC_PTR,val)
+#define bfin_read_DMA8_CURR_ADDR()           bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val)       bfin_write32(DMA8_CURR_ADDR,val)
+#define bfin_read_DMA8_CURR_X_COUNT()        bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val)    bfin_write16(DMA8_CURR_X_COUNT,val)
+#define bfin_read_DMA8_CURR_Y_COUNT()        bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val)    bfin_write16(DMA8_CURR_Y_COUNT,val)
+#define bfin_read_DMA8_IRQ_STATUS()          bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val)      bfin_write16(DMA8_IRQ_STATUS,val)
+#define bfin_read_DMA8_PERIPHERAL_MAP()      bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val)  bfin_write16(DMA8_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA9_CONFIG()              bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val)          bfin_write16(DMA9_CONFIG,val)
+#define bfin_read_DMA9_NEXT_DESC_PTR()       bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val)   bfin_write32(DMA9_NEXT_DESC_PTR,val)
+#define bfin_read_DMA9_START_ADDR()          bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val)      bfin_write32(DMA9_START_ADDR,val)
+#define bfin_read_DMA9_X_COUNT()             bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val)         bfin_write16(DMA9_X_COUNT,val)
+#define bfin_read_DMA9_Y_COUNT()             bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val)         bfin_write16(DMA9_Y_COUNT,val)
+#define bfin_read_DMA9_X_MODIFY()            bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val)        bfin_write16(DMA9_X_MODIFY,val)
+#define bfin_read_DMA9_Y_MODIFY()            bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val)        bfin_write16(DMA9_Y_MODIFY,val)
+#define bfin_read_DMA9_CURR_DESC_PTR()       bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val)   bfin_write32(DMA9_CURR_DESC_PTR,val)
+#define bfin_read_DMA9_CURR_ADDR()           bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val)       bfin_write32(DMA9_CURR_ADDR,val)
+#define bfin_read_DMA9_CURR_X_COUNT()        bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val)    bfin_write16(DMA9_CURR_X_COUNT,val)
+#define bfin_read_DMA9_CURR_Y_COUNT()        bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val)    bfin_write16(DMA9_CURR_Y_COUNT,val)
+#define bfin_read_DMA9_IRQ_STATUS()          bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val)      bfin_write16(DMA9_IRQ_STATUS,val)
+#define bfin_read_DMA9_PERIPHERAL_MAP()      bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val)  bfin_write16(DMA9_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA10_CONFIG()             bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val)         bfin_write16(DMA10_CONFIG,val)
+#define bfin_read_DMA10_NEXT_DESC_PTR()      bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val)  bfin_write32(DMA10_NEXT_DESC_PTR,val)
+#define bfin_read_DMA10_START_ADDR()         bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val)     bfin_write32(DMA10_START_ADDR,val)
+#define bfin_read_DMA10_X_COUNT()            bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val)        bfin_write16(DMA10_X_COUNT,val)
+#define bfin_read_DMA10_Y_COUNT()            bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val)        bfin_write16(DMA10_Y_COUNT,val)
+#define bfin_read_DMA10_X_MODIFY()           bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val)       bfin_write16(DMA10_X_MODIFY,val)
+#define bfin_read_DMA10_Y_MODIFY()           bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val)       bfin_write16(DMA10_Y_MODIFY,val)
+#define bfin_read_DMA10_CURR_DESC_PTR()      bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val)  bfin_write32(DMA10_CURR_DESC_PTR,val)
+#define bfin_read_DMA10_CURR_ADDR()          bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val)      bfin_write32(DMA10_CURR_ADDR,val)
+#define bfin_read_DMA10_CURR_X_COUNT()       bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val)   bfin_write16(DMA10_CURR_X_COUNT,val)
+#define bfin_read_DMA10_CURR_Y_COUNT()       bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val)   bfin_write16(DMA10_CURR_Y_COUNT,val)
+#define bfin_read_DMA10_IRQ_STATUS()         bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val)     bfin_write16(DMA10_IRQ_STATUS,val)
+#define bfin_read_DMA10_PERIPHERAL_MAP()     bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val) bfin_write16(DMA10_PERIPHERAL_MAP,val)
+
+#define bfin_read_DMA11_CONFIG()             bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val)         bfin_write16(DMA11_CONFIG,val)
+#define bfin_read_DMA11_NEXT_DESC_PTR()      bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val)  bfin_write32(DMA11_NEXT_DESC_PTR,val)
+#define bfin_read_DMA11_START_ADDR()         bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val)     bfin_write32(DMA11_START_ADDR,val)
+#define bfin_read_DMA11_X_COUNT()            bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val)        bfin_write16(DMA11_X_COUNT,val)
+#define bfin_read_DMA11_Y_COUNT()            bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val)        bfin_write16(DMA11_Y_COUNT,val)
+#define bfin_read_DMA11_X_MODIFY()           bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val)       bfin_write16(DMA11_X_MODIFY,val)
+#define bfin_read_DMA11_Y_MODIFY()           bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val)       bfin_write16(DMA11_Y_MODIFY,val)
+#define bfin_read_DMA11_CURR_DESC_PTR()      bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val)  bfin_write32(DMA11_CURR_DESC_PTR,val)
+#define bfin_read_DMA11_CURR_ADDR()          bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val)      bfin_write32(DMA11_CURR_ADDR,val)
+#define bfin_read_DMA11_CURR_X_COUNT()       bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val)   bfin_write16(DMA11_CURR_X_COUNT,val)
+#define bfin_read_DMA11_CURR_Y_COUNT()       bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val)   bfin_write16(DMA11_CURR_Y_COUNT,val)
+#define bfin_read_DMA11_IRQ_STATUS()         bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val)     bfin_write16(DMA11_IRQ_STATUS,val)
+#define bfin_read_DMA11_PERIPHERAL_MAP()     bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val) bfin_write16(DMA11_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_D0_CONFIG()           bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)       bfin_write16(MDMA_D0_CONFIG,val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR()    bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D0_START_ADDR()       bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)   bfin_write32(MDMA_D0_START_ADDR,val)
+#define bfin_read_MDMA_D0_X_COUNT()          bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)      bfin_write16(MDMA_D0_X_COUNT,val)
+#define bfin_read_MDMA_D0_Y_COUNT()          bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)      bfin_write16(MDMA_D0_Y_COUNT,val)
+#define bfin_read_MDMA_D0_X_MODIFY()         bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)     bfin_write16(MDMA_D0_X_MODIFY,val)
+#define bfin_read_MDMA_D0_Y_MODIFY()         bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)     bfin_write16(MDMA_D0_Y_MODIFY,val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR()    bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_write32(MDMA_D0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D0_CURR_ADDR()        bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)    bfin_write32(MDMA_D0_CURR_ADDR,val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()     bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val) bfin_write16(MDMA_D0_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()     bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val) bfin_write16(MDMA_D0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()       bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)   bfin_write16(MDMA_D0_IRQ_STATUS,val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()   bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA_D0_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_S0_CONFIG()           bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)       bfin_write16(MDMA_S0_CONFIG,val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR()    bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA_S0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S0_START_ADDR()       bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)   bfin_write32(MDMA_S0_START_ADDR,val)
+#define bfin_read_MDMA_S0_X_COUNT()          bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)      bfin_write16(MDMA_S0_X_COUNT,val)
+#define bfin_read_MDMA_S0_Y_COUNT()          bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)      bfin_write16(MDMA_S0_Y_COUNT,val)
+#define bfin_read_MDMA_S0_X_MODIFY()         bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)     bfin_write16(MDMA_S0_X_MODIFY,val)
+#define bfin_read_MDMA_S0_Y_MODIFY()         bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)     bfin_write16(MDMA_S0_Y_MODIFY,val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR()    bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_write32(MDMA_S0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S0_CURR_ADDR()        bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)    bfin_write32(MDMA_S0_CURR_ADDR,val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()     bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val) bfin_write16(MDMA_S0_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()     bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val) bfin_write16(MDMA_S0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()       bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)   bfin_write16(MDMA_S0_IRQ_STATUS,val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()   bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA_S0_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_D1_CONFIG()           bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)       bfin_write16(MDMA_D1_CONFIG,val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR()    bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA_D1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D1_START_ADDR()       bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)   bfin_write32(MDMA_D1_START_ADDR,val)
+#define bfin_read_MDMA_D1_X_COUNT()          bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)      bfin_write16(MDMA_D1_X_COUNT,val)
+#define bfin_read_MDMA_D1_Y_COUNT()          bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)      bfin_write16(MDMA_D1_Y_COUNT,val)
+#define bfin_read_MDMA_D1_X_MODIFY()         bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)     bfin_write16(MDMA_D1_X_MODIFY,val)
+#define bfin_read_MDMA_D1_Y_MODIFY()         bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)     bfin_write16(MDMA_D1_Y_MODIFY,val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR()    bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D1_CURR_ADDR()        bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)    bfin_write32(MDMA_D1_CURR_ADDR,val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()     bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val) bfin_write16(MDMA_D1_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()     bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val) bfin_write16(MDMA_D1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()       bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)   bfin_write16(MDMA_D1_IRQ_STATUS,val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()   bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA_D1_PERIPHERAL_MAP,val)
+
+#define bfin_read_MDMA_S1_CONFIG()           bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)       bfin_write16(MDMA_S1_CONFIG,val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR()    bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA_S1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S1_START_ADDR()       bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)   bfin_write32(MDMA_S1_START_ADDR,val)
+#define bfin_read_MDMA_S1_X_COUNT()          bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)      bfin_write16(MDMA_S1_X_COUNT,val)
+#define bfin_read_MDMA_S1_Y_COUNT()          bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)      bfin_write16(MDMA_S1_Y_COUNT,val)
+#define bfin_read_MDMA_S1_X_MODIFY()         bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)     bfin_write16(MDMA_S1_X_MODIFY,val)
+#define bfin_read_MDMA_S1_Y_MODIFY()         bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)     bfin_write16(MDMA_S1_Y_MODIFY,val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR()    bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S1_CURR_ADDR()        bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)    bfin_write32(MDMA_S1_CURR_ADDR,val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()     bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val) bfin_write16(MDMA_S1_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()     bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val) bfin_write16(MDMA_S1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()       bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)   bfin_write16(MDMA_S1_IRQ_STATUS,val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()   bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA_S1_PERIPHERAL_MAP,val)
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)                                                     */
+#define bfin_read_PPI_CONTROL()              bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val)          bfin_write16(PPI_CONTROL,val)
+#define bfin_read_PPI_STATUS()               bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val)           bfin_write16(PPI_STATUS,val)
+#define bfin_clear_PPI_STATUS()              bfin_write_PPI_STATUS(0xFFFF)
+#define bfin_read_PPI_DELAY()                bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val)            bfin_write16(PPI_DELAY,val)
+#define bfin_read_PPI_COUNT()                bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val)            bfin_write16(PPI_COUNT,val)
+#define bfin_read_PPI_FRAME()                bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val)            bfin_write16(PPI_FRAME,val)
+
+/* Two-Wire Interface          (0xFFC01400 - 0xFFC014FF)                                                               */
+#define bfin_read_TWI_CLKDIV()               bfin_read16(TWI_CLKDIV)
+#define bfin_write_TWI_CLKDIV(val)           bfin_write16(TWI_CLKDIV,val)
+#define bfin_read_TWI_CONTROL()              bfin_read16(TWI_CONTROL)
+#define bfin_write_TWI_CONTROL(val)          bfin_write16(TWI_CONTROL,val)
+#define bfin_read_TWI_SLAVE_CTL()            bfin_read16(TWI_SLAVE_CTL)
+#define bfin_write_TWI_SLAVE_CTL(val)        bfin_write16(TWI_SLAVE_CTL,val)
+#define bfin_read_TWI_SLAVE_STAT()           bfin_read16(TWI_SLAVE_STAT)
+#define bfin_write_TWI_SLAVE_STAT(val)       bfin_write16(TWI_SLAVE_STAT,val)
+#define bfin_read_TWI_SLAVE_ADDR()           bfin_read16(TWI_SLAVE_ADDR)
+#define bfin_write_TWI_SLAVE_ADDR(val)       bfin_write16(TWI_SLAVE_ADDR,val)
+#define bfin_read_TWI_MASTER_CTL()           bfin_read16(TWI_MASTER_CTL)
+#define bfin_write_TWI_MASTER_CTL(val)       bfin_write16(TWI_MASTER_CTL,val)
+#define bfin_read_TWI_MASTER_STAT()          bfin_read16(TWI_MASTER_STAT)
+#define bfin_write_TWI_MASTER_STAT(val)      bfin_write16(TWI_MASTER_STAT,val)
+#define bfin_read_TWI_MASTER_ADDR()          bfin_read16(TWI_MASTER_ADDR)
+#define bfin_write_TWI_MASTER_ADDR(val)      bfin_write16(TWI_MASTER_ADDR,val)
+#define bfin_read_TWI_INT_STAT()             bfin_read16(TWI_INT_STAT)
+#define bfin_write_TWI_INT_STAT(val)         bfin_write16(TWI_INT_STAT,val)
+#define bfin_read_TWI_INT_MASK()             bfin_read16(TWI_INT_MASK)
+#define bfin_write_TWI_INT_MASK(val)         bfin_write16(TWI_INT_MASK,val)
+#define bfin_read_TWI_FIFO_CTL()             bfin_read16(TWI_FIFO_CTL)
+#define bfin_write_TWI_FIFO_CTL(val)         bfin_write16(TWI_FIFO_CTL,val)
+#define bfin_read_TWI_FIFO_STAT()            bfin_read16(TWI_FIFO_STAT)
+#define bfin_write_TWI_FIFO_STAT(val)        bfin_write16(TWI_FIFO_STAT,val)
+#define bfin_read_TWI_XMT_DATA8()            bfin_read16(TWI_XMT_DATA8)
+#define bfin_write_TWI_XMT_DATA8(val)        bfin_write16(TWI_XMT_DATA8,val)
+#define bfin_read_TWI_XMT_DATA16()           bfin_read16(TWI_XMT_DATA16)
+#define bfin_write_TWI_XMT_DATA16(val)       bfin_write16(TWI_XMT_DATA16,val)
+#define bfin_read_TWI_RCV_DATA8()            bfin_read16(TWI_RCV_DATA8)
+#define bfin_write_TWI_RCV_DATA8(val)        bfin_write16(TWI_RCV_DATA8,val)
+#define bfin_read_TWI_RCV_DATA16()           bfin_read16(TWI_RCV_DATA16)
+#define bfin_write_TWI_RCV_DATA16(val)       bfin_write16(TWI_RCV_DATA16,val)
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)                                                                */
+#define bfin_read_PORTGIO()                  bfin_read16(PORTGIO)
+#define bfin_write_PORTGIO(val)              bfin_write16(PORTGIO,val)
+#define bfin_read_PORTGIO_CLEAR()            bfin_read16(PORTGIO_CLEAR)
+#define bfin_write_PORTGIO_CLEAR(val)        bfin_write16(PORTGIO_CLEAR,val)
+#define bfin_read_PORTGIO_SET()              bfin_read16(PORTGIO_SET)
+#define bfin_write_PORTGIO_SET(val)          bfin_write16(PORTGIO_SET,val)
+#define bfin_read_PORTGIO_TOGGLE()           bfin_read16(PORTGIO_TOGGLE)
+#define bfin_write_PORTGIO_TOGGLE(val)       bfin_write16(PORTGIO_TOGGLE,val)
+#define bfin_read_PORTGIO_MASKA()            bfin_read16(PORTGIO_MASKA)
+#define bfin_write_PORTGIO_MASKA(val)        bfin_write16(PORTGIO_MASKA,val)
+#define bfin_read_PORTGIO_MASKA_CLEAR()      bfin_read16(PORTGIO_MASKA_CLEAR)
+#define bfin_write_PORTGIO_MASKA_CLEAR(val)  bfin_write16(PORTGIO_MASKA_CLEAR,val)
+#define bfin_read_PORTGIO_MASKA_SET()        bfin_read16(PORTGIO_MASKA_SET)
+#define bfin_write_PORTGIO_MASKA_SET(val)    bfin_write16(PORTGIO_MASKA_SET,val)
+#define bfin_read_PORTGIO_MASKA_TOGGLE()     bfin_read16(PORTGIO_MASKA_TOGGLE)
+#define bfin_write_PORTGIO_MASKA_TOGGLE(val) bfin_write16(PORTGIO_MASKA_TOGGLE,val)
+#define bfin_read_PORTGIO_MASKB()            bfin_read16(PORTGIO_MASKB)
+#define bfin_write_PORTGIO_MASKB(val)        bfin_write16(PORTGIO_MASKB,val)
+#define bfin_read_PORTGIO_MASKB_CLEAR()      bfin_read16(PORTGIO_MASKB_CLEAR)
+#define bfin_write_PORTGIO_MASKB_CLEAR(val)  bfin_write16(PORTGIO_MASKB_CLEAR,val)
+#define bfin_read_PORTGIO_MASKB_SET()        bfin_read16(PORTGIO_MASKB_SET)
+#define bfin_write_PORTGIO_MASKB_SET(val)    bfin_write16(PORTGIO_MASKB_SET,val)
+#define bfin_read_PORTGIO_MASKB_TOGGLE()     bfin_read16(PORTGIO_MASKB_TOGGLE)
+#define bfin_write_PORTGIO_MASKB_TOGGLE(val) bfin_write16(PORTGIO_MASKB_TOGGLE,val)
+#define bfin_read_PORTGIO_DIR()              bfin_read16(PORTGIO_DIR)
+#define bfin_write_PORTGIO_DIR(val)          bfin_write16(PORTGIO_DIR,val)
+#define bfin_read_PORTGIO_POLAR()            bfin_read16(PORTGIO_POLAR)
+#define bfin_write_PORTGIO_POLAR(val)        bfin_write16(PORTGIO_POLAR,val)
+#define bfin_read_PORTGIO_EDGE()             bfin_read16(PORTGIO_EDGE)
+#define bfin_write_PORTGIO_EDGE(val)         bfin_write16(PORTGIO_EDGE,val)
+#define bfin_read_PORTGIO_BOTH()             bfin_read16(PORTGIO_BOTH)
+#define bfin_write_PORTGIO_BOTH(val)         bfin_write16(PORTGIO_BOTH,val)
+#define bfin_read_PORTGIO_INEN()             bfin_read16(PORTGIO_INEN)
+#define bfin_write_PORTGIO_INEN(val)         bfin_write16(PORTGIO_INEN,val)
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)                                                                */
+#define bfin_read_PORTHIO()                  bfin_read16(PORTHIO)
+#define bfin_write_PORTHIO(val)              bfin_write16(PORTHIO,val)
+#define bfin_read_PORTHIO_CLEAR()            bfin_read16(PORTHIO_CLEAR)
+#define bfin_write_PORTHIO_CLEAR(val)        bfin_write16(PORTHIO_CLEAR,val)
+#define bfin_read_PORTHIO_SET()              bfin_read16(PORTHIO_SET)
+#define bfin_write_PORTHIO_SET(val)          bfin_write16(PORTHIO_SET,val)
+#define bfin_read_PORTHIO_TOGGLE()           bfin_read16(PORTHIO_TOGGLE)
+#define bfin_write_PORTHIO_TOGGLE(val)       bfin_write16(PORTHIO_TOGGLE,val)
+#define bfin_read_PORTHIO_MASKA()            bfin_read16(PORTHIO_MASKA)
+#define bfin_write_PORTHIO_MASKA(val)        bfin_write16(PORTHIO_MASKA,val)
+#define bfin_read_PORTHIO_MASKA_CLEAR()      bfin_read16(PORTHIO_MASKA_CLEAR)
+#define bfin_write_PORTHIO_MASKA_CLEAR(val)  bfin_write16(PORTHIO_MASKA_CLEAR,val)
+#define bfin_read_PORTHIO_MASKA_SET()        bfin_read16(PORTHIO_MASKA_SET)
+#define bfin_write_PORTHIO_MASKA_SET(val)    bfin_write16(PORTHIO_MASKA_SET,val)
+#define bfin_read_PORTHIO_MASKA_TOGGLE()     bfin_read16(PORTHIO_MASKA_TOGGLE)
+#define bfin_write_PORTHIO_MASKA_TOGGLE(val) bfin_write16(PORTHIO_MASKA_TOGGLE,val)
+#define bfin_read_PORTHIO_MASKB()            bfin_read16(PORTHIO_MASKB)
+#define bfin_write_PORTHIO_MASKB(val)        bfin_write16(PORTHIO_MASKB,val)
+#define bfin_read_PORTHIO_MASKB_CLEAR()      bfin_read16(PORTHIO_MASKB_CLEAR)
+#define bfin_write_PORTHIO_MASKB_CLEAR(val)  bfin_write16(PORTHIO_MASKB_CLEAR,val)
+#define bfin_read_PORTHIO_MASKB_SET()        bfin_read16(PORTHIO_MASKB_SET)
+#define bfin_write_PORTHIO_MASKB_SET(val)    bfin_write16(PORTHIO_MASKB_SET,val)
+#define bfin_read_PORTHIO_MASKB_TOGGLE()     bfin_read16(PORTHIO_MASKB_TOGGLE)
+#define bfin_write_PORTHIO_MASKB_TOGGLE(val) bfin_write16(PORTHIO_MASKB_TOGGLE,val)
+#define bfin_read_PORTHIO_DIR()              bfin_read16(PORTHIO_DIR)
+#define bfin_write_PORTHIO_DIR(val)          bfin_write16(PORTHIO_DIR,val)
+#define bfin_read_PORTHIO_POLAR()            bfin_read16(PORTHIO_POLAR)
+#define bfin_write_PORTHIO_POLAR(val)        bfin_write16(PORTHIO_POLAR,val)
+#define bfin_read_PORTHIO_EDGE()             bfin_read16(PORTHIO_EDGE)
+#define bfin_write_PORTHIO_EDGE(val)         bfin_write16(PORTHIO_EDGE,val)
+#define bfin_read_PORTHIO_BOTH()             bfin_read16(PORTHIO_BOTH)
+#define bfin_write_PORTHIO_BOTH(val)         bfin_write16(PORTHIO_BOTH,val)
+#define bfin_read_PORTHIO_INEN()             bfin_read16(PORTHIO_INEN)
+#define bfin_write_PORTHIO_INEN(val)         bfin_write16(PORTHIO_INEN,val)
+
+/* UART1 Controller            (0xFFC02000 - 0xFFC020FF)                                                               */
+#define bfin_read_UART1_THR()                bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val)            bfin_write16(UART1_THR,val)
+#define bfin_read_UART1_RBR()                bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val)            bfin_write16(UART1_RBR,val)
+#define bfin_read_UART1_DLL()                bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val)            bfin_write16(UART1_DLL,val)
+#define bfin_read_UART1_IER()                bfin_read16(UART1_IER)
+#define bfin_write_UART1_IER(val)            bfin_write16(UART1_IER,val)
+#define bfin_read_UART1_DLH()                bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val)            bfin_write16(UART1_DLH,val)
+#define bfin_read_UART1_IIR()                bfin_read16(UART1_IIR)
+#define bfin_write_UART1_IIR(val)            bfin_write16(UART1_IIR,val)
+#define bfin_read_UART1_LCR()                bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val)            bfin_write16(UART1_LCR,val)
+#define bfin_read_UART1_MCR()                bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val)            bfin_write16(UART1_MCR,val)
+#define bfin_read_UART1_LSR()                bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val)            bfin_write16(UART1_LSR,val)
+#define bfin_read_UART1_MSR()                bfin_read16(UART1_MSR)
+#define bfin_write_UART1_MSR(val)            bfin_write16(UART1_MSR,val)
+#define bfin_read_UART1_SCR()                bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val)            bfin_write16(UART1_SCR,val)
+#define bfin_read_UART1_GCTL()               bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val)           bfin_write16(UART1_GCTL,val)
+
+/* CAN Controller              (0xFFC02A00 - 0xFFC02FFF)                                                               */
+/* For Mailboxes 0-15 */
+#define bfin_read_CAN_MC1()                  bfin_read16(CAN_MC1)
+#define bfin_write_CAN_MC1(val)              bfin_write16(CAN_MC1,val)
+#define bfin_read_CAN_MD1()                  bfin_read16(CAN_MD1)
+#define bfin_write_CAN_MD1(val)              bfin_write16(CAN_MD1,val)
+#define bfin_read_CAN_TRS1()                 bfin_read16(CAN_TRS1)
+#define bfin_write_CAN_TRS1(val)             bfin_write16(CAN_TRS1,val)
+#define bfin_read_CAN_TRR1()                 bfin_read16(CAN_TRR1)
+#define bfin_write_CAN_TRR1(val)             bfin_write16(CAN_TRR1,val)
+#define bfin_read_CAN_TA1()                  bfin_read16(CAN_TA1)
+#define bfin_write_CAN_TA1(val)              bfin_write16(CAN_TA1,val)
+#define bfin_read_CAN_AA1()                  bfin_read16(CAN_AA1)
+#define bfin_write_CAN_AA1(val)              bfin_write16(CAN_AA1,val)
+#define bfin_read_CAN_RMP1()                 bfin_read16(CAN_RMP1)
+#define bfin_write_CAN_RMP1(val)             bfin_write16(CAN_RMP1,val)
+#define bfin_read_CAN_RML1()                 bfin_read16(CAN_RML1)
+#define bfin_write_CAN_RML1(val)             bfin_write16(CAN_RML1,val)
+#define bfin_read_CAN_MBTIF1()               bfin_read16(CAN_MBTIF1)
+#define bfin_write_CAN_MBTIF1(val)           bfin_write16(CAN_MBTIF1,val)
+#define bfin_read_CAN_MBRIF1()               bfin_read16(CAN_MBRIF1)
+#define bfin_write_CAN_MBRIF1(val)           bfin_write16(CAN_MBRIF1,val)
+#define bfin_read_CAN_MBIM1()                bfin_read16(CAN_MBIM1)
+#define bfin_write_CAN_MBIM1(val)            bfin_write16(CAN_MBIM1,val)
+#define bfin_read_CAN_RFH1()                 bfin_read16(CAN_RFH1)
+#define bfin_write_CAN_RFH1(val)             bfin_write16(CAN_RFH1,val)
+#define bfin_read_CAN_OPSS1()                bfin_read16(CAN_OPSS1)
+#define bfin_write_CAN_OPSS1(val)            bfin_write16(CAN_OPSS1,val)
+
+/* For Mailboxes 16-31 */
+#define bfin_read_CAN_MC2()                  bfin_read16(CAN_MC2)
+#define bfin_write_CAN_MC2(val)              bfin_write16(CAN_MC2,val)
+#define bfin_read_CAN_MD2()                  bfin_read16(CAN_MD2)
+#define bfin_write_CAN_MD2(val)              bfin_write16(CAN_MD2,val)
+#define bfin_read_CAN_TRS2()                 bfin_read16(CAN_TRS2)
+#define bfin_write_CAN_TRS2(val)             bfin_write16(CAN_TRS2,val)
+#define bfin_read_CAN_TRR2()                 bfin_read16(CAN_TRR2)
+#define bfin_write_CAN_TRR2(val)             bfin_write16(CAN_TRR2,val)
+#define bfin_read_CAN_TA2()                  bfin_read16(CAN_TA2)
+#define bfin_write_CAN_TA2(val)              bfin_write16(CAN_TA2,val)
+#define bfin_read_CAN_AA2()                  bfin_read16(CAN_AA2)
+#define bfin_write_CAN_AA2(val)              bfin_write16(CAN_AA2,val)
+#define bfin_read_CAN_RMP2()                 bfin_read16(CAN_RMP2)
+#define bfin_write_CAN_RMP2(val)             bfin_write16(CAN_RMP2,val)
+#define bfin_read_CAN_RML2()                 bfin_read16(CAN_RML2)
+#define bfin_write_CAN_RML2(val)             bfin_write16(CAN_RML2,val)
+#define bfin_read_CAN_MBTIF2()               bfin_read16(CAN_MBTIF2)
+#define bfin_write_CAN_MBTIF2(val)           bfin_write16(CAN_MBTIF2,val)
+#define bfin_read_CAN_MBRIF2()               bfin_read16(CAN_MBRIF2)
+#define bfin_write_CAN_MBRIF2(val)           bfin_write16(CAN_MBRIF2,val)
+#define bfin_read_CAN_MBIM2()                bfin_read16(CAN_MBIM2)
+#define bfin_write_CAN_MBIM2(val)            bfin_write16(CAN_MBIM2,val)
+#define bfin_read_CAN_RFH2()                 bfin_read16(CAN_RFH2)
+#define bfin_write_CAN_RFH2(val)             bfin_write16(CAN_RFH2,val)
+#define bfin_read_CAN_OPSS2()                bfin_read16(CAN_OPSS2)
+#define bfin_write_CAN_OPSS2(val)            bfin_write16(CAN_OPSS2,val)
+
+#define bfin_read_CAN_CLOCK()                bfin_read16(CAN_CLOCK)
+#define bfin_write_CAN_CLOCK(val)            bfin_write16(CAN_CLOCK,val)
+#define bfin_read_CAN_TIMING()               bfin_read16(CAN_TIMING)
+#define bfin_write_CAN_TIMING(val)           bfin_write16(CAN_TIMING,val)
+#define bfin_read_CAN_DEBUG()                bfin_read16(CAN_DEBUG)
+#define bfin_write_CAN_DEBUG(val)            bfin_write16(CAN_DEBUG,val)
+#define bfin_read_CAN_STATUS()               bfin_read16(CAN_STATUS)
+#define bfin_write_CAN_STATUS(val)           bfin_write16(CAN_STATUS,val)
+#define bfin_read_CAN_CEC()                  bfin_read16(CAN_CEC)
+#define bfin_write_CAN_CEC(val)              bfin_write16(CAN_CEC,val)
+#define bfin_read_CAN_GIS()                  bfin_read16(CAN_GIS)
+#define bfin_write_CAN_GIS(val)              bfin_write16(CAN_GIS,val)
+#define bfin_read_CAN_GIM()                  bfin_read16(CAN_GIM)
+#define bfin_write_CAN_GIM(val)              bfin_write16(CAN_GIM,val)
+#define bfin_read_CAN_GIF()                  bfin_read16(CAN_GIF)
+#define bfin_write_CAN_GIF(val)              bfin_write16(CAN_GIF,val)
+#define bfin_read_CAN_CONTROL()              bfin_read16(CAN_CONTROL)
+#define bfin_write_CAN_CONTROL(val)          bfin_write16(CAN_CONTROL,val)
+#define bfin_read_CAN_INTR()                 bfin_read16(CAN_INTR)
+#define bfin_write_CAN_INTR(val)             bfin_write16(CAN_INTR,val)
+#define bfin_read_CAN_SFCMVER()              bfin_read16(CAN_SFCMVER)
+#define bfin_write_CAN_SFCMVER(val)          bfin_write16(CAN_SFCMVER,val)
+#define bfin_read_CAN_MBTD()                 bfin_read16(CAN_MBTD)
+#define bfin_write_CAN_MBTD(val)             bfin_write16(CAN_MBTD,val)
+#define bfin_read_CAN_EWR()                  bfin_read16(CAN_EWR)
+#define bfin_write_CAN_EWR(val)              bfin_write16(CAN_EWR,val)
+#define bfin_read_CAN_ESR()                  bfin_read16(CAN_ESR)
+#define bfin_write_CAN_ESR(val)              bfin_write16(CAN_ESR,val)
+#define bfin_read_CAN_UCREG()                bfin_read16(CAN_UCREG)
+#define bfin_write_CAN_UCREG(val)            bfin_write16(CAN_UCREG,val)
+#define bfin_read_CAN_UCCNT()                bfin_read16(CAN_UCCNT)
+#define bfin_write_CAN_UCCNT(val)            bfin_write16(CAN_UCCNT,val)
+#define bfin_read_CAN_UCRC()                 bfin_read16(CAN_UCRC)
+#define bfin_write_CAN_UCRC(val)             bfin_write16(CAN_UCRC,val)
+#define bfin_read_CAN_UCCNF()                bfin_read16(CAN_UCCNF)
+#define bfin_write_CAN_UCCNF(val)            bfin_write16(CAN_UCCNF,val)
+#define bfin_read_CAN_SFCMVER2()             bfin_read16(CAN_SFCMVER2)
+#define bfin_write_CAN_SFCMVER2(val)         bfin_write16(CAN_SFCMVER2,val)
+
+/* Mailbox Acceptance Masks */
+#define bfin_read_CAN_AM00L()                bfin_read16(CAN_AM00L)
+#define bfin_write_CAN_AM00L(val)            bfin_write16(CAN_AM00L,val)
+#define bfin_read_CAN_AM00H()                bfin_read16(CAN_AM00H)
+#define bfin_write_CAN_AM00H(val)            bfin_write16(CAN_AM00H,val)
+#define bfin_read_CAN_AM01L()                bfin_read16(CAN_AM01L)
+#define bfin_write_CAN_AM01L(val)            bfin_write16(CAN_AM01L,val)
+#define bfin_read_CAN_AM01H()                bfin_read16(CAN_AM01H)
+#define bfin_write_CAN_AM01H(val)            bfin_write16(CAN_AM01H,val)
+#define bfin_read_CAN_AM02L()                bfin_read16(CAN_AM02L)
+#define bfin_write_CAN_AM02L(val)            bfin_write16(CAN_AM02L,val)
+#define bfin_read_CAN_AM02H()                bfin_read16(CAN_AM02H)
+#define bfin_write_CAN_AM02H(val)            bfin_write16(CAN_AM02H,val)
+#define bfin_read_CAN_AM03L()                bfin_read16(CAN_AM03L)
+#define bfin_write_CAN_AM03L(val)            bfin_write16(CAN_AM03L,val)
+#define bfin_read_CAN_AM03H()                bfin_read16(CAN_AM03H)
+#define bfin_write_CAN_AM03H(val)            bfin_write16(CAN_AM03H,val)
+#define bfin_read_CAN_AM04L()                bfin_read16(CAN_AM04L)
+#define bfin_write_CAN_AM04L(val)            bfin_write16(CAN_AM04L,val)
+#define bfin_read_CAN_AM04H()                bfin_read16(CAN_AM04H)
+#define bfin_write_CAN_AM04H(val)            bfin_write16(CAN_AM04H,val)
+#define bfin_read_CAN_AM05L()                bfin_read16(CAN_AM05L)
+#define bfin_write_CAN_AM05L(val)            bfin_write16(CAN_AM05L,val)
+#define bfin_read_CAN_AM05H()                bfin_read16(CAN_AM05H)
+#define bfin_write_CAN_AM05H(val)            bfin_write16(CAN_AM05H,val)
+#define bfin_read_CAN_AM06L()                bfin_read16(CAN_AM06L)
+#define bfin_write_CAN_AM06L(val)            bfin_write16(CAN_AM06L,val)
+#define bfin_read_CAN_AM06H()                bfin_read16(CAN_AM06H)
+#define bfin_write_CAN_AM06H(val)            bfin_write16(CAN_AM06H,val)
+#define bfin_read_CAN_AM07L()                bfin_read16(CAN_AM07L)
+#define bfin_write_CAN_AM07L(val)            bfin_write16(CAN_AM07L,val)
+#define bfin_read_CAN_AM07H()                bfin_read16(CAN_AM07H)
+#define bfin_write_CAN_AM07H(val)            bfin_write16(CAN_AM07H,val)
+#define bfin_read_CAN_AM08L()                bfin_read16(CAN_AM08L)
+#define bfin_write_CAN_AM08L(val)            bfin_write16(CAN_AM08L,val)
+#define bfin_read_CAN_AM08H()                bfin_read16(CAN_AM08H)
+#define bfin_write_CAN_AM08H(val)            bfin_write16(CAN_AM08H,val)
+#define bfin_read_CAN_AM09L()                bfin_read16(CAN_AM09L)
+#define bfin_write_CAN_AM09L(val)            bfin_write16(CAN_AM09L,val)
+#define bfin_read_CAN_AM09H()                bfin_read16(CAN_AM09H)
+#define bfin_write_CAN_AM09H(val)            bfin_write16(CAN_AM09H,val)
+#define bfin_read_CAN_AM10L()                bfin_read16(CAN_AM10L)
+#define bfin_write_CAN_AM10L(val)            bfin_write16(CAN_AM10L,val)
+#define bfin_read_CAN_AM10H()                bfin_read16(CAN_AM10H)
+#define bfin_write_CAN_AM10H(val)            bfin_write16(CAN_AM10H,val)
+#define bfin_read_CAN_AM11L()                bfin_read16(CAN_AM11L)
+#define bfin_write_CAN_AM11L(val)            bfin_write16(CAN_AM11L,val)
+#define bfin_read_CAN_AM11H()                bfin_read16(CAN_AM11H)
+#define bfin_write_CAN_AM11H(val)            bfin_write16(CAN_AM11H,val)
+#define bfin_read_CAN_AM12L()                bfin_read16(CAN_AM12L)
+#define bfin_write_CAN_AM12L(val)            bfin_write16(CAN_AM12L,val)
+#define bfin_read_CAN_AM12H()                bfin_read16(CAN_AM12H)
+#define bfin_write_CAN_AM12H(val)            bfin_write16(CAN_AM12H,val)
+#define bfin_read_CAN_AM13L()                bfin_read16(CAN_AM13L)
+#define bfin_write_CAN_AM13L(val)            bfin_write16(CAN_AM13L,val)
+#define bfin_read_CAN_AM13H()                bfin_read16(CAN_AM13H)
+#define bfin_write_CAN_AM13H(val)            bfin_write16(CAN_AM13H,val)
+#define bfin_read_CAN_AM14L()                bfin_read16(CAN_AM14L)
+#define bfin_write_CAN_AM14L(val)            bfin_write16(CAN_AM14L,val)
+#define bfin_read_CAN_AM14H()                bfin_read16(CAN_AM14H)
+#define bfin_write_CAN_AM14H(val)            bfin_write16(CAN_AM14H,val)
+#define bfin_read_CAN_AM15L()                bfin_read16(CAN_AM15L)
+#define bfin_write_CAN_AM15L(val)            bfin_write16(CAN_AM15L,val)
+#define bfin_read_CAN_AM15H()                bfin_read16(CAN_AM15H)
+#define bfin_write_CAN_AM15H(val)            bfin_write16(CAN_AM15H,val)
+
+#define bfin_read_CAN_AM16L()                bfin_read16(CAN_AM16L)
+#define bfin_write_CAN_AM16L(val)            bfin_write16(CAN_AM16L,val)
+#define bfin_read_CAN_AM16H()                bfin_read16(CAN_AM16H)
+#define bfin_write_CAN_AM16H(val)            bfin_write16(CAN_AM16H,val)
+#define bfin_read_CAN_AM17L()                bfin_read16(CAN_AM17L)
+#define bfin_write_CAN_AM17L(val)            bfin_write16(CAN_AM17L,val)
+#define bfin_read_CAN_AM17H()                bfin_read16(CAN_AM17H)
+#define bfin_write_CAN_AM17H(val)            bfin_write16(CAN_AM17H,val)
+#define bfin_read_CAN_AM18L()                bfin_read16(CAN_AM18L)
+#define bfin_write_CAN_AM18L(val)            bfin_write16(CAN_AM18L,val)
+#define bfin_read_CAN_AM18H()                bfin_read16(CAN_AM18H)
+#define bfin_write_CAN_AM18H(val)            bfin_write16(CAN_AM18H,val)
+#define bfin_read_CAN_AM19L()                bfin_read16(CAN_AM19L)
+#define bfin_write_CAN_AM19L(val)            bfin_write16(CAN_AM19L,val)
+#define bfin_read_CAN_AM19H()                bfin_read16(CAN_AM19H)
+#define bfin_write_CAN_AM19H(val)            bfin_write16(CAN_AM19H,val)
+#define bfin_read_CAN_AM20L()                bfin_read16(CAN_AM20L)
+#define bfin_write_CAN_AM20L(val)            bfin_write16(CAN_AM20L,val)
+#define bfin_read_CAN_AM20H()                bfin_read16(CAN_AM20H)
+#define bfin_write_CAN_AM20H(val)            bfin_write16(CAN_AM20H,val)
+#define bfin_read_CAN_AM21L()                bfin_read16(CAN_AM21L)
+#define bfin_write_CAN_AM21L(val)            bfin_write16(CAN_AM21L,val)
+#define bfin_read_CAN_AM21H()                bfin_read16(CAN_AM21H)
+#define bfin_write_CAN_AM21H(val)            bfin_write16(CAN_AM21H,val)
+#define bfin_read_CAN_AM22L()                bfin_read16(CAN_AM22L)
+#define bfin_write_CAN_AM22L(val)            bfin_write16(CAN_AM22L,val)
+#define bfin_read_CAN_AM22H()                bfin_read16(CAN_AM22H)
+#define bfin_write_CAN_AM22H(val)            bfin_write16(CAN_AM22H,val)
+#define bfin_read_CAN_AM23L()                bfin_read16(CAN_AM23L)
+#define bfin_write_CAN_AM23L(val)            bfin_write16(CAN_AM23L,val)
+#define bfin_read_CAN_AM23H()                bfin_read16(CAN_AM23H)
+#define bfin_write_CAN_AM23H(val)            bfin_write16(CAN_AM23H,val)
+#define bfin_read_CAN_AM24L()                bfin_read16(CAN_AM24L)
+#define bfin_write_CAN_AM24L(val)            bfin_write16(CAN_AM24L,val)
+#define bfin_read_CAN_AM24H()                bfin_read16(CAN_AM24H)
+#define bfin_write_CAN_AM24H(val)            bfin_write16(CAN_AM24H,val)
+#define bfin_read_CAN_AM25L()                bfin_read16(CAN_AM25L)
+#define bfin_write_CAN_AM25L(val)            bfin_write16(CAN_AM25L,val)
+#define bfin_read_CAN_AM25H()                bfin_read16(CAN_AM25H)
+#define bfin_write_CAN_AM25H(val)            bfin_write16(CAN_AM25H,val)
+#define bfin_read_CAN_AM26L()                bfin_read16(CAN_AM26L)
+#define bfin_write_CAN_AM26L(val)            bfin_write16(CAN_AM26L,val)
+#define bfin_read_CAN_AM26H()                bfin_read16(CAN_AM26H)
+#define bfin_write_CAN_AM26H(val)            bfin_write16(CAN_AM26H,val)
+#define bfin_read_CAN_AM27L()                bfin_read16(CAN_AM27L)
+#define bfin_write_CAN_AM27L(val)            bfin_write16(CAN_AM27L,val)
+#define bfin_read_CAN_AM27H()                bfin_read16(CAN_AM27H)
+#define bfin_write_CAN_AM27H(val)            bfin_write16(CAN_AM27H,val)
+#define bfin_read_CAN_AM28L()                bfin_read16(CAN_AM28L)
+#define bfin_write_CAN_AM28L(val)            bfin_write16(CAN_AM28L,val)
+#define bfin_read_CAN_AM28H()                bfin_read16(CAN_AM28H)
+#define bfin_write_CAN_AM28H(val)            bfin_write16(CAN_AM28H,val)
+#define bfin_read_CAN_AM29L()                bfin_read16(CAN_AM29L)
+#define bfin_write_CAN_AM29L(val)            bfin_write16(CAN_AM29L,val)
+#define bfin_read_CAN_AM29H()                bfin_read16(CAN_AM29H)
+#define bfin_write_CAN_AM29H(val)            bfin_write16(CAN_AM29H,val)
+#define bfin_read_CAN_AM30L()                bfin_read16(CAN_AM30L)
+#define bfin_write_CAN_AM30L(val)            bfin_write16(CAN_AM30L,val)
+#define bfin_read_CAN_AM30H()                bfin_read16(CAN_AM30H)
+#define bfin_write_CAN_AM30H(val)            bfin_write16(CAN_AM30H,val)
+#define bfin_read_CAN_AM31L()                bfin_read16(CAN_AM31L)
+#define bfin_write_CAN_AM31L(val)            bfin_write16(CAN_AM31L,val)
+#define bfin_read_CAN_AM31H()                bfin_read16(CAN_AM31H)
+#define bfin_write_CAN_AM31H(val)            bfin_write16(CAN_AM31H,val)
+
+/* CAN Acceptance Mask Area Macros     */
+#define bfin_read_CAN_AM_L(x)()              bfin_read16(CAN_AM_L(x))
+#define bfin_write_CAN_AM_L(x)(val)          bfin_write16(CAN_AM_L(x),val)
+#define bfin_read_CAN_AM_H(x)()              bfin_read16(CAN_AM_H(x))
+#define bfin_write_CAN_AM_H(x)(val)          bfin_write16(CAN_AM_H(x),val)
+
+/* Mailbox Registers */
+#define bfin_read_CAN_MB00_ID1()             bfin_read16(CAN_MB00_ID1)
+#define bfin_write_CAN_MB00_ID1(val)         bfin_write16(CAN_MB00_ID1,val)
+#define bfin_read_CAN_MB00_ID0()             bfin_read16(CAN_MB00_ID0)
+#define bfin_write_CAN_MB00_ID0(val)         bfin_write16(CAN_MB00_ID0,val)
+#define bfin_read_CAN_MB00_TIMESTAMP()       bfin_read16(CAN_MB00_TIMESTAMP)
+#define bfin_write_CAN_MB00_TIMESTAMP(val)   bfin_write16(CAN_MB00_TIMESTAMP,val)
+#define bfin_read_CAN_MB00_LENGTH()          bfin_read16(CAN_MB00_LENGTH)
+#define bfin_write_CAN_MB00_LENGTH(val)      bfin_write16(CAN_MB00_LENGTH,val)
+#define bfin_read_CAN_MB00_DATA3()           bfin_read16(CAN_MB00_DATA3)
+#define bfin_write_CAN_MB00_DATA3(val)       bfin_write16(CAN_MB00_DATA3,val)
+#define bfin_read_CAN_MB00_DATA2()           bfin_read16(CAN_MB00_DATA2)
+#define bfin_write_CAN_MB00_DATA2(val)       bfin_write16(CAN_MB00_DATA2,val)
+#define bfin_read_CAN_MB00_DATA1()           bfin_read16(CAN_MB00_DATA1)
+#define bfin_write_CAN_MB00_DATA1(val)       bfin_write16(CAN_MB00_DATA1,val)
+#define bfin_read_CAN_MB00_DATA0()           bfin_read16(CAN_MB00_DATA0)
+#define bfin_write_CAN_MB00_DATA0(val)       bfin_write16(CAN_MB00_DATA0,val)
+
+#define bfin_read_CAN_MB01_ID1()             bfin_read16(CAN_MB01_ID1)
+#define bfin_write_CAN_MB01_ID1(val)         bfin_write16(CAN_MB01_ID1,val)
+#define bfin_read_CAN_MB01_ID0()             bfin_read16(CAN_MB01_ID0)
+#define bfin_write_CAN_MB01_ID0(val)         bfin_write16(CAN_MB01_ID0,val)
+#define bfin_read_CAN_MB01_TIMESTAMP()       bfin_read16(CAN_MB01_TIMESTAMP)
+#define bfin_write_CAN_MB01_TIMESTAMP(val)   bfin_write16(CAN_MB01_TIMESTAMP,val)
+#define bfin_read_CAN_MB01_LENGTH()          bfin_read16(CAN_MB01_LENGTH)
+#define bfin_write_CAN_MB01_LENGTH(val)      bfin_write16(CAN_MB01_LENGTH,val)
+#define bfin_read_CAN_MB01_DATA3()           bfin_read16(CAN_MB01_DATA3)
+#define bfin_write_CAN_MB01_DATA3(val)       bfin_write16(CAN_MB01_DATA3,val)
+#define bfin_read_CAN_MB01_DATA2()           bfin_read16(CAN_MB01_DATA2)
+#define bfin_write_CAN_MB01_DATA2(val)       bfin_write16(CAN_MB01_DATA2,val)
+#define bfin_read_CAN_MB01_DATA1()           bfin_read16(CAN_MB01_DATA1)
+#define bfin_write_CAN_MB01_DATA1(val)       bfin_write16(CAN_MB01_DATA1,val)
+#define bfin_read_CAN_MB01_DATA0()           bfin_read16(CAN_MB01_DATA0)
+#define bfin_write_CAN_MB01_DATA0(val)       bfin_write16(CAN_MB01_DATA0,val)
+
+#define bfin_read_CAN_MB02_ID1()             bfin_read16(CAN_MB02_ID1)
+#define bfin_write_CAN_MB02_ID1(val)         bfin_write16(CAN_MB02_ID1,val)
+#define bfin_read_CAN_MB02_ID0()             bfin_read16(CAN_MB02_ID0)
+#define bfin_write_CAN_MB02_ID0(val)         bfin_write16(CAN_MB02_ID0,val)
+#define bfin_read_CAN_MB02_TIMESTAMP()       bfin_read16(CAN_MB02_TIMESTAMP)
+#define bfin_write_CAN_MB02_TIMESTAMP(val)   bfin_write16(CAN_MB02_TIMESTAMP,val)
+#define bfin_read_CAN_MB02_LENGTH()          bfin_read16(CAN_MB02_LENGTH)
+#define bfin_write_CAN_MB02_LENGTH(val)      bfin_write16(CAN_MB02_LENGTH,val)
+#define bfin_read_CAN_MB02_DATA3()           bfin_read16(CAN_MB02_DATA3)
+#define bfin_write_CAN_MB02_DATA3(val)       bfin_write16(CAN_MB02_DATA3,val)
+#define bfin_read_CAN_MB02_DATA2()           bfin_read16(CAN_MB02_DATA2)
+#define bfin_write_CAN_MB02_DATA2(val)       bfin_write16(CAN_MB02_DATA2,val)
+#define bfin_read_CAN_MB02_DATA1()           bfin_read16(CAN_MB02_DATA1)
+#define bfin_write_CAN_MB02_DATA1(val)       bfin_write16(CAN_MB02_DATA1,val)
+#define bfin_read_CAN_MB02_DATA0()           bfin_read16(CAN_MB02_DATA0)
+#define bfin_write_CAN_MB02_DATA0(val)       bfin_write16(CAN_MB02_DATA0,val)
+
+#define bfin_read_CAN_MB03_ID1()             bfin_read16(CAN_MB03_ID1)
+#define bfin_write_CAN_MB03_ID1(val)         bfin_write16(CAN_MB03_ID1,val)
+#define bfin_read_CAN_MB03_ID0()             bfin_read16(CAN_MB03_ID0)
+#define bfin_write_CAN_MB03_ID0(val)         bfin_write16(CAN_MB03_ID0,val)
+#define bfin_read_CAN_MB03_TIMESTAMP()       bfin_read16(CAN_MB03_TIMESTAMP)
+#define bfin_write_CAN_MB03_TIMESTAMP(val)   bfin_write16(CAN_MB03_TIMESTAMP,val)
+#define bfin_read_CAN_MB03_LENGTH()          bfin_read16(CAN_MB03_LENGTH)
+#define bfin_write_CAN_MB03_LENGTH(val)      bfin_write16(CAN_MB03_LENGTH,val)
+#define bfin_read_CAN_MB03_DATA3()           bfin_read16(CAN_MB03_DATA3)
+#define bfin_write_CAN_MB03_DATA3(val)       bfin_write16(CAN_MB03_DATA3,val)
+#define bfin_read_CAN_MB03_DATA2()           bfin_read16(CAN_MB03_DATA2)
+#define bfin_write_CAN_MB03_DATA2(val)       bfin_write16(CAN_MB03_DATA2,val)
+#define bfin_read_CAN_MB03_DATA1()           bfin_read16(CAN_MB03_DATA1)
+#define bfin_write_CAN_MB03_DATA1(val)       bfin_write16(CAN_MB03_DATA1,val)
+#define bfin_read_CAN_MB03_DATA0()           bfin_read16(CAN_MB03_DATA0)
+#define bfin_write_CAN_MB03_DATA0(val)       bfin_write16(CAN_MB03_DATA0,val)
+
+#define bfin_read_CAN_MB04_ID1()             bfin_read16(CAN_MB04_ID1)
+#define bfin_write_CAN_MB04_ID1(val)         bfin_write16(CAN_MB04_ID1,val)
+#define bfin_read_CAN_MB04_ID0()             bfin_read16(CAN_MB04_ID0)
+#define bfin_write_CAN_MB04_ID0(val)         bfin_write16(CAN_MB04_ID0,val)
+#define bfin_read_CAN_MB04_TIMESTAMP()       bfin_read16(CAN_MB04_TIMESTAMP)
+#define bfin_write_CAN_MB04_TIMESTAMP(val)   bfin_write16(CAN_MB04_TIMESTAMP,val)
+#define bfin_read_CAN_MB04_LENGTH()          bfin_read16(CAN_MB04_LENGTH)
+#define bfin_write_CAN_MB04_LENGTH(val)      bfin_write16(CAN_MB04_LENGTH,val)
+#define bfin_read_CAN_MB04_DATA3()           bfin_read16(CAN_MB04_DATA3)
+#define bfin_write_CAN_MB04_DATA3(val)       bfin_write16(CAN_MB04_DATA3,val)
+#define bfin_read_CAN_MB04_DATA2()           bfin_read16(CAN_MB04_DATA2)
+#define bfin_write_CAN_MB04_DATA2(val)       bfin_write16(CAN_MB04_DATA2,val)
+#define bfin_read_CAN_MB04_DATA1()           bfin_read16(CAN_MB04_DATA1)
+#define bfin_write_CAN_MB04_DATA1(val)       bfin_write16(CAN_MB04_DATA1,val)
+#define bfin_read_CAN_MB04_DATA0()           bfin_read16(CAN_MB04_DATA0)
+#define bfin_write_CAN_MB04_DATA0(val)       bfin_write16(CAN_MB04_DATA0,val)
+
+#define bfin_read_CAN_MB05_ID1()             bfin_read16(CAN_MB05_ID1)
+#define bfin_write_CAN_MB05_ID1(val)         bfin_write16(CAN_MB05_ID1,val)
+#define bfin_read_CAN_MB05_ID0()             bfin_read16(CAN_MB05_ID0)
+#define bfin_write_CAN_MB05_ID0(val)         bfin_write16(CAN_MB05_ID0,val)
+#define bfin_read_CAN_MB05_TIMESTAMP()       bfin_read16(CAN_MB05_TIMESTAMP)
+#define bfin_write_CAN_MB05_TIMESTAMP(val)   bfin_write16(CAN_MB05_TIMESTAMP,val)
+#define bfin_read_CAN_MB05_LENGTH()          bfin_read16(CAN_MB05_LENGTH)
+#define bfin_write_CAN_MB05_LENGTH(val)      bfin_write16(CAN_MB05_LENGTH,val)
+#define bfin_read_CAN_MB05_DATA3()           bfin_read16(CAN_MB05_DATA3)
+#define bfin_write_CAN_MB05_DATA3(val)       bfin_write16(CAN_MB05_DATA3,val)
+#define bfin_read_CAN_MB05_DATA2()           bfin_read16(CAN_MB05_DATA2)
+#define bfin_write_CAN_MB05_DATA2(val)       bfin_write16(CAN_MB05_DATA2,val)
+#define bfin_read_CAN_MB05_DATA1()           bfin_read16(CAN_MB05_DATA1)
+#define bfin_write_CAN_MB05_DATA1(val)       bfin_write16(CAN_MB05_DATA1,val)
+#define bfin_read_CAN_MB05_DATA0()           bfin_read16(CAN_MB05_DATA0)
+#define bfin_write_CAN_MB05_DATA0(val)       bfin_write16(CAN_MB05_DATA0,val)
+
+#define bfin_read_CAN_MB06_ID1()             bfin_read16(CAN_MB06_ID1)
+#define bfin_write_CAN_MB06_ID1(val)         bfin_write16(CAN_MB06_ID1,val)
+#define bfin_read_CAN_MB06_ID0()             bfin_read16(CAN_MB06_ID0)
+#define bfin_write_CAN_MB06_ID0(val)         bfin_write16(CAN_MB06_ID0,val)
+#define bfin_read_CAN_MB06_TIMESTAMP()       bfin_read16(CAN_MB06_TIMESTAMP)
+#define bfin_write_CAN_MB06_TIMESTAMP(val)   bfin_write16(CAN_MB06_TIMESTAMP,val)
+#define bfin_read_CAN_MB06_LENGTH()          bfin_read16(CAN_MB06_LENGTH)
+#define bfin_write_CAN_MB06_LENGTH(val)      bfin_write16(CAN_MB06_LENGTH,val)
+#define bfin_read_CAN_MB06_DATA3()           bfin_read16(CAN_MB06_DATA3)
+#define bfin_write_CAN_MB06_DATA3(val)       bfin_write16(CAN_MB06_DATA3,val)
+#define bfin_read_CAN_MB06_DATA2()           bfin_read16(CAN_MB06_DATA2)
+#define bfin_write_CAN_MB06_DATA2(val)       bfin_write16(CAN_MB06_DATA2,val)
+#define bfin_read_CAN_MB06_DATA1()           bfin_read16(CAN_MB06_DATA1)
+#define bfin_write_CAN_MB06_DATA1(val)       bfin_write16(CAN_MB06_DATA1,val)
+#define bfin_read_CAN_MB06_DATA0()           bfin_read16(CAN_MB06_DATA0)
+#define bfin_write_CAN_MB06_DATA0(val)       bfin_write16(CAN_MB06_DATA0,val)
+
+#define bfin_read_CAN_MB07_ID1()             bfin_read16(CAN_MB07_ID1)
+#define bfin_write_CAN_MB07_ID1(val)         bfin_write16(CAN_MB07_ID1,val)
+#define bfin_read_CAN_MB07_ID0()             bfin_read16(CAN_MB07_ID0)
+#define bfin_write_CAN_MB07_ID0(val)         bfin_write16(CAN_MB07_ID0,val)
+#define bfin_read_CAN_MB07_TIMESTAMP()       bfin_read16(CAN_MB07_TIMESTAMP)
+#define bfin_write_CAN_MB07_TIMESTAMP(val)   bfin_write16(CAN_MB07_TIMESTAMP,val)
+#define bfin_read_CAN_MB07_LENGTH()          bfin_read16(CAN_MB07_LENGTH)
+#define bfin_write_CAN_MB07_LENGTH(val)      bfin_write16(CAN_MB07_LENGTH,val)
+#define bfin_read_CAN_MB07_DATA3()           bfin_read16(CAN_MB07_DATA3)
+#define bfin_write_CAN_MB07_DATA3(val)       bfin_write16(CAN_MB07_DATA3,val)
+#define bfin_read_CAN_MB07_DATA2()           bfin_read16(CAN_MB07_DATA2)
+#define bfin_write_CAN_MB07_DATA2(val)       bfin_write16(CAN_MB07_DATA2,val)
+#define bfin_read_CAN_MB07_DATA1()           bfin_read16(CAN_MB07_DATA1)
+#define bfin_write_CAN_MB07_DATA1(val)       bfin_write16(CAN_MB07_DATA1,val)
+#define bfin_read_CAN_MB07_DATA0()           bfin_read16(CAN_MB07_DATA0)
+#define bfin_write_CAN_MB07_DATA0(val)       bfin_write16(CAN_MB07_DATA0,val)
+
+#define bfin_read_CAN_MB08_ID1()             bfin_read16(CAN_MB08_ID1)
+#define bfin_write_CAN_MB08_ID1(val)         bfin_write16(CAN_MB08_ID1,val)
+#define bfin_read_CAN_MB08_ID0()             bfin_read16(CAN_MB08_ID0)
+#define bfin_write_CAN_MB08_ID0(val)         bfin_write16(CAN_MB08_ID0,val)
+#define bfin_read_CAN_MB08_TIMESTAMP()       bfin_read16(CAN_MB08_TIMESTAMP)
+#define bfin_write_CAN_MB08_TIMESTAMP(val)   bfin_write16(CAN_MB08_TIMESTAMP,val)
+#define bfin_read_CAN_MB08_LENGTH()          bfin_read16(CAN_MB08_LENGTH)
+#define bfin_write_CAN_MB08_LENGTH(val)      bfin_write16(CAN_MB08_LENGTH,val)
+#define bfin_read_CAN_MB08_DATA3()           bfin_read16(CAN_MB08_DATA3)
+#define bfin_write_CAN_MB08_DATA3(val)       bfin_write16(CAN_MB08_DATA3,val)
+#define bfin_read_CAN_MB08_DATA2()           bfin_read16(CAN_MB08_DATA2)
+#define bfin_write_CAN_MB08_DATA2(val)       bfin_write16(CAN_MB08_DATA2,val)
+#define bfin_read_CAN_MB08_DATA1()           bfin_read16(CAN_MB08_DATA1)
+#define bfin_write_CAN_MB08_DATA1(val)       bfin_write16(CAN_MB08_DATA1,val)
+#define bfin_read_CAN_MB08_DATA0()           bfin_read16(CAN_MB08_DATA0)
+#define bfin_write_CAN_MB08_DATA0(val)       bfin_write16(CAN_MB08_DATA0,val)
+
+#define bfin_read_CAN_MB09_ID1()             bfin_read16(CAN_MB09_ID1)
+#define bfin_write_CAN_MB09_ID1(val)         bfin_write16(CAN_MB09_ID1,val)
+#define bfin_read_CAN_MB09_ID0()             bfin_read16(CAN_MB09_ID0)
+#define bfin_write_CAN_MB09_ID0(val)         bfin_write16(CAN_MB09_ID0,val)
+#define bfin_read_CAN_MB09_TIMESTAMP()       bfin_read16(CAN_MB09_TIMESTAMP)
+#define bfin_write_CAN_MB09_TIMESTAMP(val)   bfin_write16(CAN_MB09_TIMESTAMP,val)
+#define bfin_read_CAN_MB09_LENGTH()          bfin_read16(CAN_MB09_LENGTH)
+#define bfin_write_CAN_MB09_LENGTH(val)      bfin_write16(CAN_MB09_LENGTH,val)
+#define bfin_read_CAN_MB09_DATA3()           bfin_read16(CAN_MB09_DATA3)
+#define bfin_write_CAN_MB09_DATA3(val)       bfin_write16(CAN_MB09_DATA3,val)
+#define bfin_read_CAN_MB09_DATA2()           bfin_read16(CAN_MB09_DATA2)
+#define bfin_write_CAN_MB09_DATA2(val)       bfin_write16(CAN_MB09_DATA2,val)
+#define bfin_read_CAN_MB09_DATA1()           bfin_read16(CAN_MB09_DATA1)
+#define bfin_write_CAN_MB09_DATA1(val)       bfin_write16(CAN_MB09_DATA1,val)
+#define bfin_read_CAN_MB09_DATA0()           bfin_read16(CAN_MB09_DATA0)
+#define bfin_write_CAN_MB09_DATA0(val)       bfin_write16(CAN_MB09_DATA0,val)
+
+#define bfin_read_CAN_MB10_ID1()             bfin_read16(CAN_MB10_ID1)
+#define bfin_write_CAN_MB10_ID1(val)         bfin_write16(CAN_MB10_ID1,val)
+#define bfin_read_CAN_MB10_ID0()             bfin_read16(CAN_MB10_ID0)
+#define bfin_write_CAN_MB10_ID0(val)         bfin_write16(CAN_MB10_ID0,val)
+#define bfin_read_CAN_MB10_TIMESTAMP()       bfin_read16(CAN_MB10_TIMESTAMP)
+#define bfin_write_CAN_MB10_TIMESTAMP(val)   bfin_write16(CAN_MB10_TIMESTAMP,val)
+#define bfin_read_CAN_MB10_LENGTH()          bfin_read16(CAN_MB10_LENGTH)
+#define bfin_write_CAN_MB10_LENGTH(val)      bfin_write16(CAN_MB10_LENGTH,val)
+#define bfin_read_CAN_MB10_DATA3()           bfin_read16(CAN_MB10_DATA3)
+#define bfin_write_CAN_MB10_DATA3(val)       bfin_write16(CAN_MB10_DATA3,val)
+#define bfin_read_CAN_MB10_DATA2()           bfin_read16(CAN_MB10_DATA2)
+#define bfin_write_CAN_MB10_DATA2(val)       bfin_write16(CAN_MB10_DATA2,val)
+#define bfin_read_CAN_MB10_DATA1()           bfin_read16(CAN_MB10_DATA1)
+#define bfin_write_CAN_MB10_DATA1(val)       bfin_write16(CAN_MB10_DATA1,val)
+#define bfin_read_CAN_MB10_DATA0()           bfin_read16(CAN_MB10_DATA0)
+#define bfin_write_CAN_MB10_DATA0(val)       bfin_write16(CAN_MB10_DATA0,val)
+
+#define bfin_read_CAN_MB11_ID1()             bfin_read16(CAN_MB11_ID1)
+#define bfin_write_CAN_MB11_ID1(val)         bfin_write16(CAN_MB11_ID1,val)
+#define bfin_read_CAN_MB11_ID0()             bfin_read16(CAN_MB11_ID0)
+#define bfin_write_CAN_MB11_ID0(val)         bfin_write16(CAN_MB11_ID0,val)
+#define bfin_read_CAN_MB11_TIMESTAMP()       bfin_read16(CAN_MB11_TIMESTAMP)
+#define bfin_write_CAN_MB11_TIMESTAMP(val)   bfin_write16(CAN_MB11_TIMESTAMP,val)
+#define bfin_read_CAN_MB11_LENGTH()          bfin_read16(CAN_MB11_LENGTH)
+#define bfin_write_CAN_MB11_LENGTH(val)      bfin_write16(CAN_MB11_LENGTH,val)
+#define bfin_read_CAN_MB11_DATA3()           bfin_read16(CAN_MB11_DATA3)
+#define bfin_write_CAN_MB11_DATA3(val)       bfin_write16(CAN_MB11_DATA3,val)
+#define bfin_read_CAN_MB11_DATA2()           bfin_read16(CAN_MB11_DATA2)
+#define bfin_write_CAN_MB11_DATA2(val)       bfin_write16(CAN_MB11_DATA2,val)
+#define bfin_read_CAN_MB11_DATA1()           bfin_read16(CAN_MB11_DATA1)
+#define bfin_write_CAN_MB11_DATA1(val)       bfin_write16(CAN_MB11_DATA1,val)
+#define bfin_read_CAN_MB11_DATA0()           bfin_read16(CAN_MB11_DATA0)
+#define bfin_write_CAN_MB11_DATA0(val)       bfin_write16(CAN_MB11_DATA0,val)
+
+#define bfin_read_CAN_MB12_ID1()             bfin_read16(CAN_MB12_ID1)
+#define bfin_write_CAN_MB12_ID1(val)         bfin_write16(CAN_MB12_ID1,val)
+#define bfin_read_CAN_MB12_ID0()             bfin_read16(CAN_MB12_ID0)
+#define bfin_write_CAN_MB12_ID0(val)         bfin_write16(CAN_MB12_ID0,val)
+#define bfin_read_CAN_MB12_TIMESTAMP()       bfin_read16(CAN_MB12_TIMESTAMP)
+#define bfin_write_CAN_MB12_TIMESTAMP(val)   bfin_write16(CAN_MB12_TIMESTAMP,val)
+#define bfin_read_CAN_MB12_LENGTH()          bfin_read16(CAN_MB12_LENGTH)
+#define bfin_write_CAN_MB12_LENGTH(val)      bfin_write16(CAN_MB12_LENGTH,val)
+#define bfin_read_CAN_MB12_DATA3()           bfin_read16(CAN_MB12_DATA3)
+#define bfin_write_CAN_MB12_DATA3(val)       bfin_write16(CAN_MB12_DATA3,val)
+#define bfin_read_CAN_MB12_DATA2()           bfin_read16(CAN_MB12_DATA2)
+#define bfin_write_CAN_MB12_DATA2(val)       bfin_write16(CAN_MB12_DATA2,val)
+#define bfin_read_CAN_MB12_DATA1()           bfin_read16(CAN_MB12_DATA1)
+#define bfin_write_CAN_MB12_DATA1(val)       bfin_write16(CAN_MB12_DATA1,val)
+#define bfin_read_CAN_MB12_DATA0()           bfin_read16(CAN_MB12_DATA0)
+#define bfin_write_CAN_MB12_DATA0(val)       bfin_write16(CAN_MB12_DATA0,val)
+
+#define bfin_read_CAN_MB13_ID1()             bfin_read16(CAN_MB13_ID1)
+#define bfin_write_CAN_MB13_ID1(val)         bfin_write16(CAN_MB13_ID1,val)
+#define bfin_read_CAN_MB13_ID0()             bfin_read16(CAN_MB13_ID0)
+#define bfin_write_CAN_MB13_ID0(val)         bfin_write16(CAN_MB13_ID0,val)
+#define bfin_read_CAN_MB13_TIMESTAMP()       bfin_read16(CAN_MB13_TIMESTAMP)
+#define bfin_write_CAN_MB13_TIMESTAMP(val)   bfin_write16(CAN_MB13_TIMESTAMP,val)
+#define bfin_read_CAN_MB13_LENGTH()          bfin_read16(CAN_MB13_LENGTH)
+#define bfin_write_CAN_MB13_LENGTH(val)      bfin_write16(CAN_MB13_LENGTH,val)
+#define bfin_read_CAN_MB13_DATA3()           bfin_read16(CAN_MB13_DATA3)
+#define bfin_write_CAN_MB13_DATA3(val)       bfin_write16(CAN_MB13_DATA3,val)
+#define bfin_read_CAN_MB13_DATA2()           bfin_read16(CAN_MB13_DATA2)
+#define bfin_write_CAN_MB13_DATA2(val)       bfin_write16(CAN_MB13_DATA2,val)
+#define bfin_read_CAN_MB13_DATA1()           bfin_read16(CAN_MB13_DATA1)
+#define bfin_write_CAN_MB13_DATA1(val)       bfin_write16(CAN_MB13_DATA1,val)
+#define bfin_read_CAN_MB13_DATA0()           bfin_read16(CAN_MB13_DATA0)
+#define bfin_write_CAN_MB13_DATA0(val)       bfin_write16(CAN_MB13_DATA0,val)
+
+#define bfin_read_CAN_MB14_ID1()             bfin_read16(CAN_MB14_ID1)
+#define bfin_write_CAN_MB14_ID1(val)         bfin_write16(CAN_MB14_ID1,val)
+#define bfin_read_CAN_MB14_ID0()             bfin_read16(CAN_MB14_ID0)
+#define bfin_write_CAN_MB14_ID0(val)         bfin_write16(CAN_MB14_ID0,val)
+#define bfin_read_CAN_MB14_TIMESTAMP()       bfin_read16(CAN_MB14_TIMESTAMP)
+#define bfin_write_CAN_MB14_TIMESTAMP(val)   bfin_write16(CAN_MB14_TIMESTAMP,val)
+#define bfin_read_CAN_MB14_LENGTH()          bfin_read16(CAN_MB14_LENGTH)
+#define bfin_write_CAN_MB14_LENGTH(val)      bfin_write16(CAN_MB14_LENGTH,val)
+#define bfin_read_CAN_MB14_DATA3()           bfin_read16(CAN_MB14_DATA3)
+#define bfin_write_CAN_MB14_DATA3(val)       bfin_write16(CAN_MB14_DATA3,val)
+#define bfin_read_CAN_MB14_DATA2()           bfin_read16(CAN_MB14_DATA2)
+#define bfin_write_CAN_MB14_DATA2(val)       bfin_write16(CAN_MB14_DATA2,val)
+#define bfin_read_CAN_MB14_DATA1()           bfin_read16(CAN_MB14_DATA1)
+#define bfin_write_CAN_MB14_DATA1(val)       bfin_write16(CAN_MB14_DATA1,val)
+#define bfin_read_CAN_MB14_DATA0()           bfin_read16(CAN_MB14_DATA0)
+#define bfin_write_CAN_MB14_DATA0(val)       bfin_write16(CAN_MB14_DATA0,val)
+
+#define bfin_read_CAN_MB15_ID1()             bfin_read16(CAN_MB15_ID1)
+#define bfin_write_CAN_MB15_ID1(val)         bfin_write16(CAN_MB15_ID1,val)
+#define bfin_read_CAN_MB15_ID0()             bfin_read16(CAN_MB15_ID0)
+#define bfin_write_CAN_MB15_ID0(val)         bfin_write16(CAN_MB15_ID0,val)
+#define bfin_read_CAN_MB15_TIMESTAMP()       bfin_read16(CAN_MB15_TIMESTAMP)
+#define bfin_write_CAN_MB15_TIMESTAMP(val)   bfin_write16(CAN_MB15_TIMESTAMP,val)
+#define bfin_read_CAN_MB15_LENGTH()          bfin_read16(CAN_MB15_LENGTH)
+#define bfin_write_CAN_MB15_LENGTH(val)      bfin_write16(CAN_MB15_LENGTH,val)
+#define bfin_read_CAN_MB15_DATA3()           bfin_read16(CAN_MB15_DATA3)
+#define bfin_write_CAN_MB15_DATA3(val)       bfin_write16(CAN_MB15_DATA3,val)
+#define bfin_read_CAN_MB15_DATA2()           bfin_read16(CAN_MB15_DATA2)
+#define bfin_write_CAN_MB15_DATA2(val)       bfin_write16(CAN_MB15_DATA2,val)
+#define bfin_read_CAN_MB15_DATA1()           bfin_read16(CAN_MB15_DATA1)
+#define bfin_write_CAN_MB15_DATA1(val)       bfin_write16(CAN_MB15_DATA1,val)
+#define bfin_read_CAN_MB15_DATA0()           bfin_read16(CAN_MB15_DATA0)
+#define bfin_write_CAN_MB15_DATA0(val)       bfin_write16(CAN_MB15_DATA0,val)
+
+#define bfin_read_CAN_MB16_ID1()             bfin_read16(CAN_MB16_ID1)
+#define bfin_write_CAN_MB16_ID1(val)         bfin_write16(CAN_MB16_ID1,val)
+#define bfin_read_CAN_MB16_ID0()             bfin_read16(CAN_MB16_ID0)
+#define bfin_write_CAN_MB16_ID0(val)         bfin_write16(CAN_MB16_ID0,val)
+#define bfin_read_CAN_MB16_TIMESTAMP()       bfin_read16(CAN_MB16_TIMESTAMP)
+#define bfin_write_CAN_MB16_TIMESTAMP(val)   bfin_write16(CAN_MB16_TIMESTAMP,val)
+#define bfin_read_CAN_MB16_LENGTH()          bfin_read16(CAN_MB16_LENGTH)
+#define bfin_write_CAN_MB16_LENGTH(val)      bfin_write16(CAN_MB16_LENGTH,val)
+#define bfin_read_CAN_MB16_DATA3()           bfin_read16(CAN_MB16_DATA3)
+#define bfin_write_CAN_MB16_DATA3(val)       bfin_write16(CAN_MB16_DATA3,val)
+#define bfin_read_CAN_MB16_DATA2()           bfin_read16(CAN_MB16_DATA2)
+#define bfin_write_CAN_MB16_DATA2(val)       bfin_write16(CAN_MB16_DATA2,val)
+#define bfin_read_CAN_MB16_DATA1()           bfin_read16(CAN_MB16_DATA1)
+#define bfin_write_CAN_MB16_DATA1(val)       bfin_write16(CAN_MB16_DATA1,val)
+#define bfin_read_CAN_MB16_DATA0()           bfin_read16(CAN_MB16_DATA0)
+#define bfin_write_CAN_MB16_DATA0(val)       bfin_write16(CAN_MB16_DATA0,val)
+
+#define bfin_read_CAN_MB17_ID1()             bfin_read16(CAN_MB17_ID1)
+#define bfin_write_CAN_MB17_ID1(val)         bfin_write16(CAN_MB17_ID1,val)
+#define bfin_read_CAN_MB17_ID0()             bfin_read16(CAN_MB17_ID0)
+#define bfin_write_CAN_MB17_ID0(val)         bfin_write16(CAN_MB17_ID0,val)
+#define bfin_read_CAN_MB17_TIMESTAMP()       bfin_read16(CAN_MB17_TIMESTAMP)
+#define bfin_write_CAN_MB17_TIMESTAMP(val)   bfin_write16(CAN_MB17_TIMESTAMP,val)
+#define bfin_read_CAN_MB17_LENGTH()          bfin_read16(CAN_MB17_LENGTH)
+#define bfin_write_CAN_MB17_LENGTH(val)      bfin_write16(CAN_MB17_LENGTH,val)
+#define bfin_read_CAN_MB17_DATA3()           bfin_read16(CAN_MB17_DATA3)
+#define bfin_write_CAN_MB17_DATA3(val)       bfin_write16(CAN_MB17_DATA3,val)
+#define bfin_read_CAN_MB17_DATA2()           bfin_read16(CAN_MB17_DATA2)
+#define bfin_write_CAN_MB17_DATA2(val)       bfin_write16(CAN_MB17_DATA2,val)
+#define bfin_read_CAN_MB17_DATA1()           bfin_read16(CAN_MB17_DATA1)
+#define bfin_write_CAN_MB17_DATA1(val)       bfin_write16(CAN_MB17_DATA1,val)
+#define bfin_read_CAN_MB17_DATA0()           bfin_read16(CAN_MB17_DATA0)
+#define bfin_write_CAN_MB17_DATA0(val)       bfin_write16(CAN_MB17_DATA0,val)
+
+#define bfin_read_CAN_MB18_ID1()             bfin_read16(CAN_MB18_ID1)
+#define bfin_write_CAN_MB18_ID1(val)         bfin_write16(CAN_MB18_ID1,val)
+#define bfin_read_CAN_MB18_ID0()             bfin_read16(CAN_MB18_ID0)
+#define bfin_write_CAN_MB18_ID0(val)         bfin_write16(CAN_MB18_ID0,val)
+#define bfin_read_CAN_MB18_TIMESTAMP()       bfin_read16(CAN_MB18_TIMESTAMP)
+#define bfin_write_CAN_MB18_TIMESTAMP(val)   bfin_write16(CAN_MB18_TIMESTAMP,val)
+#define bfin_read_CAN_MB18_LENGTH()          bfin_read16(CAN_MB18_LENGTH)
+#define bfin_write_CAN_MB18_LENGTH(val)      bfin_write16(CAN_MB18_LENGTH,val)
+#define bfin_read_CAN_MB18_DATA3()           bfin_read16(CAN_MB18_DATA3)
+#define bfin_write_CAN_MB18_DATA3(val)       bfin_write16(CAN_MB18_DATA3,val)
+#define bfin_read_CAN_MB18_DATA2()           bfin_read16(CAN_MB18_DATA2)
+#define bfin_write_CAN_MB18_DATA2(val)       bfin_write16(CAN_MB18_DATA2,val)
+#define bfin_read_CAN_MB18_DATA1()           bfin_read16(CAN_MB18_DATA1)
+#define bfin_write_CAN_MB18_DATA1(val)       bfin_write16(CAN_MB18_DATA1,val)
+#define bfin_read_CAN_MB18_DATA0()           bfin_read16(CAN_MB18_DATA0)
+#define bfin_write_CAN_MB18_DATA0(val)       bfin_write16(CAN_MB18_DATA0,val)
+
+#define bfin_read_CAN_MB19_ID1()             bfin_read16(CAN_MB19_ID1)
+#define bfin_write_CAN_MB19_ID1(val)         bfin_write16(CAN_MB19_ID1,val)
+#define bfin_read_CAN_MB19_ID0()             bfin_read16(CAN_MB19_ID0)
+#define bfin_write_CAN_MB19_ID0(val)         bfin_write16(CAN_MB19_ID0,val)
+#define bfin_read_CAN_MB19_TIMESTAMP()       bfin_read16(CAN_MB19_TIMESTAMP)
+#define bfin_write_CAN_MB19_TIMESTAMP(val)   bfin_write16(CAN_MB19_TIMESTAMP,val)
+#define bfin_read_CAN_MB19_LENGTH()          bfin_read16(CAN_MB19_LENGTH)
+#define bfin_write_CAN_MB19_LENGTH(val)      bfin_write16(CAN_MB19_LENGTH,val)
+#define bfin_read_CAN_MB19_DATA3()           bfin_read16(CAN_MB19_DATA3)
+#define bfin_write_CAN_MB19_DATA3(val)       bfin_write16(CAN_MB19_DATA3,val)
+#define bfin_read_CAN_MB19_DATA2()           bfin_read16(CAN_MB19_DATA2)
+#define bfin_write_CAN_MB19_DATA2(val)       bfin_write16(CAN_MB19_DATA2,val)
+#define bfin_read_CAN_MB19_DATA1()           bfin_read16(CAN_MB19_DATA1)
+#define bfin_write_CAN_MB19_DATA1(val)       bfin_write16(CAN_MB19_DATA1,val)
+#define bfin_read_CAN_MB19_DATA0()           bfin_read16(CAN_MB19_DATA0)
+#define bfin_write_CAN_MB19_DATA0(val)       bfin_write16(CAN_MB19_DATA0,val)
+
+#define bfin_read_CAN_MB20_ID1()             bfin_read16(CAN_MB20_ID1)
+#define bfin_write_CAN_MB20_ID1(val)         bfin_write16(CAN_MB20_ID1,val)
+#define bfin_read_CAN_MB20_ID0()             bfin_read16(CAN_MB20_ID0)
+#define bfin_write_CAN_MB20_ID0(val)         bfin_write16(CAN_MB20_ID0,val)
+#define bfin_read_CAN_MB20_TIMESTAMP()       bfin_read16(CAN_MB20_TIMESTAMP)
+#define bfin_write_CAN_MB20_TIMESTAMP(val)   bfin_write16(CAN_MB20_TIMESTAMP,val)
+#define bfin_read_CAN_MB20_LENGTH()          bfin_read16(CAN_MB20_LENGTH)
+#define bfin_write_CAN_MB20_LENGTH(val)      bfin_write16(CAN_MB20_LENGTH,val)
+#define bfin_read_CAN_MB20_DATA3()           bfin_read16(CAN_MB20_DATA3)
+#define bfin_write_CAN_MB20_DATA3(val)       bfin_write16(CAN_MB20_DATA3,val)
+#define bfin_read_CAN_MB20_DATA2()           bfin_read16(CAN_MB20_DATA2)
+#define bfin_write_CAN_MB20_DATA2(val)       bfin_write16(CAN_MB20_DATA2,val)
+#define bfin_read_CAN_MB20_DATA1()           bfin_read16(CAN_MB20_DATA1)
+#define bfin_write_CAN_MB20_DATA1(val)       bfin_write16(CAN_MB20_DATA1,val)
+#define bfin_read_CAN_MB20_DATA0()           bfin_read16(CAN_MB20_DATA0)
+#define bfin_write_CAN_MB20_DATA0(val)       bfin_write16(CAN_MB20_DATA0,val)
+
+#define bfin_read_CAN_MB21_ID1()             bfin_read16(CAN_MB21_ID1)
+#define bfin_write_CAN_MB21_ID1(val)         bfin_write16(CAN_MB21_ID1,val)
+#define bfin_read_CAN_MB21_ID0()             bfin_read16(CAN_MB21_ID0)
+#define bfin_write_CAN_MB21_ID0(val)         bfin_write16(CAN_MB21_ID0,val)
+#define bfin_read_CAN_MB21_TIMESTAMP()       bfin_read16(CAN_MB21_TIMESTAMP)
+#define bfin_write_CAN_MB21_TIMESTAMP(val)   bfin_write16(CAN_MB21_TIMESTAMP,val)
+#define bfin_read_CAN_MB21_LENGTH()          bfin_read16(CAN_MB21_LENGTH)
+#define bfin_write_CAN_MB21_LENGTH(val)      bfin_write16(CAN_MB21_LENGTH,val)
+#define bfin_read_CAN_MB21_DATA3()           bfin_read16(CAN_MB21_DATA3)
+#define bfin_write_CAN_MB21_DATA3(val)       bfin_write16(CAN_MB21_DATA3,val)
+#define bfin_read_CAN_MB21_DATA2()           bfin_read16(CAN_MB21_DATA2)
+#define bfin_write_CAN_MB21_DATA2(val)       bfin_write16(CAN_MB21_DATA2,val)
+#define bfin_read_CAN_MB21_DATA1()           bfin_read16(CAN_MB21_DATA1)
+#define bfin_write_CAN_MB21_DATA1(val)       bfin_write16(CAN_MB21_DATA1,val)
+#define bfin_read_CAN_MB21_DATA0()           bfin_read16(CAN_MB21_DATA0)
+#define bfin_write_CAN_MB21_DATA0(val)       bfin_write16(CAN_MB21_DATA0,val)
+
+#define bfin_read_CAN_MB22_ID1()             bfin_read16(CAN_MB22_ID1)
+#define bfin_write_CAN_MB22_ID1(val)         bfin_write16(CAN_MB22_ID1,val)
+#define bfin_read_CAN_MB22_ID0()             bfin_read16(CAN_MB22_ID0)
+#define bfin_write_CAN_MB22_ID0(val)         bfin_write16(CAN_MB22_ID0,val)
+#define bfin_read_CAN_MB22_TIMESTAMP()       bfin_read16(CAN_MB22_TIMESTAMP)
+#define bfin_write_CAN_MB22_TIMESTAMP(val)   bfin_write16(CAN_MB22_TIMESTAMP,val)
+#define bfin_read_CAN_MB22_LENGTH()          bfin_read16(CAN_MB22_LENGTH)
+#define bfin_write_CAN_MB22_LENGTH(val)      bfin_write16(CAN_MB22_LENGTH,val)
+#define bfin_read_CAN_MB22_DATA3()           bfin_read16(CAN_MB22_DATA3)
+#define bfin_write_CAN_MB22_DATA3(val)       bfin_write16(CAN_MB22_DATA3,val)
+#define bfin_read_CAN_MB22_DATA2()           bfin_read16(CAN_MB22_DATA2)
+#define bfin_write_CAN_MB22_DATA2(val)       bfin_write16(CAN_MB22_DATA2,val)
+#define bfin_read_CAN_MB22_DATA1()           bfin_read16(CAN_MB22_DATA1)
+#define bfin_write_CAN_MB22_DATA1(val)       bfin_write16(CAN_MB22_DATA1,val)
+#define bfin_read_CAN_MB22_DATA0()           bfin_read16(CAN_MB22_DATA0)
+#define bfin_write_CAN_MB22_DATA0(val)       bfin_write16(CAN_MB22_DATA0,val)
+
+#define bfin_read_CAN_MB23_ID1()             bfin_read16(CAN_MB23_ID1)
+#define bfin_write_CAN_MB23_ID1(val)         bfin_write16(CAN_MB23_ID1,val)
+#define bfin_read_CAN_MB23_ID0()             bfin_read16(CAN_MB23_ID0)
+#define bfin_write_CAN_MB23_ID0(val)         bfin_write16(CAN_MB23_ID0,val)
+#define bfin_read_CAN_MB23_TIMESTAMP()       bfin_read16(CAN_MB23_TIMESTAMP)
+#define bfin_write_CAN_MB23_TIMESTAMP(val)   bfin_write16(CAN_MB23_TIMESTAMP,val)
+#define bfin_read_CAN_MB23_LENGTH()          bfin_read16(CAN_MB23_LENGTH)
+#define bfin_write_CAN_MB23_LENGTH(val)      bfin_write16(CAN_MB23_LENGTH,val)
+#define bfin_read_CAN_MB23_DATA3()           bfin_read16(CAN_MB23_DATA3)
+#define bfin_write_CAN_MB23_DATA3(val)       bfin_write16(CAN_MB23_DATA3,val)
+#define bfin_read_CAN_MB23_DATA2()           bfin_read16(CAN_MB23_DATA2)
+#define bfin_write_CAN_MB23_DATA2(val)       bfin_write16(CAN_MB23_DATA2,val)
+#define bfin_read_CAN_MB23_DATA1()           bfin_read16(CAN_MB23_DATA1)
+#define bfin_write_CAN_MB23_DATA1(val)       bfin_write16(CAN_MB23_DATA1,val)
+#define bfin_read_CAN_MB23_DATA0()           bfin_read16(CAN_MB23_DATA0)
+#define bfin_write_CAN_MB23_DATA0(val)       bfin_write16(CAN_MB23_DATA0,val)
+
+#define bfin_read_CAN_MB24_ID1()             bfin_read16(CAN_MB24_ID1)
+#define bfin_write_CAN_MB24_ID1(val)         bfin_write16(CAN_MB24_ID1,val)
+#define bfin_read_CAN_MB24_ID0()             bfin_read16(CAN_MB24_ID0)
+#define bfin_write_CAN_MB24_ID0(val)         bfin_write16(CAN_MB24_ID0,val)
+#define bfin_read_CAN_MB24_TIMESTAMP()       bfin_read16(CAN_MB24_TIMESTAMP)
+#define bfin_write_CAN_MB24_TIMESTAMP(val)   bfin_write16(CAN_MB24_TIMESTAMP,val)
+#define bfin_read_CAN_MB24_LENGTH()          bfin_read16(CAN_MB24_LENGTH)
+#define bfin_write_CAN_MB24_LENGTH(val)      bfin_write16(CAN_MB24_LENGTH,val)
+#define bfin_read_CAN_MB24_DATA3()           bfin_read16(CAN_MB24_DATA3)
+#define bfin_write_CAN_MB24_DATA3(val)       bfin_write16(CAN_MB24_DATA3,val)
+#define bfin_read_CAN_MB24_DATA2()           bfin_read16(CAN_MB24_DATA2)
+#define bfin_write_CAN_MB24_DATA2(val)       bfin_write16(CAN_MB24_DATA2,val)
+#define bfin_read_CAN_MB24_DATA1()           bfin_read16(CAN_MB24_DATA1)
+#define bfin_write_CAN_MB24_DATA1(val)       bfin_write16(CAN_MB24_DATA1,val)
+#define bfin_read_CAN_MB24_DATA0()           bfin_read16(CAN_MB24_DATA0)
+#define bfin_write_CAN_MB24_DATA0(val)       bfin_write16(CAN_MB24_DATA0,val)
+
+#define bfin_read_CAN_MB25_ID1()             bfin_read16(CAN_MB25_ID1)
+#define bfin_write_CAN_MB25_ID1(val)         bfin_write16(CAN_MB25_ID1,val)
+#define bfin_read_CAN_MB25_ID0()             bfin_read16(CAN_MB25_ID0)
+#define bfin_write_CAN_MB25_ID0(val)         bfin_write16(CAN_MB25_ID0,val)
+#define bfin_read_CAN_MB25_TIMESTAMP()       bfin_read16(CAN_MB25_TIMESTAMP)
+#define bfin_write_CAN_MB25_TIMESTAMP(val)   bfin_write16(CAN_MB25_TIMESTAMP,val)
+#define bfin_read_CAN_MB25_LENGTH()          bfin_read16(CAN_MB25_LENGTH)
+#define bfin_write_CAN_MB25_LENGTH(val)      bfin_write16(CAN_MB25_LENGTH,val)
+#define bfin_read_CAN_MB25_DATA3()           bfin_read16(CAN_MB25_DATA3)
+#define bfin_write_CAN_MB25_DATA3(val)       bfin_write16(CAN_MB25_DATA3,val)
+#define bfin_read_CAN_MB25_DATA2()           bfin_read16(CAN_MB25_DATA2)
+#define bfin_write_CAN_MB25_DATA2(val)       bfin_write16(CAN_MB25_DATA2,val)
+#define bfin_read_CAN_MB25_DATA1()           bfin_read16(CAN_MB25_DATA1)
+#define bfin_write_CAN_MB25_DATA1(val)       bfin_write16(CAN_MB25_DATA1,val)
+#define bfin_read_CAN_MB25_DATA0()           bfin_read16(CAN_MB25_DATA0)
+#define bfin_write_CAN_MB25_DATA0(val)       bfin_write16(CAN_MB25_DATA0,val)
+
+#define bfin_read_CAN_MB26_ID1()             bfin_read16(CAN_MB26_ID1)
+#define bfin_write_CAN_MB26_ID1(val)         bfin_write16(CAN_MB26_ID1,val)
+#define bfin_read_CAN_MB26_ID0()             bfin_read16(CAN_MB26_ID0)
+#define bfin_write_CAN_MB26_ID0(val)         bfin_write16(CAN_MB26_ID0,val)
+#define bfin_read_CAN_MB26_TIMESTAMP()       bfin_read16(CAN_MB26_TIMESTAMP)
+#define bfin_write_CAN_MB26_TIMESTAMP(val)   bfin_write16(CAN_MB26_TIMESTAMP,val)
+#define bfin_read_CAN_MB26_LENGTH()          bfin_read16(CAN_MB26_LENGTH)
+#define bfin_write_CAN_MB26_LENGTH(val)      bfin_write16(CAN_MB26_LENGTH,val)
+#define bfin_read_CAN_MB26_DATA3()           bfin_read16(CAN_MB26_DATA3)
+#define bfin_write_CAN_MB26_DATA3(val)       bfin_write16(CAN_MB26_DATA3,val)
+#define bfin_read_CAN_MB26_DATA2()           bfin_read16(CAN_MB26_DATA2)
+#define bfin_write_CAN_MB26_DATA2(val)       bfin_write16(CAN_MB26_DATA2,val)
+#define bfin_read_CAN_MB26_DATA1()           bfin_read16(CAN_MB26_DATA1)
+#define bfin_write_CAN_MB26_DATA1(val)       bfin_write16(CAN_MB26_DATA1,val)
+#define bfin_read_CAN_MB26_DATA0()           bfin_read16(CAN_MB26_DATA0)
+#define bfin_write_CAN_MB26_DATA0(val)       bfin_write16(CAN_MB26_DATA0,val)
+
+#define bfin_read_CAN_MB27_ID1()             bfin_read16(CAN_MB27_ID1)
+#define bfin_write_CAN_MB27_ID1(val)         bfin_write16(CAN_MB27_ID1,val)
+#define bfin_read_CAN_MB27_ID0()             bfin_read16(CAN_MB27_ID0)
+#define bfin_write_CAN_MB27_ID0(val)         bfin_write16(CAN_MB27_ID0,val)
+#define bfin_read_CAN_MB27_TIMESTAMP()       bfin_read16(CAN_MB27_TIMESTAMP)
+#define bfin_write_CAN_MB27_TIMESTAMP(val)   bfin_write16(CAN_MB27_TIMESTAMP,val)
+#define bfin_read_CAN_MB27_LENGTH()          bfin_read16(CAN_MB27_LENGTH)
+#define bfin_write_CAN_MB27_LENGTH(val)      bfin_write16(CAN_MB27_LENGTH,val)
+#define bfin_read_CAN_MB27_DATA3()           bfin_read16(CAN_MB27_DATA3)
+#define bfin_write_CAN_MB27_DATA3(val)       bfin_write16(CAN_MB27_DATA3,val)
+#define bfin_read_CAN_MB27_DATA2()           bfin_read16(CAN_MB27_DATA2)
+#define bfin_write_CAN_MB27_DATA2(val)       bfin_write16(CAN_MB27_DATA2,val)
+#define bfin_read_CAN_MB27_DATA1()           bfin_read16(CAN_MB27_DATA1)
+#define bfin_write_CAN_MB27_DATA1(val)       bfin_write16(CAN_MB27_DATA1,val)
+#define bfin_read_CAN_MB27_DATA0()           bfin_read16(CAN_MB27_DATA0)
+#define bfin_write_CAN_MB27_DATA0(val)       bfin_write16(CAN_MB27_DATA0,val)
+
+#define bfin_read_CAN_MB28_ID1()             bfin_read16(CAN_MB28_ID1)
+#define bfin_write_CAN_MB28_ID1(val)         bfin_write16(CAN_MB28_ID1,val)
+#define bfin_read_CAN_MB28_ID0()             bfin_read16(CAN_MB28_ID0)
+#define bfin_write_CAN_MB28_ID0(val)         bfin_write16(CAN_MB28_ID0,val)
+#define bfin_read_CAN_MB28_TIMESTAMP()       bfin_read16(CAN_MB28_TIMESTAMP)
+#define bfin_write_CAN_MB28_TIMESTAMP(val)   bfin_write16(CAN_MB28_TIMESTAMP,val)
+#define bfin_read_CAN_MB28_LENGTH()          bfin_read16(CAN_MB28_LENGTH)
+#define bfin_write_CAN_MB28_LENGTH(val)      bfin_write16(CAN_MB28_LENGTH,val)
+#define bfin_read_CAN_MB28_DATA3()           bfin_read16(CAN_MB28_DATA3)
+#define bfin_write_CAN_MB28_DATA3(val)       bfin_write16(CAN_MB28_DATA3,val)
+#define bfin_read_CAN_MB28_DATA2()           bfin_read16(CAN_MB28_DATA2)
+#define bfin_write_CAN_MB28_DATA2(val)       bfin_write16(CAN_MB28_DATA2,val)
+#define bfin_read_CAN_MB28_DATA1()           bfin_read16(CAN_MB28_DATA1)
+#define bfin_write_CAN_MB28_DATA1(val)       bfin_write16(CAN_MB28_DATA1,val)
+#define bfin_read_CAN_MB28_DATA0()           bfin_read16(CAN_MB28_DATA0)
+#define bfin_write_CAN_MB28_DATA0(val)       bfin_write16(CAN_MB28_DATA0,val)
+
+#define bfin_read_CAN_MB29_ID1()             bfin_read16(CAN_MB29_ID1)
+#define bfin_write_CAN_MB29_ID1(val)         bfin_write16(CAN_MB29_ID1,val)
+#define bfin_read_CAN_MB29_ID0()             bfin_read16(CAN_MB29_ID0)
+#define bfin_write_CAN_MB29_ID0(val)         bfin_write16(CAN_MB29_ID0,val)
+#define bfin_read_CAN_MB29_TIMESTAMP()       bfin_read16(CAN_MB29_TIMESTAMP)
+#define bfin_write_CAN_MB29_TIMESTAMP(val)   bfin_write16(CAN_MB29_TIMESTAMP,val)
+#define bfin_read_CAN_MB29_LENGTH()          bfin_read16(CAN_MB29_LENGTH)
+#define bfin_write_CAN_MB29_LENGTH(val)      bfin_write16(CAN_MB29_LENGTH,val)
+#define bfin_read_CAN_MB29_DATA3()           bfin_read16(CAN_MB29_DATA3)
+#define bfin_write_CAN_MB29_DATA3(val)       bfin_write16(CAN_MB29_DATA3,val)
+#define bfin_read_CAN_MB29_DATA2()           bfin_read16(CAN_MB29_DATA2)
+#define bfin_write_CAN_MB29_DATA2(val)       bfin_write16(CAN_MB29_DATA2,val)
+#define bfin_read_CAN_MB29_DATA1()           bfin_read16(CAN_MB29_DATA1)
+#define bfin_write_CAN_MB29_DATA1(val)       bfin_write16(CAN_MB29_DATA1,val)
+#define bfin_read_CAN_MB29_DATA0()           bfin_read16(CAN_MB29_DATA0)
+#define bfin_write_CAN_MB29_DATA0(val)       bfin_write16(CAN_MB29_DATA0,val)
+
+#define bfin_read_CAN_MB30_ID1()             bfin_read16(CAN_MB30_ID1)
+#define bfin_write_CAN_MB30_ID1(val)         bfin_write16(CAN_MB30_ID1,val)
+#define bfin_read_CAN_MB30_ID0()             bfin_read16(CAN_MB30_ID0)
+#define bfin_write_CAN_MB30_ID0(val)         bfin_write16(CAN_MB30_ID0,val)
+#define bfin_read_CAN_MB30_TIMESTAMP()       bfin_read16(CAN_MB30_TIMESTAMP)
+#define bfin_write_CAN_MB30_TIMESTAMP(val)   bfin_write16(CAN_MB30_TIMESTAMP,val)
+#define bfin_read_CAN_MB30_LENGTH()          bfin_read16(CAN_MB30_LENGTH)
+#define bfin_write_CAN_MB30_LENGTH(val)      bfin_write16(CAN_MB30_LENGTH,val)
+#define bfin_read_CAN_MB30_DATA3()           bfin_read16(CAN_MB30_DATA3)
+#define bfin_write_CAN_MB30_DATA3(val)       bfin_write16(CAN_MB30_DATA3,val)
+#define bfin_read_CAN_MB30_DATA2()           bfin_read16(CAN_MB30_DATA2)
+#define bfin_write_CAN_MB30_DATA2(val)       bfin_write16(CAN_MB30_DATA2,val)
+#define bfin_read_CAN_MB30_DATA1()           bfin_read16(CAN_MB30_DATA1)
+#define bfin_write_CAN_MB30_DATA1(val)       bfin_write16(CAN_MB30_DATA1,val)
+#define bfin_read_CAN_MB30_DATA0()           bfin_read16(CAN_MB30_DATA0)
+#define bfin_write_CAN_MB30_DATA0(val)       bfin_write16(CAN_MB30_DATA0,val)
+
+#define bfin_read_CAN_MB31_ID1()             bfin_read16(CAN_MB31_ID1)
+#define bfin_write_CAN_MB31_ID1(val)         bfin_write16(CAN_MB31_ID1,val)
+#define bfin_read_CAN_MB31_ID0()             bfin_read16(CAN_MB31_ID0)
+#define bfin_write_CAN_MB31_ID0(val)         bfin_write16(CAN_MB31_ID0,val)
+#define bfin_read_CAN_MB31_TIMESTAMP()       bfin_read16(CAN_MB31_TIMESTAMP)
+#define bfin_write_CAN_MB31_TIMESTAMP(val)   bfin_write16(CAN_MB31_TIMESTAMP,val)
+#define bfin_read_CAN_MB31_LENGTH()          bfin_read16(CAN_MB31_LENGTH)
+#define bfin_write_CAN_MB31_LENGTH(val)      bfin_write16(CAN_MB31_LENGTH,val)
+#define bfin_read_CAN_MB31_DATA3()           bfin_read16(CAN_MB31_DATA3)
+#define bfin_write_CAN_MB31_DATA3(val)       bfin_write16(CAN_MB31_DATA3,val)
+#define bfin_read_CAN_MB31_DATA2()           bfin_read16(CAN_MB31_DATA2)
+#define bfin_write_CAN_MB31_DATA2(val)       bfin_write16(CAN_MB31_DATA2,val)
+#define bfin_read_CAN_MB31_DATA1()           bfin_read16(CAN_MB31_DATA1)
+#define bfin_write_CAN_MB31_DATA1(val)       bfin_write16(CAN_MB31_DATA1,val)
+#define bfin_read_CAN_MB31_DATA0()           bfin_read16(CAN_MB31_DATA0)
+#define bfin_write_CAN_MB31_DATA0(val)       bfin_write16(CAN_MB31_DATA0,val)
+
+/* CAN Mailbox Area Macros             */
+#define bfin_read_CAN_MB_ID1(x)()            bfin_read16(CAN_MB_ID1(x))
+#define bfin_write_CAN_MB_ID1(x)(val)        bfin_write16(CAN_MB_ID1(x),val)
+#define bfin_read_CAN_MB_ID0(x)()            bfin_read16(CAN_MB_ID0(x))
+#define bfin_write_CAN_MB_ID0(x)(val)        bfin_write16(CAN_MB_ID0(x),val)
+#define bfin_read_CAN_MB_TIMESTAMP(x)()      bfin_read16(CAN_MB_TIMESTAMP(x))
+#define bfin_write_CAN_MB_TIMESTAMP(x)(val)  bfin_write16(CAN_MB_TIMESTAMP(x),val)
+#define bfin_read_CAN_MB_LENGTH(x)()         bfin_read16(CAN_MB_LENGTH(x))
+#define bfin_write_CAN_MB_LENGTH(x)(val)     bfin_write16(CAN_MB_LENGTH(x),val)
+#define bfin_read_CAN_MB_DATA3(x)()          bfin_read16(CAN_MB_DATA3(x))
+#define bfin_write_CAN_MB_DATA3(x)(val)      bfin_write16(CAN_MB_DATA3(x),val)
+#define bfin_read_CAN_MB_DATA2(x)()          bfin_read16(CAN_MB_DATA2(x))
+#define bfin_write_CAN_MB_DATA2(x)(val)      bfin_write16(CAN_MB_DATA2(x),val)
+#define bfin_read_CAN_MB_DATA1(x)()          bfin_read16(CAN_MB_DATA1(x))
+#define bfin_write_CAN_MB_DATA1(x)(val)      bfin_write16(CAN_MB_DATA1(x),val)
+#define bfin_read_CAN_MB_DATA0(x)()          bfin_read16(CAN_MB_DATA0(x))
+#define bfin_write_CAN_MB_DATA0(x)(val)      bfin_write16(CAN_MB_DATA0(x),val)
+
+/* Pin Control Registers       (0xFFC03200 - 0xFFC032FF)                                                               */
+#define bfin_read_PORTF_FER()                bfin_read16(PORTF_FER)
+#define bfin_write_PORTF_FER(val)            bfin_write16(PORTF_FER,val)
+#define bfin_read_PORTG_FER()                bfin_read16(PORTG_FER)
+#define bfin_write_PORTG_FER(val)            bfin_write16(PORTG_FER,val)
+#define bfin_read_PORTH_FER()                bfin_read16(PORTH_FER)
+#define bfin_write_PORTH_FER(val)            bfin_write16(PORTH_FER,val)
+#define bfin_read_PORT_MUX()                 bfin_read16(BFIN_PORT_MUX)
+#define bfin_write_PORT_MUX(val)             bfin_write16(BFIN_PORT_MUX,val)
+
+/* Handshake MDMA Registers    (0xFFC03300 - 0xFFC033FF)                                                               */
+#define bfin_read_HMDMA0_CONTROL()           bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)       bfin_write16(HMDMA0_CONTROL,val)
+#define bfin_read_HMDMA0_ECINIT()            bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)        bfin_write16(HMDMA0_ECINIT,val)
+#define bfin_read_HMDMA0_BCINIT()            bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)        bfin_write16(HMDMA0_BCINIT,val)
+#define bfin_read_HMDMA0_ECURGENT()          bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)      bfin_write16(HMDMA0_ECURGENT,val)
+#define bfin_read_HMDMA0_ECOVERFLOW()        bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)    bfin_write16(HMDMA0_ECOVERFLOW,val)
+#define bfin_read_HMDMA0_ECOUNT()            bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)        bfin_write16(HMDMA0_ECOUNT,val)
+#define bfin_read_HMDMA0_BCOUNT()            bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)        bfin_write16(HMDMA0_BCOUNT,val)
+
+#define bfin_read_HMDMA1_CONTROL()           bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)       bfin_write16(HMDMA1_CONTROL,val)
+#define bfin_read_HMDMA1_ECINIT()            bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)        bfin_write16(HMDMA1_ECINIT,val)
+#define bfin_read_HMDMA1_BCINIT()            bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)        bfin_write16(HMDMA1_BCINIT,val)
+#define bfin_read_HMDMA1_ECURGENT()          bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)      bfin_write16(HMDMA1_ECURGENT,val)
+#define bfin_read_HMDMA1_ECOVERFLOW()        bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)    bfin_write16(HMDMA1_ECOVERFLOW,val)
+#define bfin_read_HMDMA1_ECOUNT()            bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)        bfin_write16(HMDMA1_ECOUNT,val)
+#define bfin_read_HMDMA1_BCOUNT()            bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)        bfin_write16(HMDMA1_BCOUNT,val)
+
+#endif                         /* _CDEF_BF534_H */
diff --git a/include/asm-blackfin/mach-bf537/cdefBF537.h b/include/asm-blackfin/mach-bf537/cdefBF537.h
new file mode 100644 (file)
index 0000000..932a1b6
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * File:         include/asm-blackfin/mach-bf537/cdefBF537.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *     System MMR Register Map
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF537_H
+#define _CDEF_BF537_H
+
+/* Include MMRs Common to BF534                                                                */
+#include "cdefBF534.h"
+
+/* Include all Core registers and bit definitions                                                                      */
+#include "defBF537.h"
+
+/* Include Macro "Defines" For EMAC (Unique to BF536/BF537             */
+/* 10/100 Ethernet Controller  (0xFFC03000 - 0xFFC031FF)                                               */
+#define        pEMAC_OPMODE            ((volatile unsigned long  *)EMAC_OPMODE)
+#define bfin_read_EMAC_OPMODE()              bfin_read32(EMAC_OPMODE)
+#define bfin_write_EMAC_OPMODE(val)          bfin_write32(EMAC_OPMODE,val)
+#define bfin_read_EMAC_ADDRLO()              bfin_read32(EMAC_ADDRLO)
+#define bfin_write_EMAC_ADDRLO(val)          bfin_write32(EMAC_ADDRLO,val)
+#define bfin_read_EMAC_ADDRHI()              bfin_read32(EMAC_ADDRHI)
+#define bfin_write_EMAC_ADDRHI(val)          bfin_write32(EMAC_ADDRHI,val)
+#define bfin_read_EMAC_HASHLO()              bfin_read32(EMAC_HASHLO)
+#define bfin_write_EMAC_HASHLO(val)          bfin_write32(EMAC_HASHLO,val)
+#define bfin_read_EMAC_HASHHI()              bfin_read32(EMAC_HASHHI)
+#define bfin_write_EMAC_HASHHI(val)          bfin_write32(EMAC_HASHHI,val)
+#define bfin_read_EMAC_STAADD()              bfin_read32(EMAC_STAADD)
+#define bfin_write_EMAC_STAADD(val)          bfin_write32(EMAC_STAADD,val)
+#define bfin_read_EMAC_STADAT()              bfin_read32(EMAC_STADAT)
+#define bfin_write_EMAC_STADAT(val)          bfin_write32(EMAC_STADAT,val)
+#define bfin_read_EMAC_FLC()                 bfin_read32(EMAC_FLC)
+#define bfin_write_EMAC_FLC(val)             bfin_write32(EMAC_FLC,val)
+#define bfin_read_EMAC_VLAN1()               bfin_read32(EMAC_VLAN1)
+#define bfin_write_EMAC_VLAN1(val)           bfin_write32(EMAC_VLAN1,val)
+#define bfin_read_EMAC_VLAN2()               bfin_read32(EMAC_VLAN2)
+#define bfin_write_EMAC_VLAN2(val)           bfin_write32(EMAC_VLAN2,val)
+#define bfin_read_EMAC_WKUP_CTL()            bfin_read32(EMAC_WKUP_CTL)
+#define bfin_write_EMAC_WKUP_CTL(val)        bfin_write32(EMAC_WKUP_CTL,val)
+#define bfin_read_EMAC_WKUP_FFMSK0()         bfin_read32(EMAC_WKUP_FFMSK0)
+#define bfin_write_EMAC_WKUP_FFMSK0(val)     bfin_write32(EMAC_WKUP_FFMSK0,val)
+#define bfin_read_EMAC_WKUP_FFMSK1()         bfin_read32(EMAC_WKUP_FFMSK1)
+#define bfin_write_EMAC_WKUP_FFMSK1(val)     bfin_write32(EMAC_WKUP_FFMSK1,val)
+#define bfin_read_EMAC_WKUP_FFMSK2()         bfin_read32(EMAC_WKUP_FFMSK2)
+#define bfin_write_EMAC_WKUP_FFMSK2(val)     bfin_write32(EMAC_WKUP_FFMSK2,val)
+#define bfin_read_EMAC_WKUP_FFMSK3()         bfin_read32(EMAC_WKUP_FFMSK3)
+#define bfin_write_EMAC_WKUP_FFMSK3(val)     bfin_write32(EMAC_WKUP_FFMSK3,val)
+#define bfin_read_EMAC_WKUP_FFCMD()          bfin_read32(EMAC_WKUP_FFCMD)
+#define bfin_write_EMAC_WKUP_FFCMD(val)      bfin_write32(EMAC_WKUP_FFCMD,val)
+#define bfin_read_EMAC_WKUP_FFOFF()          bfin_read32(EMAC_WKUP_FFOFF)
+#define bfin_write_EMAC_WKUP_FFOFF(val)      bfin_write32(EMAC_WKUP_FFOFF,val)
+#define bfin_read_EMAC_WKUP_FFCRC0()         bfin_read32(EMAC_WKUP_FFCRC0)
+#define bfin_write_EMAC_WKUP_FFCRC0(val)     bfin_write32(EMAC_WKUP_FFCRC0,val)
+#define bfin_read_EMAC_WKUP_FFCRC1()         bfin_read32(EMAC_WKUP_FFCRC1)
+#define bfin_write_EMAC_WKUP_FFCRC1(val)     bfin_write32(EMAC_WKUP_FFCRC1,val)
+
+#define        pEMAC_SYSCTL            ((volatile unsigned long  *)EMAC_SYSCTL)
+#define bfin_read_EMAC_SYSCTL()              bfin_read32(EMAC_SYSCTL)
+#define bfin_write_EMAC_SYSCTL(val)          bfin_write32(EMAC_SYSCTL,val)
+#define bfin_read_EMAC_SYSTAT()              bfin_read32(EMAC_SYSTAT)
+#define bfin_write_EMAC_SYSTAT(val)          bfin_write32(EMAC_SYSTAT,val)
+#define bfin_read_EMAC_RX_STAT()             bfin_read32(EMAC_RX_STAT)
+#define bfin_write_EMAC_RX_STAT(val)         bfin_write32(EMAC_RX_STAT,val)
+#define bfin_read_EMAC_RX_STKY()             bfin_read32(EMAC_RX_STKY)
+#define bfin_write_EMAC_RX_STKY(val)         bfin_write32(EMAC_RX_STKY,val)
+#define bfin_read_EMAC_RX_IRQE()             bfin_read32(EMAC_RX_IRQE)
+#define bfin_write_EMAC_RX_IRQE(val)         bfin_write32(EMAC_RX_IRQE,val)
+#define bfin_read_EMAC_TX_STAT()             bfin_read32(EMAC_TX_STAT)
+#define bfin_write_EMAC_TX_STAT(val)         bfin_write32(EMAC_TX_STAT,val)
+#define bfin_read_EMAC_TX_STKY()             bfin_read32(EMAC_TX_STKY)
+#define bfin_write_EMAC_TX_STKY(val)         bfin_write32(EMAC_TX_STKY,val)
+#define bfin_read_EMAC_TX_IRQE()             bfin_read32(EMAC_TX_IRQE)
+#define bfin_write_EMAC_TX_IRQE(val)         bfin_write32(EMAC_TX_IRQE,val)
+
+#define bfin_read_EMAC_MMC_CTL()             bfin_read32(EMAC_MMC_CTL)
+#define bfin_write_EMAC_MMC_CTL(val)         bfin_write32(EMAC_MMC_CTL,val)
+#define bfin_read_EMAC_MMC_RIRQS()           bfin_read32(EMAC_MMC_RIRQS)
+#define bfin_write_EMAC_MMC_RIRQS(val)       bfin_write32(EMAC_MMC_RIRQS,val)
+#define bfin_read_EMAC_MMC_RIRQE()           bfin_read32(EMAC_MMC_RIRQE)
+#define bfin_write_EMAC_MMC_RIRQE(val)       bfin_write32(EMAC_MMC_RIRQE,val)
+#define bfin_read_EMAC_MMC_TIRQS()           bfin_read32(EMAC_MMC_TIRQS)
+#define bfin_write_EMAC_MMC_TIRQS(val)       bfin_write32(EMAC_MMC_TIRQS,val)
+#define bfin_read_EMAC_MMC_TIRQE()           bfin_read32(EMAC_MMC_TIRQE)
+#define bfin_write_EMAC_MMC_TIRQE(val)       bfin_write32(EMAC_MMC_TIRQE,val)
+
+#define bfin_read_EMAC_RXC_OK()              bfin_read32(EMAC_RXC_OK)
+#define bfin_write_EMAC_RXC_OK(val)          bfin_write32(EMAC_RXC_OK,val)
+#define bfin_read_EMAC_RXC_FCS()             bfin_read32(EMAC_RXC_FCS)
+#define bfin_write_EMAC_RXC_FCS(val)         bfin_write32(EMAC_RXC_FCS,val)
+#define bfin_read_EMAC_RXC_ALIGN()           bfin_read32(EMAC_RXC_ALIGN)
+#define bfin_write_EMAC_RXC_ALIGN(val)       bfin_write32(EMAC_RXC_ALIGN,val)
+#define bfin_read_EMAC_RXC_OCTET()           bfin_read32(EMAC_RXC_OCTET)
+#define bfin_write_EMAC_RXC_OCTET(val)       bfin_write32(EMAC_RXC_OCTET,val)
+#define bfin_read_EMAC_RXC_DMAOVF()          bfin_read32(EMAC_RXC_DMAOVF)
+#define bfin_write_EMAC_RXC_DMAOVF(val)      bfin_write32(EMAC_RXC_DMAOVF,val)
+#define bfin_read_EMAC_RXC_UNICST()          bfin_read32(EMAC_RXC_UNICST)
+#define bfin_write_EMAC_RXC_UNICST(val)      bfin_write32(EMAC_RXC_UNICST,val)
+#define bfin_read_EMAC_RXC_MULTI()           bfin_read32(EMAC_RXC_MULTI)
+#define bfin_write_EMAC_RXC_MULTI(val)       bfin_write32(EMAC_RXC_MULTI,val)
+#define bfin_read_EMAC_RXC_BROAD()           bfin_read32(EMAC_RXC_BROAD)
+#define bfin_write_EMAC_RXC_BROAD(val)       bfin_write32(EMAC_RXC_BROAD,val)
+#define bfin_read_EMAC_RXC_LNERRI()          bfin_read32(EMAC_RXC_LNERRI)
+#define bfin_write_EMAC_RXC_LNERRI(val)      bfin_write32(EMAC_RXC_LNERRI,val)
+#define bfin_read_EMAC_RXC_LNERRO()          bfin_read32(EMAC_RXC_LNERRO)
+#define bfin_write_EMAC_RXC_LNERRO(val)      bfin_write32(EMAC_RXC_LNERRO,val)
+#define bfin_read_EMAC_RXC_LONG()            bfin_read32(EMAC_RXC_LONG)
+#define bfin_write_EMAC_RXC_LONG(val)        bfin_write32(EMAC_RXC_LONG,val)
+#define bfin_read_EMAC_RXC_MACCTL()          bfin_read32(EMAC_RXC_MACCTL)
+#define bfin_write_EMAC_RXC_MACCTL(val)      bfin_write32(EMAC_RXC_MACCTL,val)
+#define bfin_read_EMAC_RXC_OPCODE()          bfin_read32(EMAC_RXC_OPCODE)
+#define bfin_write_EMAC_RXC_OPCODE(val)      bfin_write32(EMAC_RXC_OPCODE,val)
+#define bfin_read_EMAC_RXC_PAUSE()           bfin_read32(EMAC_RXC_PAUSE)
+#define bfin_write_EMAC_RXC_PAUSE(val)       bfin_write32(EMAC_RXC_PAUSE,val)
+#define bfin_read_EMAC_RXC_ALLFRM()          bfin_read32(EMAC_RXC_ALLFRM)
+#define bfin_write_EMAC_RXC_ALLFRM(val)      bfin_write32(EMAC_RXC_ALLFRM,val)
+#define bfin_read_EMAC_RXC_ALLOCT()          bfin_read32(EMAC_RXC_ALLOCT)
+#define bfin_write_EMAC_RXC_ALLOCT(val)      bfin_write32(EMAC_RXC_ALLOCT,val)
+#define bfin_read_EMAC_RXC_TYPED()           bfin_read32(EMAC_RXC_TYPED)
+#define bfin_write_EMAC_RXC_TYPED(val)       bfin_write32(EMAC_RXC_TYPED,val)
+#define bfin_read_EMAC_RXC_SHORT()           bfin_read32(EMAC_RXC_SHORT)
+#define bfin_write_EMAC_RXC_SHORT(val)       bfin_write32(EMAC_RXC_SHORT,val)
+#define bfin_read_EMAC_RXC_EQ64()            bfin_read32(EMAC_RXC_EQ64)
+#define bfin_write_EMAC_RXC_EQ64(val)        bfin_write32(EMAC_RXC_EQ64,val)
+#define        pEMAC_RXC_LT128         ((volatile unsigned long  *)EMAC_RXC_LT128)
+#define bfin_read_EMAC_RXC_LT128()           bfin_read32(EMAC_RXC_LT128)
+#define bfin_write_EMAC_RXC_LT128(val)       bfin_write32(EMAC_RXC_LT128,val)
+#define bfin_read_EMAC_RXC_LT256()           bfin_read32(EMAC_RXC_LT256)
+#define bfin_write_EMAC_RXC_LT256(val)       bfin_write32(EMAC_RXC_LT256,val)
+#define bfin_read_EMAC_RXC_LT512()           bfin_read32(EMAC_RXC_LT512)
+#define bfin_write_EMAC_RXC_LT512(val)       bfin_write32(EMAC_RXC_LT512,val)
+#define bfin_read_EMAC_RXC_LT1024()          bfin_read32(EMAC_RXC_LT1024)
+#define bfin_write_EMAC_RXC_LT1024(val)      bfin_write32(EMAC_RXC_LT1024,val)
+#define bfin_read_EMAC_RXC_GE1024()          bfin_read32(EMAC_RXC_GE1024)
+#define bfin_write_EMAC_RXC_GE1024(val)      bfin_write32(EMAC_RXC_GE1024,val)
+
+#define bfin_read_EMAC_TXC_OK()              bfin_read32(EMAC_TXC_OK)
+#define bfin_write_EMAC_TXC_OK(val)          bfin_write32(EMAC_TXC_OK,val)
+#define bfin_read_EMAC_TXC_1COL()            bfin_read32(EMAC_TXC_1COL)
+#define bfin_write_EMAC_TXC_1COL(val)        bfin_write32(EMAC_TXC_1COL,val)
+#define bfin_read_EMAC_TXC_GT1COL()          bfin_read32(EMAC_TXC_GT1COL)
+#define bfin_write_EMAC_TXC_GT1COL(val)      bfin_write32(EMAC_TXC_GT1COL,val)
+#define bfin_read_EMAC_TXC_OCTET()           bfin_read32(EMAC_TXC_OCTET)
+#define bfin_write_EMAC_TXC_OCTET(val)       bfin_write32(EMAC_TXC_OCTET,val)
+#define bfin_read_EMAC_TXC_DEFER()           bfin_read32(EMAC_TXC_DEFER)
+#define bfin_write_EMAC_TXC_DEFER(val)       bfin_write32(EMAC_TXC_DEFER,val)
+#define bfin_read_EMAC_TXC_LATECL()          bfin_read32(EMAC_TXC_LATECL)
+#define bfin_write_EMAC_TXC_LATECL(val)      bfin_write32(EMAC_TXC_LATECL,val)
+#define bfin_read_EMAC_TXC_XS_COL()          bfin_read32(EMAC_TXC_XS_COL)
+#define bfin_write_EMAC_TXC_XS_COL(val)      bfin_write32(EMAC_TXC_XS_COL,val)
+#define bfin_read_EMAC_TXC_DMAUND()          bfin_read32(EMAC_TXC_DMAUND)
+#define bfin_write_EMAC_TXC_DMAUND(val)      bfin_write32(EMAC_TXC_DMAUND,val)
+#define bfin_read_EMAC_TXC_CRSERR()          bfin_read32(EMAC_TXC_CRSERR)
+#define bfin_write_EMAC_TXC_CRSERR(val)      bfin_write32(EMAC_TXC_CRSERR,val)
+#define bfin_read_EMAC_TXC_UNICST()          bfin_read32(EMAC_TXC_UNICST)
+#define bfin_write_EMAC_TXC_UNICST(val)      bfin_write32(EMAC_TXC_UNICST,val)
+#define bfin_read_EMAC_TXC_MULTI()           bfin_read32(EMAC_TXC_MULTI)
+#define bfin_write_EMAC_TXC_MULTI(val)       bfin_write32(EMAC_TXC_MULTI,val)
+#define bfin_read_EMAC_TXC_BROAD()           bfin_read32(EMAC_TXC_BROAD)
+#define bfin_write_EMAC_TXC_BROAD(val)       bfin_write32(EMAC_TXC_BROAD,val)
+#define bfin_read_EMAC_TXC_XS_DFR()          bfin_read32(EMAC_TXC_XS_DFR)
+#define bfin_write_EMAC_TXC_XS_DFR(val)      bfin_write32(EMAC_TXC_XS_DFR,val)
+#define bfin_read_EMAC_TXC_MACCTL()          bfin_read32(EMAC_TXC_MACCTL)
+#define bfin_write_EMAC_TXC_MACCTL(val)      bfin_write32(EMAC_TXC_MACCTL,val)
+#define bfin_read_EMAC_TXC_ALLFRM()          bfin_read32(EMAC_TXC_ALLFRM)
+#define bfin_write_EMAC_TXC_ALLFRM(val)      bfin_write32(EMAC_TXC_ALLFRM,val)
+#define bfin_read_EMAC_TXC_ALLOCT()          bfin_read32(EMAC_TXC_ALLOCT)
+#define bfin_write_EMAC_TXC_ALLOCT(val)      bfin_write32(EMAC_TXC_ALLOCT,val)
+#define bfin_read_EMAC_TXC_EQ64()            bfin_read32(EMAC_TXC_EQ64)
+#define bfin_write_EMAC_TXC_EQ64(val)        bfin_write32(EMAC_TXC_EQ64,val)
+#define bfin_read_EMAC_TXC_LT128()           bfin_read32(EMAC_TXC_LT128)
+#define bfin_write_EMAC_TXC_LT128(val)       bfin_write32(EMAC_TXC_LT128,val)
+#define bfin_read_EMAC_TXC_LT256()           bfin_read32(EMAC_TXC_LT256)
+#define bfin_write_EMAC_TXC_LT256(val)       bfin_write32(EMAC_TXC_LT256,val)
+#define bfin_read_EMAC_TXC_LT512()           bfin_read32(EMAC_TXC_LT512)
+#define bfin_write_EMAC_TXC_LT512(val)       bfin_write32(EMAC_TXC_LT512,val)
+#define bfin_read_EMAC_TXC_LT1024()          bfin_read32(EMAC_TXC_LT1024)
+#define bfin_write_EMAC_TXC_LT1024(val)      bfin_write32(EMAC_TXC_LT1024,val)
+#define bfin_read_EMAC_TXC_GE1024()          bfin_read32(EMAC_TXC_GE1024)
+#define bfin_write_EMAC_TXC_GE1024(val)      bfin_write32(EMAC_TXC_GE1024,val)
+#define bfin_read_EMAC_TXC_ABORT()           bfin_read32(EMAC_TXC_ABORT)
+#define bfin_write_EMAC_TXC_ABORT(val)       bfin_write32(EMAC_TXC_ABORT,val)
+
+#endif                         /* _CDEF_BF537_H */
diff --git a/include/asm-blackfin/mach-bf537/defBF534.h b/include/asm-blackfin/mach-bf537/defBF534.h
new file mode 100644 (file)
index 0000000..e605e97
--- /dev/null
@@ -0,0 +1,2501 @@
+/*
+ * File:         include/asm-blackfin/mach-bf537/cdefBF537.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF534_H
+#define _DEF_BF534_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/************************************************************************************
+** System MMR Register Map
+*************************************************************************************/
+/* Clock and System Control    (0xFFC00000 - 0xFFC000FF)                                                               */
+#define PLL_CTL                                0xFFC00000      /* PLL Control Register                                         */
+#define PLL_DIV                                0xFFC00004      /* PLL Divide Register                                          */
+#define VR_CTL                         0xFFC00008      /* Voltage Regulator Control Register           */
+#define PLL_STAT                       0xFFC0000C      /* PLL Status Register                                          */
+#define PLL_LOCKCNT                    0xFFC00010      /* PLL Lock Count Register                                      */
+#define CHIPID                         0xFFC00014      /* Chip ID Register                                             */
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)                                                       */
+#define SWRST                          0xFFC00100      /* Software Reset Register                                      */
+#define SYSCR                          0xFFC00104      /* System Configuration Register                        */
+#define SIC_RVECT                      0xFFC00108      /* Interrupt Reset Vector Address Register      */
+#define SIC_IMASK                      0xFFC0010C      /* Interrupt Mask Register                                      */
+#define SIC_IAR0                       0xFFC00110      /* Interrupt Assignment Register 0                      */
+#define SIC_IAR1                       0xFFC00114      /* Interrupt Assignment Register 1                      */
+#define SIC_IAR2                       0xFFC00118      /* Interrupt Assignment Register 2                      */
+#define SIC_IAR3                       0xFFC0011C      /* Interrupt Assignment Register 3                      */
+#define SIC_ISR                                0xFFC00120      /* Interrupt Status Register                            */
+#define SIC_IWR                                0xFFC00124      /* Interrupt Wakeup Register                            */
+
+/* Watchdog Timer                      (0xFFC00200 - 0xFFC002FF)                                                               */
+#define WDOG_CTL                       0xFFC00200      /* Watchdog Control Register                            */
+#define WDOG_CNT                       0xFFC00204      /* Watchdog Count Register                                      */
+#define WDOG_STAT                      0xFFC00208      /* Watchdog Status Register                                     */
+
+/* Real Time Clock             (0xFFC00300 - 0xFFC003FF)                                                                       */
+#define RTC_STAT                       0xFFC00300      /* RTC Status Register                                          */
+#define RTC_ICTL                       0xFFC00304      /* RTC Interrupt Control Register                       */
+#define RTC_ISTAT                      0xFFC00308      /* RTC Interrupt Status Register                        */
+#define RTC_SWCNT                      0xFFC0030C      /* RTC Stopwatch Count Register                         */
+#define RTC_ALARM                      0xFFC00310      /* RTC Alarm Time Register                                      */
+#define RTC_FAST                       0xFFC00314      /* RTC Prescaler Enable Register                        */
+#define RTC_PREN                       0xFFC00314      /* RTC Prescaler Enable Alternate Macro         */
+
+/* UART0 Controller            (0xFFC00400 - 0xFFC004FF)                                                                       */
+#define UART0_THR                      0xFFC00400      /* Transmit Holding register                            */
+#define UART0_RBR                      0xFFC00400      /* Receive Buffer register                                      */
+#define UART0_DLL                      0xFFC00400      /* Divisor Latch (Low-Byte)                                     */
+#define UART0_IER                      0xFFC00404      /* Interrupt Enable Register                            */
+#define UART0_DLH                      0xFFC00404      /* Divisor Latch (High-Byte)                            */
+#define UART0_IIR                      0xFFC00408      /* Interrupt Identification Register            */
+#define UART0_LCR                      0xFFC0040C      /* Line Control Register                                        */
+#define UART0_MCR                      0xFFC00410      /* Modem Control Register                                       */
+#define UART0_LSR                      0xFFC00414      /* Line Status Register                                         */
+#define UART0_MSR                      0xFFC00418      /* Modem Status Register                                        */
+#define UART0_SCR                      0xFFC0041C      /* SCR Scratch Register                                         */
+#define UART0_GCTL                     0xFFC00424      /* Global Control Register                                      */
+
+/* SPI Controller                      (0xFFC00500 - 0xFFC005FF)                                                               */
+#define SPI_CTL                                0xFFC00500      /* SPI Control Register                                         */
+#define SPI_FLG                                0xFFC00504      /* SPI Flag register                                            */
+#define SPI_STAT                       0xFFC00508      /* SPI Status register                                          */
+#define SPI_TDBR                       0xFFC0050C      /* SPI Transmit Data Buffer Register            */
+#define SPI_RDBR                       0xFFC00510      /* SPI Receive Data Buffer Register                     */
+#define SPI_BAUD                       0xFFC00514      /* SPI Baud rate Register                                       */
+#define SPI_SHADOW                     0xFFC00518      /* SPI_RDBR Shadow Register                                     */
+
+/* TIMER0-7 Registers          (0xFFC00600 - 0xFFC006FF)                                                               */
+#define TIMER0_CONFIG          0xFFC00600      /* Timer 0 Configuration Register                       */
+#define TIMER0_COUNTER         0xFFC00604      /* Timer 0 Counter Register                                     */
+#define TIMER0_PERIOD          0xFFC00608      /* Timer 0 Period Register                                      */
+#define TIMER0_WIDTH           0xFFC0060C      /* Timer 0 Width Register                                       */
+
+#define TIMER1_CONFIG          0xFFC00610      /* Timer 1 Configuration Register                       */
+#define TIMER1_COUNTER         0xFFC00614      /* Timer 1 Counter Register                             */
+#define TIMER1_PERIOD          0xFFC00618      /* Timer 1 Period Register                              */
+#define TIMER1_WIDTH           0xFFC0061C      /* Timer 1 Width Register                               */
+
+#define TIMER2_CONFIG          0xFFC00620      /* Timer 2 Configuration Register                       */
+#define TIMER2_COUNTER         0xFFC00624      /* Timer 2 Counter Register                             */
+#define TIMER2_PERIOD          0xFFC00628      /* Timer 2 Period Register                              */
+#define TIMER2_WIDTH           0xFFC0062C      /* Timer 2 Width Register                               */
+
+#define TIMER3_CONFIG          0xFFC00630      /* Timer 3 Configuration Register                       */
+#define TIMER3_COUNTER         0xFFC00634      /* Timer 3 Counter Register                                     */
+#define TIMER3_PERIOD          0xFFC00638      /* Timer 3 Period Register                                      */
+#define TIMER3_WIDTH           0xFFC0063C      /* Timer 3 Width Register                                       */
+
+#define TIMER4_CONFIG          0xFFC00640      /* Timer 4 Configuration Register                       */
+#define TIMER4_COUNTER         0xFFC00644      /* Timer 4 Counter Register                             */
+#define TIMER4_PERIOD          0xFFC00648      /* Timer 4 Period Register                              */
+#define TIMER4_WIDTH           0xFFC0064C      /* Timer 4 Width Register                               */
+
+#define TIMER5_CONFIG          0xFFC00650      /* Timer 5 Configuration Register                       */
+#define TIMER5_COUNTER         0xFFC00654      /* Timer 5 Counter Register                             */
+#define TIMER5_PERIOD          0xFFC00658      /* Timer 5 Period Register                              */
+#define TIMER5_WIDTH           0xFFC0065C      /* Timer 5 Width Register                               */
+
+#define TIMER6_CONFIG          0xFFC00660      /* Timer 6 Configuration Register                       */
+#define TIMER6_COUNTER         0xFFC00664      /* Timer 6 Counter Register                             */
+#define TIMER6_PERIOD          0xFFC00668      /* Timer 6 Period Register                              */
+#define TIMER6_WIDTH           0xFFC0066C      /* Timer 6 Width Register                               */
+
+#define TIMER7_CONFIG          0xFFC00670      /* Timer 7 Configuration Register                       */
+#define TIMER7_COUNTER         0xFFC00674      /* Timer 7 Counter Register                             */
+#define TIMER7_PERIOD          0xFFC00678      /* Timer 7 Period Register                              */
+#define TIMER7_WIDTH           0xFFC0067C      /* Timer 7 Width Register                               */
+
+#define TIMER_ENABLE           0xFFC00680      /* Timer Enable Register                                        */
+#define TIMER_DISABLE          0xFFC00684      /* Timer Disable Register                                       */
+#define TIMER_STATUS           0xFFC00688      /* Timer Status Register                                        */
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)                                                                                                */
+#define PORTFIO                                        0xFFC00700      /* Port F I/O Pin State Specify Register                                */
+#define PORTFIO_CLEAR                  0xFFC00704      /* Port F I/O Peripheral Interrupt Clear Register               */
+#define PORTFIO_SET                            0xFFC00708      /* Port F I/O Peripheral Interrupt Set Register                 */
+#define PORTFIO_TOGGLE                 0xFFC0070C      /* Port F I/O Pin State Toggle Register                                 */
+#define PORTFIO_MASKA                  0xFFC00710      /* Port F I/O Mask State Specify Interrupt A Register   */
+#define PORTFIO_MASKA_CLEAR            0xFFC00714      /* Port F I/O Mask Disable Interrupt A Register                 */
+#define PORTFIO_MASKA_SET              0xFFC00718      /* Port F I/O Mask Enable Interrupt A Register                  */
+#define PORTFIO_MASKA_TOGGLE   0xFFC0071C      /* Port F I/O Mask Toggle Enable Interrupt A Register   */
+#define PORTFIO_MASKB                  0xFFC00720      /* Port F I/O Mask State Specify Interrupt B Register   */
+#define PORTFIO_MASKB_CLEAR            0xFFC00724      /* Port F I/O Mask Disable Interrupt B Register                 */
+#define PORTFIO_MASKB_SET              0xFFC00728      /* Port F I/O Mask Enable Interrupt B Register                  */
+#define PORTFIO_MASKB_TOGGLE   0xFFC0072C      /* Port F I/O Mask Toggle Enable Interrupt B Register   */
+#define PORTFIO_DIR                            0xFFC00730      /* Port F I/O Direction Register                                                */
+#define PORTFIO_POLAR                  0xFFC00734      /* Port F I/O Source Polarity Register                                  */
+#define PORTFIO_EDGE                   0xFFC00738      /* Port F I/O Source Sensitivity Register                               */
+#define PORTFIO_BOTH                   0xFFC0073C      /* Port F I/O Set on BOTH Edges Register                                */
+#define PORTFIO_INEN                   0xFFC00740      /* Port F I/O Input Enable Register                                     */
+
+/* SPORT0 Controller           (0xFFC00800 - 0xFFC008FF)                                                                               */
+#define SPORT0_TCR1                    0xFFC00800      /* SPORT0 Transmit Configuration 1 Register                     */
+#define SPORT0_TCR2                    0xFFC00804      /* SPORT0 Transmit Configuration 2 Register                     */
+#define SPORT0_TCLKDIV         0xFFC00808      /* SPORT0 Transmit Clock Divider                                        */
+#define SPORT0_TFSDIV          0xFFC0080C      /* SPORT0 Transmit Frame Sync Divider                           */
+#define SPORT0_TX                      0xFFC00810      /* SPORT0 TX Data Register                                                      */
+#define SPORT0_RX                      0xFFC00818      /* SPORT0 RX Data Register                                                      */
+#define SPORT0_RCR1                    0xFFC00820      /* SPORT0 Transmit Configuration 1 Register                     */
+#define SPORT0_RCR2                    0xFFC00824      /* SPORT0 Transmit Configuration 2 Register                     */
+#define SPORT0_RCLKDIV         0xFFC00828      /* SPORT0 Receive Clock Divider                                         */
+#define SPORT0_RFSDIV          0xFFC0082C      /* SPORT0 Receive Frame Sync Divider                            */
+#define SPORT0_STAT                    0xFFC00830      /* SPORT0 Status Register                                                       */
+#define SPORT0_CHNL                    0xFFC00834      /* SPORT0 Current Channel Register                                      */
+#define SPORT0_MCMC1           0xFFC00838      /* SPORT0 Multi-Channel Configuration Register 1        */
+#define SPORT0_MCMC2           0xFFC0083C      /* SPORT0 Multi-Channel Configuration Register 2        */
+#define SPORT0_MTCS0           0xFFC00840      /* SPORT0 Multi-Channel Transmit Select Register 0      */
+#define SPORT0_MTCS1           0xFFC00844      /* SPORT0 Multi-Channel Transmit Select Register 1      */
+#define SPORT0_MTCS2           0xFFC00848      /* SPORT0 Multi-Channel Transmit Select Register 2      */
+#define SPORT0_MTCS3           0xFFC0084C      /* SPORT0 Multi-Channel Transmit Select Register 3      */
+#define SPORT0_MRCS0           0xFFC00850      /* SPORT0 Multi-Channel Receive Select Register 0       */
+#define SPORT0_MRCS1           0xFFC00854      /* SPORT0 Multi-Channel Receive Select Register 1       */
+#define SPORT0_MRCS2           0xFFC00858      /* SPORT0 Multi-Channel Receive Select Register 2       */
+#define SPORT0_MRCS3           0xFFC0085C      /* SPORT0 Multi-Channel Receive Select Register 3       */
+
+/* SPORT1 Controller           (0xFFC00900 - 0xFFC009FF)                                                                               */
+#define SPORT1_TCR1                    0xFFC00900      /* SPORT1 Transmit Configuration 1 Register                     */
+#define SPORT1_TCR2                    0xFFC00904      /* SPORT1 Transmit Configuration 2 Register                     */
+#define SPORT1_TCLKDIV         0xFFC00908      /* SPORT1 Transmit Clock Divider                                        */
+#define SPORT1_TFSDIV          0xFFC0090C      /* SPORT1 Transmit Frame Sync Divider                           */
+#define SPORT1_TX                      0xFFC00910      /* SPORT1 TX Data Register                                                      */
+#define SPORT1_RX                      0xFFC00918      /* SPORT1 RX Data Register                                                      */
+#define SPORT1_RCR1                    0xFFC00920      /* SPORT1 Transmit Configuration 1 Register                     */
+#define SPORT1_RCR2                    0xFFC00924      /* SPORT1 Transmit Configuration 2 Register                     */
+#define SPORT1_RCLKDIV         0xFFC00928      /* SPORT1 Receive Clock Divider                                         */
+#define SPORT1_RFSDIV          0xFFC0092C      /* SPORT1 Receive Frame Sync Divider                            */
+#define SPORT1_STAT                    0xFFC00930      /* SPORT1 Status Register                                                       */
+#define SPORT1_CHNL                    0xFFC00934      /* SPORT1 Current Channel Register                                      */
+#define SPORT1_MCMC1           0xFFC00938      /* SPORT1 Multi-Channel Configuration Register 1        */
+#define SPORT1_MCMC2           0xFFC0093C      /* SPORT1 Multi-Channel Configuration Register 2        */
+#define SPORT1_MTCS0           0xFFC00940      /* SPORT1 Multi-Channel Transmit Select Register 0      */
+#define SPORT1_MTCS1           0xFFC00944      /* SPORT1 Multi-Channel Transmit Select Register 1      */
+#define SPORT1_MTCS2           0xFFC00948      /* SPORT1 Multi-Channel Transmit Select Register 2      */
+#define SPORT1_MTCS3           0xFFC0094C      /* SPORT1 Multi-Channel Transmit Select Register 3      */
+#define SPORT1_MRCS0           0xFFC00950      /* SPORT1 Multi-Channel Receive Select Register 0       */
+#define SPORT1_MRCS1           0xFFC00954      /* SPORT1 Multi-Channel Receive Select Register 1       */
+#define SPORT1_MRCS2           0xFFC00958      /* SPORT1 Multi-Channel Receive Select Register 2       */
+#define SPORT1_MRCS3           0xFFC0095C      /* SPORT1 Multi-Channel Receive Select Register 3       */
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)                                                               */
+#define EBIU_AMGCTL                    0xFFC00A00      /* Asynchronous Memory Global Control Register  */
+#define EBIU_AMBCTL0           0xFFC00A04      /* Asynchronous Memory Bank Control Register 0  */
+#define EBIU_AMBCTL1           0xFFC00A08      /* Asynchronous Memory Bank Control Register 1  */
+#define EBIU_SDGCTL                    0xFFC00A10      /* SDRAM Global Control Register                                */
+#define EBIU_SDBCTL                    0xFFC00A14      /* SDRAM Bank Control Register                                  */
+#define EBIU_SDRRC                     0xFFC00A18      /* SDRAM Refresh Rate Control Register                  */
+#define EBIU_SDSTAT                    0xFFC00A1C      /* SDRAM Status Register                                                */
+
+/* DMA Traffic Control Registers                                                                                                       */
+#define DMA_TCPER                      0xFFC00B0C      /* Traffic Control Periods Register                     */
+#define DMA_TCCNT                      0xFFC00B10      /* Traffic Control Current Counts Register      */
+
+/* DMA Controller (0xFFC00C00 - 0xFFC00FFF)                                                                                                                    */
+#define DMA0_NEXT_DESC_PTR             0xFFC00C00      /* DMA Channel 0 Next Descriptor Pointer Register               */
+#define DMA0_START_ADDR                        0xFFC00C04      /* DMA Channel 0 Start Address Register                                 */
+#define DMA0_CONFIG                            0xFFC00C08      /* DMA Channel 0 Configuration Register                                 */
+#define DMA0_X_COUNT                   0xFFC00C10      /* DMA Channel 0 X Count Register                                               */
+#define DMA0_X_MODIFY                  0xFFC00C14      /* DMA Channel 0 X Modify Register                                              */
+#define DMA0_Y_COUNT                   0xFFC00C18      /* DMA Channel 0 Y Count Register                                               */
+#define DMA0_Y_MODIFY                  0xFFC00C1C      /* DMA Channel 0 Y Modify Register                                              */
+#define DMA0_CURR_DESC_PTR             0xFFC00C20      /* DMA Channel 0 Current Descriptor Pointer Register    */
+#define DMA0_CURR_ADDR                 0xFFC00C24      /* DMA Channel 0 Current Address Register                               */
+#define DMA0_IRQ_STATUS                        0xFFC00C28      /* DMA Channel 0 Interrupt/Status Register                              */
+#define DMA0_PERIPHERAL_MAP            0xFFC00C2C      /* DMA Channel 0 Peripheral Map Register                                */
+#define DMA0_CURR_X_COUNT              0xFFC00C30      /* DMA Channel 0 Current X Count Register                               */
+#define DMA0_CURR_Y_COUNT              0xFFC00C38      /* DMA Channel 0 Current Y Count Register                               */
+
+#define DMA1_NEXT_DESC_PTR             0xFFC00C40      /* DMA Channel 1 Next Descriptor Pointer Register               */
+#define DMA1_START_ADDR                        0xFFC00C44      /* DMA Channel 1 Start Address Register                                 */
+#define DMA1_CONFIG                            0xFFC00C48      /* DMA Channel 1 Configuration Register                                 */
+#define DMA1_X_COUNT                   0xFFC00C50      /* DMA Channel 1 X Count Register                                               */
+#define DMA1_X_MODIFY                  0xFFC00C54      /* DMA Channel 1 X Modify Register                                              */
+#define DMA1_Y_COUNT                   0xFFC00C58      /* DMA Channel 1 Y Count Register                                               */
+#define DMA1_Y_MODIFY                  0xFFC00C5C      /* DMA Channel 1 Y Modify Register                                              */
+#define DMA1_CURR_DESC_PTR             0xFFC00C60      /* DMA Channel 1 Current Descriptor Pointer Register    */
+#define DMA1_CURR_ADDR                 0xFFC00C64      /* DMA Channel 1 Current Address Register                               */
+#define DMA1_IRQ_STATUS                        0xFFC00C68      /* DMA Channel 1 Interrupt/Status Register                              */
+#define DMA1_PERIPHERAL_MAP            0xFFC00C6C      /* DMA Channel 1 Peripheral Map Register                                */
+#define DMA1_CURR_X_COUNT              0xFFC00C70      /* DMA Channel 1 Current X Count Register                               */
+#define DMA1_CURR_Y_COUNT              0xFFC00C78      /* DMA Channel 1 Current Y Count Register                               */
+
+#define DMA2_NEXT_DESC_PTR             0xFFC00C80      /* DMA Channel 2 Next Descriptor Pointer Register               */
+#define DMA2_START_ADDR                        0xFFC00C84      /* DMA Channel 2 Start Address Register                                 */
+#define DMA2_CONFIG                            0xFFC00C88      /* DMA Channel 2 Configuration Register                                 */
+#define DMA2_X_COUNT                   0xFFC00C90      /* DMA Channel 2 X Count Register                                               */
+#define DMA2_X_MODIFY                  0xFFC00C94      /* DMA Channel 2 X Modify Register                                              */
+#define DMA2_Y_COUNT                   0xFFC00C98      /* DMA Channel 2 Y Count Register                                               */
+#define DMA2_Y_MODIFY                  0xFFC00C9C      /* DMA Channel 2 Y Modify Register                                              */
+#define DMA2_CURR_DESC_PTR             0xFFC00CA0      /* DMA Channel 2 Current Descriptor Pointer Register    */
+#define DMA2_CURR_ADDR                 0xFFC00CA4      /* DMA Channel 2 Current Address Register                               */
+#define DMA2_IRQ_STATUS                        0xFFC00CA8      /* DMA Channel 2 Interrupt/Status Register                              */
+#define DMA2_PERIPHERAL_MAP            0xFFC00CAC      /* DMA Channel 2 Peripheral Map Register                                */
+#define DMA2_CURR_X_COUNT              0xFFC00CB0      /* DMA Channel 2 Current X Count Register                               */
+#define DMA2_CURR_Y_COUNT              0xFFC00CB8      /* DMA Channel 2 Current Y Count Register                               */
+
+#define DMA3_NEXT_DESC_PTR             0xFFC00CC0      /* DMA Channel 3 Next Descriptor Pointer Register               */
+#define DMA3_START_ADDR                        0xFFC00CC4      /* DMA Channel 3 Start Address Register                                 */
+#define DMA3_CONFIG                            0xFFC00CC8      /* DMA Channel 3 Configuration Register                                 */
+#define DMA3_X_COUNT                   0xFFC00CD0      /* DMA Channel 3 X Count Register                                               */
+#define DMA3_X_MODIFY                  0xFFC00CD4      /* DMA Channel 3 X Modify Register                                              */
+#define DMA3_Y_COUNT                   0xFFC00CD8      /* DMA Channel 3 Y Count Register                                               */
+#define DMA3_Y_MODIFY                  0xFFC00CDC      /* DMA Channel 3 Y Modify Register                                              */
+#define DMA3_CURR_DESC_PTR             0xFFC00CE0      /* DMA Channel 3 Current Descriptor Pointer Register    */
+#define DMA3_CURR_ADDR                 0xFFC00CE4      /* DMA Channel 3 Current Address Register                               */
+#define DMA3_IRQ_STATUS                        0xFFC00CE8      /* DMA Channel 3 Interrupt/Status Register                              */
+#define DMA3_PERIPHERAL_MAP            0xFFC00CEC      /* DMA Channel 3 Peripheral Map Register                                */
+#define DMA3_CURR_X_COUNT              0xFFC00CF0      /* DMA Channel 3 Current X Count Register                               */
+#define DMA3_CURR_Y_COUNT              0xFFC00CF8      /* DMA Channel 3 Current Y Count Register                               */
+
+#define DMA4_NEXT_DESC_PTR             0xFFC00D00      /* DMA Channel 4 Next Descriptor Pointer Register               */
+#define DMA4_START_ADDR                        0xFFC00D04      /* DMA Channel 4 Start Address Register                                 */
+#define DMA4_CONFIG                            0xFFC00D08      /* DMA Channel 4 Configuration Register                                 */
+#define DMA4_X_COUNT                   0xFFC00D10      /* DMA Channel 4 X Count Register                                               */
+#define DMA4_X_MODIFY                  0xFFC00D14      /* DMA Channel 4 X Modify Register                                              */
+#define DMA4_Y_COUNT                   0xFFC00D18      /* DMA Channel 4 Y Count Register                                               */
+#define DMA4_Y_MODIFY                  0xFFC00D1C      /* DMA Channel 4 Y Modify Register                                              */
+#define DMA4_CURR_DESC_PTR             0xFFC00D20      /* DMA Channel 4 Current Descriptor Pointer Register    */
+#define DMA4_CURR_ADDR                 0xFFC00D24      /* DMA Channel 4 Current Address Register                               */
+#define DMA4_IRQ_STATUS                        0xFFC00D28      /* DMA Channel 4 Interrupt/Status Register                              */
+#define DMA4_PERIPHERAL_MAP            0xFFC00D2C      /* DMA Channel 4 Peripheral Map Register                                */
+#define DMA4_CURR_X_COUNT              0xFFC00D30      /* DMA Channel 4 Current X Count Register                               */
+#define DMA4_CURR_Y_COUNT              0xFFC00D38      /* DMA Channel 4 Current Y Count Register                               */
+
+#define DMA5_NEXT_DESC_PTR             0xFFC00D40      /* DMA Channel 5 Next Descriptor Pointer Register               */
+#define DMA5_START_ADDR                        0xFFC00D44      /* DMA Channel 5 Start Address Register                                 */
+#define DMA5_CONFIG                            0xFFC00D48      /* DMA Channel 5 Configuration Register                                 */
+#define DMA5_X_COUNT                   0xFFC00D50      /* DMA Channel 5 X Count Register                                               */
+#define DMA5_X_MODIFY                  0xFFC00D54      /* DMA Channel 5 X Modify Register                                              */
+#define DMA5_Y_COUNT                   0xFFC00D58      /* DMA Channel 5 Y Count Register                                               */
+#define DMA5_Y_MODIFY                  0xFFC00D5C      /* DMA Channel 5 Y Modify Register                                              */
+#define DMA5_CURR_DESC_PTR             0xFFC00D60      /* DMA Channel 5 Current Descriptor Pointer Register    */
+#define DMA5_CURR_ADDR                 0xFFC00D64      /* DMA Channel 5 Current Address Register                               */
+#define DMA5_IRQ_STATUS                        0xFFC00D68      /* DMA Channel 5 Interrupt/Status Register                              */
+#define DMA5_PERIPHERAL_MAP            0xFFC00D6C      /* DMA Channel 5 Peripheral Map Register                                */
+#define DMA5_CURR_X_COUNT              0xFFC00D70      /* DMA Channel 5 Current X Count Register                               */
+#define DMA5_CURR_Y_COUNT              0xFFC00D78      /* DMA Channel 5 Current Y Count Register                               */
+
+#define DMA6_NEXT_DESC_PTR             0xFFC00D80      /* DMA Channel 6 Next Descriptor Pointer Register               */
+#define DMA6_START_ADDR                        0xFFC00D84      /* DMA Channel 6 Start Address Register                                 */
+#define DMA6_CONFIG                            0xFFC00D88      /* DMA Channel 6 Configuration Register                                 */
+#define DMA6_X_COUNT                   0xFFC00D90      /* DMA Channel 6 X Count Register                                               */
+#define DMA6_X_MODIFY                  0xFFC00D94      /* DMA Channel 6 X Modify Register                                              */
+#define DMA6_Y_COUNT                   0xFFC00D98      /* DMA Channel 6 Y Count Register                                               */
+#define DMA6_Y_MODIFY                  0xFFC00D9C      /* DMA Channel 6 Y Modify Register                                              */
+#define DMA6_CURR_DESC_PTR             0xFFC00DA0      /* DMA Channel 6 Current Descriptor Pointer Register    */
+#define DMA6_CURR_ADDR                 0xFFC00DA4      /* DMA Channel 6 Current Address Register                               */
+#define DMA6_IRQ_STATUS                        0xFFC00DA8      /* DMA Channel 6 Interrupt/Status Register                              */
+#define DMA6_PERIPHERAL_MAP            0xFFC00DAC      /* DMA Channel 6 Peripheral Map Register                                */
+#define DMA6_CURR_X_COUNT              0xFFC00DB0      /* DMA Channel 6 Current X Count Register                               */
+#define DMA6_CURR_Y_COUNT              0xFFC00DB8      /* DMA Channel 6 Current Y Count Register                               */
+
+#define DMA7_NEXT_DESC_PTR             0xFFC00DC0      /* DMA Channel 7 Next Descriptor Pointer Register               */
+#define DMA7_START_ADDR                        0xFFC00DC4      /* DMA Channel 7 Start Address Register                                 */
+#define DMA7_CONFIG                            0xFFC00DC8      /* DMA Channel 7 Configuration Register                                 */
+#define DMA7_X_COUNT                   0xFFC00DD0      /* DMA Channel 7 X Count Register                                               */
+#define DMA7_X_MODIFY                  0xFFC00DD4      /* DMA Channel 7 X Modify Register                                              */
+#define DMA7_Y_COUNT                   0xFFC00DD8      /* DMA Channel 7 Y Count Register                                               */
+#define DMA7_Y_MODIFY                  0xFFC00DDC      /* DMA Channel 7 Y Modify Register                                              */
+#define DMA7_CURR_DESC_PTR             0xFFC00DE0      /* DMA Channel 7 Current Descriptor Pointer Register    */
+#define DMA7_CURR_ADDR                 0xFFC00DE4      /* DMA Channel 7 Current Address Register                               */
+#define DMA7_IRQ_STATUS                        0xFFC00DE8      /* DMA Channel 7 Interrupt/Status Register                              */
+#define DMA7_PERIPHERAL_MAP            0xFFC00DEC      /* DMA Channel 7 Peripheral Map Register                                */
+#define DMA7_CURR_X_COUNT              0xFFC00DF0      /* DMA Channel 7 Current X Count Register                               */
+#define DMA7_CURR_Y_COUNT              0xFFC00DF8      /* DMA Channel 7 Current Y Count Register                               */
+
+#define DMA8_NEXT_DESC_PTR             0xFFC00E00      /* DMA Channel 8 Next Descriptor Pointer Register               */
+#define DMA8_START_ADDR                        0xFFC00E04      /* DMA Channel 8 Start Address Register                                 */
+#define DMA8_CONFIG                            0xFFC00E08      /* DMA Channel 8 Configuration Register                                 */
+#define DMA8_X_COUNT                   0xFFC00E10      /* DMA Channel 8 X Count Register                                               */
+#define DMA8_X_MODIFY                  0xFFC00E14      /* DMA Channel 8 X Modify Register                                              */
+#define DMA8_Y_COUNT                   0xFFC00E18      /* DMA Channel 8 Y Count Register                                               */
+#define DMA8_Y_MODIFY                  0xFFC00E1C      /* DMA Channel 8 Y Modify Register                                              */
+#define DMA8_CURR_DESC_PTR             0xFFC00E20      /* DMA Channel 8 Current Descriptor Pointer Register    */
+#define DMA8_CURR_ADDR                 0xFFC00E24      /* DMA Channel 8 Current Address Register                               */
+#define DMA8_IRQ_STATUS                        0xFFC00E28      /* DMA Channel 8 Interrupt/Status Register                              */
+#define DMA8_PERIPHERAL_MAP            0xFFC00E2C      /* DMA Channel 8 Peripheral Map Register                                */
+#define DMA8_CURR_X_COUNT              0xFFC00E30      /* DMA Channel 8 Current X Count Register                               */
+#define DMA8_CURR_Y_COUNT              0xFFC00E38      /* DMA Channel 8 Current Y Count Register                               */
+
+#define DMA9_NEXT_DESC_PTR             0xFFC00E40      /* DMA Channel 9 Next Descriptor Pointer Register               */
+#define DMA9_START_ADDR                        0xFFC00E44      /* DMA Channel 9 Start Address Register                                 */
+#define DMA9_CONFIG                            0xFFC00E48      /* DMA Channel 9 Configuration Register                                 */
+#define DMA9_X_COUNT                   0xFFC00E50      /* DMA Channel 9 X Count Register                                               */
+#define DMA9_X_MODIFY                  0xFFC00E54      /* DMA Channel 9 X Modify Register                                              */
+#define DMA9_Y_COUNT                   0xFFC00E58      /* DMA Channel 9 Y Count Register                                               */
+#define DMA9_Y_MODIFY                  0xFFC00E5C      /* DMA Channel 9 Y Modify Register                                              */
+#define DMA9_CURR_DESC_PTR             0xFFC00E60      /* DMA Channel 9 Current Descriptor Pointer Register    */
+#define DMA9_CURR_ADDR                 0xFFC00E64      /* DMA Channel 9 Current Address Register                               */
+#define DMA9_IRQ_STATUS                        0xFFC00E68      /* DMA Channel 9 Interrupt/Status Register                              */
+#define DMA9_PERIPHERAL_MAP            0xFFC00E6C      /* DMA Channel 9 Peripheral Map Register                                */
+#define DMA9_CURR_X_COUNT              0xFFC00E70      /* DMA Channel 9 Current X Count Register                               */
+#define DMA9_CURR_Y_COUNT              0xFFC00E78      /* DMA Channel 9 Current Y Count Register                               */
+
+#define DMA10_NEXT_DESC_PTR            0xFFC00E80      /* DMA Channel 10 Next Descriptor Pointer Register              */
+#define DMA10_START_ADDR               0xFFC00E84      /* DMA Channel 10 Start Address Register                                */
+#define DMA10_CONFIG                   0xFFC00E88      /* DMA Channel 10 Configuration Register                                */
+#define DMA10_X_COUNT                  0xFFC00E90      /* DMA Channel 10 X Count Register                                              */
+#define DMA10_X_MODIFY                 0xFFC00E94      /* DMA Channel 10 X Modify Register                                             */
+#define DMA10_Y_COUNT                  0xFFC00E98      /* DMA Channel 10 Y Count Register                                              */
+#define DMA10_Y_MODIFY                 0xFFC00E9C      /* DMA Channel 10 Y Modify Register                                             */
+#define DMA10_CURR_DESC_PTR            0xFFC00EA0      /* DMA Channel 10 Current Descriptor Pointer Register   */
+#define DMA10_CURR_ADDR                        0xFFC00EA4      /* DMA Channel 10 Current Address Register                              */
+#define DMA10_IRQ_STATUS               0xFFC00EA8      /* DMA Channel 10 Interrupt/Status Register                             */
+#define DMA10_PERIPHERAL_MAP   0xFFC00EAC      /* DMA Channel 10 Peripheral Map Register                               */
+#define DMA10_CURR_X_COUNT             0xFFC00EB0      /* DMA Channel 10 Current X Count Register                              */
+#define DMA10_CURR_Y_COUNT             0xFFC00EB8      /* DMA Channel 10 Current Y Count Register                              */
+
+#define DMA11_NEXT_DESC_PTR            0xFFC00EC0      /* DMA Channel 11 Next Descriptor Pointer Register              */
+#define DMA11_START_ADDR               0xFFC00EC4      /* DMA Channel 11 Start Address Register                                */
+#define DMA11_CONFIG                   0xFFC00EC8      /* DMA Channel 11 Configuration Register                                */
+#define DMA11_X_COUNT                  0xFFC00ED0      /* DMA Channel 11 X Count Register                                              */
+#define DMA11_X_MODIFY                 0xFFC00ED4      /* DMA Channel 11 X Modify Register                                             */
+#define DMA11_Y_COUNT                  0xFFC00ED8      /* DMA Channel 11 Y Count Register                                              */
+#define DMA11_Y_MODIFY                 0xFFC00EDC      /* DMA Channel 11 Y Modify Register                                             */
+#define DMA11_CURR_DESC_PTR            0xFFC00EE0      /* DMA Channel 11 Current Descriptor Pointer Register   */
+#define DMA11_CURR_ADDR                        0xFFC00EE4      /* DMA Channel 11 Current Address Register                              */
+#define DMA11_IRQ_STATUS               0xFFC00EE8      /* DMA Channel 11 Interrupt/Status Register                             */
+#define DMA11_PERIPHERAL_MAP   0xFFC00EEC      /* DMA Channel 11 Peripheral Map Register                               */
+#define DMA11_CURR_X_COUNT             0xFFC00EF0      /* DMA Channel 11 Current X Count Register                              */
+#define DMA11_CURR_Y_COUNT             0xFFC00EF8      /* DMA Channel 11 Current Y Count Register                              */
+
+#define MDMA_D0_NEXT_DESC_PTR  0xFFC00F00      /* MemDMA Stream 0 Destination Next Descriptor Pointer Register         */
+#define MDMA_D0_START_ADDR             0xFFC00F04      /* MemDMA Stream 0 Destination Start Address Register                           */
+#define MDMA_D0_CONFIG                 0xFFC00F08      /* MemDMA Stream 0 Destination Configuration Register                           */
+#define MDMA_D0_X_COUNT                        0xFFC00F10      /* MemDMA Stream 0 Destination X Count Register                                         */
+#define MDMA_D0_X_MODIFY               0xFFC00F14      /* MemDMA Stream 0 Destination X Modify Register                                        */
+#define MDMA_D0_Y_COUNT                        0xFFC00F18      /* MemDMA Stream 0 Destination Y Count Register                                         */
+#define MDMA_D0_Y_MODIFY               0xFFC00F1C      /* MemDMA Stream 0 Destination Y Modify Register                                        */
+#define MDMA_D0_CURR_DESC_PTR  0xFFC00F20      /* MemDMA Stream 0 Destination Current Descriptor Pointer Register      */
+#define MDMA_D0_CURR_ADDR              0xFFC00F24      /* MemDMA Stream 0 Destination Current Address Register                         */
+#define MDMA_D0_IRQ_STATUS             0xFFC00F28      /* MemDMA Stream 0 Destination Interrupt/Status Register                        */
+#define MDMA_D0_PERIPHERAL_MAP 0xFFC00F2C      /* MemDMA Stream 0 Destination Peripheral Map Register                          */
+#define MDMA_D0_CURR_X_COUNT   0xFFC00F30      /* MemDMA Stream 0 Destination Current X Count Register                         */
+#define MDMA_D0_CURR_Y_COUNT   0xFFC00F38      /* MemDMA Stream 0 Destination Current Y Count Register                         */
+
+#define MDMA_S0_NEXT_DESC_PTR  0xFFC00F40      /* MemDMA Stream 0 Source Next Descriptor Pointer Register                      */
+#define MDMA_S0_START_ADDR             0xFFC00F44      /* MemDMA Stream 0 Source Start Address Register                                        */
+#define MDMA_S0_CONFIG                 0xFFC00F48      /* MemDMA Stream 0 Source Configuration Register                                        */
+#define MDMA_S0_X_COUNT                        0xFFC00F50      /* MemDMA Stream 0 Source X Count Register                                                      */
+#define MDMA_S0_X_MODIFY               0xFFC00F54      /* MemDMA Stream 0 Source X Modify Register                                                     */
+#define MDMA_S0_Y_COUNT                        0xFFC00F58      /* MemDMA Stream 0 Source Y Count Register                                                      */
+#define MDMA_S0_Y_MODIFY               0xFFC00F5C      /* MemDMA Stream 0 Source Y Modify Register                                                     */
+#define MDMA_S0_CURR_DESC_PTR  0xFFC00F60      /* MemDMA Stream 0 Source Current Descriptor Pointer Register           */
+#define MDMA_S0_CURR_ADDR              0xFFC00F64      /* MemDMA Stream 0 Source Current Address Register                                      */
+#define MDMA_S0_IRQ_STATUS             0xFFC00F68      /* MemDMA Stream 0 Source Interrupt/Status Register                                     */
+#define MDMA_S0_PERIPHERAL_MAP 0xFFC00F6C      /* MemDMA Stream 0 Source Peripheral Map Register                                       */
+#define MDMA_S0_CURR_X_COUNT   0xFFC00F70      /* MemDMA Stream 0 Source Current X Count Register                                      */
+#define MDMA_S0_CURR_Y_COUNT   0xFFC00F78      /* MemDMA Stream 0 Source Current Y Count Register                                      */
+
+#define MDMA_D1_NEXT_DESC_PTR  0xFFC00F80      /* MemDMA Stream 1 Destination Next Descriptor Pointer Register         */
+#define MDMA_D1_START_ADDR             0xFFC00F84      /* MemDMA Stream 1 Destination Start Address Register                           */
+#define MDMA_D1_CONFIG                 0xFFC00F88      /* MemDMA Stream 1 Destination Configuration Register                           */
+#define MDMA_D1_X_COUNT                        0xFFC00F90      /* MemDMA Stream 1 Destination X Count Register                                         */
+#define MDMA_D1_X_MODIFY               0xFFC00F94      /* MemDMA Stream 1 Destination X Modify Register                                        */
+#define MDMA_D1_Y_COUNT                        0xFFC00F98      /* MemDMA Stream 1 Destination Y Count Register                                         */
+#define MDMA_D1_Y_MODIFY               0xFFC00F9C      /* MemDMA Stream 1 Destination Y Modify Register                                        */
+#define MDMA_D1_CURR_DESC_PTR  0xFFC00FA0      /* MemDMA Stream 1 Destination Current Descriptor Pointer Register      */
+#define MDMA_D1_CURR_ADDR              0xFFC00FA4      /* MemDMA Stream 1 Destination Current Address Register                         */
+#define MDMA_D1_IRQ_STATUS             0xFFC00FA8      /* MemDMA Stream 1 Destination Interrupt/Status Register                        */
+#define MDMA_D1_PERIPHERAL_MAP 0xFFC00FAC      /* MemDMA Stream 1 Destination Peripheral Map Register                          */
+#define MDMA_D1_CURR_X_COUNT   0xFFC00FB0      /* MemDMA Stream 1 Destination Current X Count Register                         */
+#define MDMA_D1_CURR_Y_COUNT   0xFFC00FB8      /* MemDMA Stream 1 Destination Current Y Count Register                         */
+
+#define MDMA_S1_NEXT_DESC_PTR  0xFFC00FC0      /* MemDMA Stream 1 Source Next Descriptor Pointer Register                      */
+#define MDMA_S1_START_ADDR             0xFFC00FC4      /* MemDMA Stream 1 Source Start Address Register                                        */
+#define MDMA_S1_CONFIG                 0xFFC00FC8      /* MemDMA Stream 1 Source Configuration Register                                        */
+#define MDMA_S1_X_COUNT                        0xFFC00FD0      /* MemDMA Stream 1 Source X Count Register                                                      */
+#define MDMA_S1_X_MODIFY               0xFFC00FD4      /* MemDMA Stream 1 Source X Modify Register                                                     */
+#define MDMA_S1_Y_COUNT                        0xFFC00FD8      /* MemDMA Stream 1 Source Y Count Register                                                      */
+#define MDMA_S1_Y_MODIFY               0xFFC00FDC      /* MemDMA Stream 1 Source Y Modify Register                                                     */
+#define MDMA_S1_CURR_DESC_PTR  0xFFC00FE0      /* MemDMA Stream 1 Source Current Descriptor Pointer Register           */
+#define MDMA_S1_CURR_ADDR              0xFFC00FE4      /* MemDMA Stream 1 Source Current Address Register                                      */
+#define MDMA_S1_IRQ_STATUS             0xFFC00FE8      /* MemDMA Stream 1 Source Interrupt/Status Register                                     */
+#define MDMA_S1_PERIPHERAL_MAP 0xFFC00FEC      /* MemDMA Stream 1 Source Peripheral Map Register                                       */
+#define MDMA_S1_CURR_X_COUNT   0xFFC00FF0      /* MemDMA Stream 1 Source Current X Count Register                                      */
+#define MDMA_S1_CURR_Y_COUNT   0xFFC00FF8      /* MemDMA Stream 1 Source Current Y Count Register                                      */
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)                             */
+#define PPI_CONTROL                    0xFFC01000      /* PPI Control Register                 */
+#define PPI_STATUS                     0xFFC01004      /* PPI Status Register                  */
+#define PPI_COUNT                      0xFFC01008      /* PPI Transfer Count Register  */
+#define PPI_DELAY                      0xFFC0100C      /* PPI Delay Count Register             */
+#define PPI_FRAME                      0xFFC01010      /* PPI Frame Length Register    */
+
+/* Two-Wire Interface          (0xFFC01400 - 0xFFC014FF)                                                               */
+#define TWI_CLKDIV                     0xFFC01400      /* Serial Clock Divider Register                        */
+#define TWI_CONTROL                    0xFFC01404      /* TWI Control Register                                         */
+#define TWI_SLAVE_CTL          0xFFC01408      /* Slave Mode Control Register                          */
+#define TWI_SLAVE_STAT         0xFFC0140C      /* Slave Mode Status Register                           */
+#define TWI_SLAVE_ADDR         0xFFC01410      /* Slave Mode Address Register                          */
+#define TWI_MASTER_CTL         0xFFC01414      /* Master Mode Control Register                         */
+#define TWI_MASTER_STAT                0xFFC01418      /* Master Mode Status Register                          */
+#define TWI_MASTER_ADDR                0xFFC0141C      /* Master Mode Address Register                         */
+#define TWI_INT_STAT           0xFFC01420      /* TWI Interrupt Status Register                        */
+#define TWI_INT_MASK           0xFFC01424      /* TWI Master Interrupt Mask Register           */
+#define TWI_FIFO_CTL           0xFFC01428      /* FIFO Control Register                                        */
+#define TWI_FIFO_STAT          0xFFC0142C      /* FIFO Status Register                                         */
+#define TWI_XMT_DATA8          0xFFC01480      /* FIFO Transmit Data Single Byte Register      */
+#define TWI_XMT_DATA16         0xFFC01484      /* FIFO Transmit Data Double Byte Register      */
+#define TWI_RCV_DATA8          0xFFC01488      /* FIFO Receive Data Single Byte Register       */
+#define TWI_RCV_DATA16         0xFFC0148C      /* FIFO Receive Data Double Byte Register       */
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)                                                                                                */
+#define PORTGIO                                        0xFFC01500      /* Port G I/O Pin State Specify Register                                */
+#define PORTGIO_CLEAR                  0xFFC01504      /* Port G I/O Peripheral Interrupt Clear Register               */
+#define PORTGIO_SET                            0xFFC01508      /* Port G I/O Peripheral Interrupt Set Register                 */
+#define PORTGIO_TOGGLE                 0xFFC0150C      /* Port G I/O Pin State Toggle Register                                 */
+#define PORTGIO_MASKA                  0xFFC01510      /* Port G I/O Mask State Specify Interrupt A Register   */
+#define PORTGIO_MASKA_CLEAR            0xFFC01514      /* Port G I/O Mask Disable Interrupt A Register                 */
+#define PORTGIO_MASKA_SET              0xFFC01518      /* Port G I/O Mask Enable Interrupt A Register                  */
+#define PORTGIO_MASKA_TOGGLE   0xFFC0151C      /* Port G I/O Mask Toggle Enable Interrupt A Register   */
+#define PORTGIO_MASKB                  0xFFC01520      /* Port G I/O Mask State Specify Interrupt B Register   */
+#define PORTGIO_MASKB_CLEAR            0xFFC01524      /* Port G I/O Mask Disable Interrupt B Register                 */
+#define PORTGIO_MASKB_SET              0xFFC01528      /* Port G I/O Mask Enable Interrupt B Register                  */
+#define PORTGIO_MASKB_TOGGLE   0xFFC0152C      /* Port G I/O Mask Toggle Enable Interrupt B Register   */
+#define PORTGIO_DIR                            0xFFC01530      /* Port G I/O Direction Register                                                */
+#define PORTGIO_POLAR                  0xFFC01534      /* Port G I/O Source Polarity Register                                  */
+#define PORTGIO_EDGE                   0xFFC01538      /* Port G I/O Source Sensitivity Register                               */
+#define PORTGIO_BOTH                   0xFFC0153C      /* Port G I/O Set on BOTH Edges Register                                */
+#define PORTGIO_INEN                   0xFFC01540      /* Port G I/O Input Enable Register                                             */
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)                                                                                                */
+#define PORTHIO                                        0xFFC01700      /* Port H I/O Pin State Specify Register                                */
+#define PORTHIO_CLEAR                  0xFFC01704      /* Port H I/O Peripheral Interrupt Clear Register               */
+#define PORTHIO_SET                            0xFFC01708      /* Port H I/O Peripheral Interrupt Set Register                 */
+#define PORTHIO_TOGGLE                 0xFFC0170C      /* Port H I/O Pin State Toggle Register                                 */
+#define PORTHIO_MASKA                  0xFFC01710      /* Port H I/O Mask State Specify Interrupt A Register   */
+#define PORTHIO_MASKA_CLEAR            0xFFC01714      /* Port H I/O Mask Disable Interrupt A Register                 */
+#define PORTHIO_MASKA_SET              0xFFC01718      /* Port H I/O Mask Enable Interrupt A Register                  */
+#define PORTHIO_MASKA_TOGGLE   0xFFC0171C      /* Port H I/O Mask Toggle Enable Interrupt A Register   */
+#define PORTHIO_MASKB                  0xFFC01720      /* Port H I/O Mask State Specify Interrupt B Register   */
+#define PORTHIO_MASKB_CLEAR            0xFFC01724      /* Port H I/O Mask Disable Interrupt B Register                 */
+#define PORTHIO_MASKB_SET              0xFFC01728      /* Port H I/O Mask Enable Interrupt B Register                  */
+#define PORTHIO_MASKB_TOGGLE   0xFFC0172C      /* Port H I/O Mask Toggle Enable Interrupt B Register   */
+#define PORTHIO_DIR                            0xFFC01730      /* Port H I/O Direction Register                                                */
+#define PORTHIO_POLAR                  0xFFC01734      /* Port H I/O Source Polarity Register                                  */
+#define PORTHIO_EDGE                   0xFFC01738      /* Port H I/O Source Sensitivity Register                               */
+#define PORTHIO_BOTH                   0xFFC0173C      /* Port H I/O Set on BOTH Edges Register                                */
+#define PORTHIO_INEN                   0xFFC01740      /* Port H I/O Input Enable Register                                             */
+
+/* UART1 Controller            (0xFFC02000 - 0xFFC020FF)                                                               */
+#define UART1_THR                      0xFFC02000      /* Transmit Holding register                    */
+#define UART1_RBR                      0xFFC02000      /* Receive Buffer register                              */
+#define UART1_DLL                      0xFFC02000      /* Divisor Latch (Low-Byte)                             */
+#define UART1_IER                      0xFFC02004      /* Interrupt Enable Register                    */
+#define UART1_DLH                      0xFFC02004      /* Divisor Latch (High-Byte)                    */
+#define UART1_IIR                      0xFFC02008      /* Interrupt Identification Register    */
+#define UART1_LCR                      0xFFC0200C      /* Line Control Register                                */
+#define UART1_MCR                      0xFFC02010      /* Modem Control Register                               */
+#define UART1_LSR                      0xFFC02014      /* Line Status Register                                 */
+#define UART1_MSR                      0xFFC02018      /* Modem Status Register                                */
+#define UART1_SCR                      0xFFC0201C      /* SCR Scratch Register                                 */
+#define UART1_GCTL                     0xFFC02024      /* Global Control Register                              */
+
+/* CAN Controller              (0xFFC02A00 - 0xFFC02FFF)                                                                               */
+/* For Mailboxes 0-15                                                                                                                                  */
+#define CAN_MC1                                0xFFC02A00      /* Mailbox config reg 1                                                 */
+#define CAN_MD1                                0xFFC02A04      /* Mailbox direction reg 1                                              */
+#define CAN_TRS1                       0xFFC02A08      /* Transmit Request Set reg 1                                   */
+#define CAN_TRR1                       0xFFC02A0C      /* Transmit Request Reset reg 1                                 */
+#define CAN_TA1                                0xFFC02A10      /* Transmit Acknowledge reg 1                                   */
+#define CAN_AA1                                0xFFC02A14      /* Transmit Abort Acknowledge reg 1                             */
+#define CAN_RMP1                       0xFFC02A18      /* Receive Message Pending reg 1                                */
+#define CAN_RML1                       0xFFC02A1C      /* Receive Message Lost reg 1                                   */
+#define CAN_MBTIF1                     0xFFC02A20      /* Mailbox Transmit Interrupt Flag reg 1                */
+#define CAN_MBRIF1                     0xFFC02A24      /* Mailbox Receive  Interrupt Flag reg 1                */
+#define CAN_MBIM1                      0xFFC02A28      /* Mailbox Interrupt Mask reg 1                                 */
+#define CAN_RFH1                       0xFFC02A2C      /* Remote Frame Handling reg 1                                  */
+#define CAN_OPSS1                      0xFFC02A30      /* Overwrite Protection Single Shot Xmit reg 1  */
+
+/* For Mailboxes 16-31                                                                                                                                 */
+#define CAN_MC2                                0xFFC02A40      /* Mailbox config reg 2                                                 */
+#define CAN_MD2                                0xFFC02A44      /* Mailbox direction reg 2                                              */
+#define CAN_TRS2                       0xFFC02A48      /* Transmit Request Set reg 2                                   */
+#define CAN_TRR2                       0xFFC02A4C      /* Transmit Request Reset reg 2                                 */
+#define CAN_TA2                                0xFFC02A50      /* Transmit Acknowledge reg 2                                   */
+#define CAN_AA2                                0xFFC02A54      /* Transmit Abort Acknowledge reg 2                             */
+#define CAN_RMP2                       0xFFC02A58      /* Receive Message Pending reg 2                                */
+#define CAN_RML2                       0xFFC02A5C      /* Receive Message Lost reg 2                                   */
+#define CAN_MBTIF2                     0xFFC02A60      /* Mailbox Transmit Interrupt Flag reg 2                */
+#define CAN_MBRIF2                     0xFFC02A64      /* Mailbox Receive  Interrupt Flag reg 2                */
+#define CAN_MBIM2                      0xFFC02A68      /* Mailbox Interrupt Mask reg 2                                 */
+#define CAN_RFH2                       0xFFC02A6C      /* Remote Frame Handling reg 2                                  */
+#define CAN_OPSS2                      0xFFC02A70      /* Overwrite Protection Single Shot Xmit reg 2  */
+
+/* CAN Configuration, Control, and Status Registers                                                                            */
+#define CAN_CLOCK                      0xFFC02A80      /* Bit Timing Configuration register 0                  */
+#define CAN_TIMING                     0xFFC02A84      /* Bit Timing Configuration register 1                  */
+#define CAN_DEBUG                      0xFFC02A88      /* Debug Register                                                               */
+#define CAN_STATUS                     0xFFC02A8C      /* Global Status Register                                               */
+#define CAN_CEC                                0xFFC02A90      /* Error Counter Register                                               */
+#define CAN_GIS                                0xFFC02A94      /* Global Interrupt Status Register                             */
+#define CAN_GIM                                0xFFC02A98      /* Global Interrupt Mask Register                               */
+#define CAN_GIF                                0xFFC02A9C      /* Global Interrupt Flag Register                               */
+#define CAN_CONTROL                    0xFFC02AA0      /* Master Control Register                                              */
+#define CAN_INTR                       0xFFC02AA4      /* Interrupt Pending Register                                   */
+#define CAN_SFCMVER                    0xFFC02AA8      /* Version Code Register                                                */
+#define CAN_MBTD                       0xFFC02AAC      /* Mailbox Temporary Disable Feature                    */
+#define CAN_EWR                                0xFFC02AB0      /* Programmable Warning Level                                   */
+#define CAN_ESR                                0xFFC02AB4      /* Error Status Register                                                */
+#define CAN_UCREG                      0xFFC02AC0      /* Universal Counter Register/Capture Register  */
+#define CAN_UCCNT                      0xFFC02AC4      /* Universal Counter                                                    */
+#define CAN_UCRC                       0xFFC02AC8      /* Universal Counter Force Reload Register              */
+#define CAN_UCCNF                      0xFFC02ACC      /* Universal Counter Configuration Register             */
+
+/* Mailbox Acceptance Masks                                                                                            */
+#define CAN_AM00L                      0xFFC02B00      /* Mailbox 0 Low Acceptance Mask        */
+#define CAN_AM00H                      0xFFC02B04      /* Mailbox 0 High Acceptance Mask       */
+#define CAN_AM01L                      0xFFC02B08      /* Mailbox 1 Low Acceptance Mask        */
+#define CAN_AM01H                      0xFFC02B0C      /* Mailbox 1 High Acceptance Mask       */
+#define CAN_AM02L                      0xFFC02B10      /* Mailbox 2 Low Acceptance Mask        */
+#define CAN_AM02H                      0xFFC02B14      /* Mailbox 2 High Acceptance Mask       */
+#define CAN_AM03L                      0xFFC02B18      /* Mailbox 3 Low Acceptance Mask        */
+#define CAN_AM03H                      0xFFC02B1C      /* Mailbox 3 High Acceptance Mask       */
+#define CAN_AM04L                      0xFFC02B20      /* Mailbox 4 Low Acceptance Mask        */
+#define CAN_AM04H                      0xFFC02B24      /* Mailbox 4 High Acceptance Mask       */
+#define CAN_AM05L                      0xFFC02B28      /* Mailbox 5 Low Acceptance Mask        */
+#define CAN_AM05H                      0xFFC02B2C      /* Mailbox 5 High Acceptance Mask       */
+#define CAN_AM06L                      0xFFC02B30      /* Mailbox 6 Low Acceptance Mask        */
+#define CAN_AM06H                      0xFFC02B34      /* Mailbox 6 High Acceptance Mask       */
+#define CAN_AM07L                      0xFFC02B38      /* Mailbox 7 Low Acceptance Mask        */
+#define CAN_AM07H                      0xFFC02B3C      /* Mailbox 7 High Acceptance Mask       */
+#define CAN_AM08L                      0xFFC02B40      /* Mailbox 8 Low Acceptance Mask        */
+#define CAN_AM08H                      0xFFC02B44      /* Mailbox 8 High Acceptance Mask       */
+#define CAN_AM09L                      0xFFC02B48      /* Mailbox 9 Low Acceptance Mask        */
+#define CAN_AM09H                      0xFFC02B4C      /* Mailbox 9 High Acceptance Mask       */
+#define CAN_AM10L                      0xFFC02B50      /* Mailbox 10 Low Acceptance Mask       */
+#define CAN_AM10H                      0xFFC02B54      /* Mailbox 10 High Acceptance Mask      */
+#define CAN_AM11L                      0xFFC02B58      /* Mailbox 11 Low Acceptance Mask       */
+#define CAN_AM11H                      0xFFC02B5C      /* Mailbox 11 High Acceptance Mask      */
+#define CAN_AM12L                      0xFFC02B60      /* Mailbox 12 Low Acceptance Mask       */
+#define CAN_AM12H                      0xFFC02B64      /* Mailbox 12 High Acceptance Mask      */
+#define CAN_AM13L                      0xFFC02B68      /* Mailbox 13 Low Acceptance Mask       */
+#define CAN_AM13H                      0xFFC02B6C      /* Mailbox 13 High Acceptance Mask      */
+#define CAN_AM14L                      0xFFC02B70      /* Mailbox 14 Low Acceptance Mask       */
+#define CAN_AM14H                      0xFFC02B74      /* Mailbox 14 High Acceptance Mask      */
+#define CAN_AM15L                      0xFFC02B78      /* Mailbox 15 Low Acceptance Mask       */
+#define CAN_AM15H                      0xFFC02B7C      /* Mailbox 15 High Acceptance Mask      */
+
+#define CAN_AM16L                      0xFFC02B80      /* Mailbox 16 Low Acceptance Mask       */
+#define CAN_AM16H                      0xFFC02B84      /* Mailbox 16 High Acceptance Mask      */
+#define CAN_AM17L                      0xFFC02B88      /* Mailbox 17 Low Acceptance Mask       */
+#define CAN_AM17H                      0xFFC02B8C      /* Mailbox 17 High Acceptance Mask      */
+#define CAN_AM18L                      0xFFC02B90      /* Mailbox 18 Low Acceptance Mask       */
+#define CAN_AM18H                      0xFFC02B94      /* Mailbox 18 High Acceptance Mask      */
+#define CAN_AM19L                      0xFFC02B98      /* Mailbox 19 Low Acceptance Mask       */
+#define CAN_AM19H                      0xFFC02B9C      /* Mailbox 19 High Acceptance Mask      */
+#define CAN_AM20L                      0xFFC02BA0      /* Mailbox 20 Low Acceptance Mask       */
+#define CAN_AM20H                      0xFFC02BA4      /* Mailbox 20 High Acceptance Mask      */
+#define CAN_AM21L                      0xFFC02BA8      /* Mailbox 21 Low Acceptance Mask       */
+#define CAN_AM21H                      0xFFC02BAC      /* Mailbox 21 High Acceptance Mask      */
+#define CAN_AM22L                      0xFFC02BB0      /* Mailbox 22 Low Acceptance Mask       */
+#define CAN_AM22H                      0xFFC02BB4      /* Mailbox 22 High Acceptance Mask      */
+#define CAN_AM23L                      0xFFC02BB8      /* Mailbox 23 Low Acceptance Mask       */
+#define CAN_AM23H                      0xFFC02BBC      /* Mailbox 23 High Acceptance Mask      */
+#define CAN_AM24L                      0xFFC02BC0      /* Mailbox 24 Low Acceptance Mask       */
+#define CAN_AM24H                      0xFFC02BC4      /* Mailbox 24 High Acceptance Mask      */
+#define CAN_AM25L                      0xFFC02BC8      /* Mailbox 25 Low Acceptance Mask       */
+#define CAN_AM25H                      0xFFC02BCC      /* Mailbox 25 High Acceptance Mask      */
+#define CAN_AM26L                      0xFFC02BD0      /* Mailbox 26 Low Acceptance Mask       */
+#define CAN_AM26H                      0xFFC02BD4      /* Mailbox 26 High Acceptance Mask      */
+#define CAN_AM27L                      0xFFC02BD8      /* Mailbox 27 Low Acceptance Mask       */
+#define CAN_AM27H                      0xFFC02BDC      /* Mailbox 27 High Acceptance Mask      */
+#define CAN_AM28L                      0xFFC02BE0      /* Mailbox 28 Low Acceptance Mask       */
+#define CAN_AM28H                      0xFFC02BE4      /* Mailbox 28 High Acceptance Mask      */
+#define CAN_AM29L                      0xFFC02BE8      /* Mailbox 29 Low Acceptance Mask       */
+#define CAN_AM29H                      0xFFC02BEC      /* Mailbox 29 High Acceptance Mask      */
+#define CAN_AM30L                      0xFFC02BF0      /* Mailbox 30 Low Acceptance Mask       */
+#define CAN_AM30H                      0xFFC02BF4      /* Mailbox 30 High Acceptance Mask      */
+#define CAN_AM31L                      0xFFC02BF8      /* Mailbox 31 Low Acceptance Mask       */
+#define CAN_AM31H                      0xFFC02BFC      /* Mailbox 31 High Acceptance Mask      */
+
+/* CAN Acceptance Mask Macros                          */
+#define CAN_AM_L(x)            (CAN_AM00L+((x)*0x8))
+#define CAN_AM_H(x)            (CAN_AM00H+((x)*0x8))
+
+/* Mailbox Registers                                                                                                                           */
+#define CAN_MB00_DATA0         0xFFC02C00      /* Mailbox 0 Data Word 0 [15:0] Register        */
+#define CAN_MB00_DATA1         0xFFC02C04      /* Mailbox 0 Data Word 1 [31:16] Register       */
+#define CAN_MB00_DATA2         0xFFC02C08      /* Mailbox 0 Data Word 2 [47:32] Register       */
+#define CAN_MB00_DATA3         0xFFC02C0C      /* Mailbox 0 Data Word 3 [63:48] Register       */
+#define CAN_MB00_LENGTH                0xFFC02C10      /* Mailbox 0 Data Length Code Register          */
+#define CAN_MB00_TIMESTAMP     0xFFC02C14      /* Mailbox 0 Time Stamp Value Register          */
+#define CAN_MB00_ID0           0xFFC02C18      /* Mailbox 0 Identifier Low Register            */
+#define CAN_MB00_ID1           0xFFC02C1C      /* Mailbox 0 Identifier High Register           */
+
+#define CAN_MB01_DATA0         0xFFC02C20      /* Mailbox 1 Data Word 0 [15:0] Register        */
+#define CAN_MB01_DATA1         0xFFC02C24      /* Mailbox 1 Data Word 1 [31:16] Register       */
+#define CAN_MB01_DATA2         0xFFC02C28      /* Mailbox 1 Data Word 2 [47:32] Register       */
+#define CAN_MB01_DATA3         0xFFC02C2C      /* Mailbox 1 Data Word 3 [63:48] Register       */
+#define CAN_MB01_LENGTH                0xFFC02C30      /* Mailbox 1 Data Length Code Register          */
+#define CAN_MB01_TIMESTAMP     0xFFC02C34      /* Mailbox 1 Time Stamp Value Register          */
+#define CAN_MB01_ID0           0xFFC02C38      /* Mailbox 1 Identifier Low Register            */
+#define CAN_MB01_ID1           0xFFC02C3C      /* Mailbox 1 Identifier High Register           */
+
+#define CAN_MB02_DATA0         0xFFC02C40      /* Mailbox 2 Data Word 0 [15:0] Register        */
+#define CAN_MB02_DATA1         0xFFC02C44      /* Mailbox 2 Data Word 1 [31:16] Register       */
+#define CAN_MB02_DATA2         0xFFC02C48      /* Mailbox 2 Data Word 2 [47:32] Register       */
+#define CAN_MB02_DATA3         0xFFC02C4C      /* Mailbox 2 Data Word 3 [63:48] Register       */
+#define CAN_MB02_LENGTH                0xFFC02C50      /* Mailbox 2 Data Length Code Register          */
+#define CAN_MB02_TIMESTAMP     0xFFC02C54      /* Mailbox 2 Time Stamp Value Register          */
+#define CAN_MB02_ID0           0xFFC02C58      /* Mailbox 2 Identifier Low Register            */
+#define CAN_MB02_ID1           0xFFC02C5C      /* Mailbox 2 Identifier High Register           */
+
+#define CAN_MB03_DATA0         0xFFC02C60      /* Mailbox 3 Data Word 0 [15:0] Register        */
+#define CAN_MB03_DATA1         0xFFC02C64      /* Mailbox 3 Data Word 1 [31:16] Register       */
+#define CAN_MB03_DATA2         0xFFC02C68      /* Mailbox 3 Data Word 2 [47:32] Register       */
+#define CAN_MB03_DATA3         0xFFC02C6C      /* Mailbox 3 Data Word 3 [63:48] Register       */
+#define CAN_MB03_LENGTH                0xFFC02C70      /* Mailbox 3 Data Length Code Register          */
+#define CAN_MB03_TIMESTAMP     0xFFC02C74      /* Mailbox 3 Time Stamp Value Register          */
+#define CAN_MB03_ID0           0xFFC02C78      /* Mailbox 3 Identifier Low Register            */
+#define CAN_MB03_ID1           0xFFC02C7C      /* Mailbox 3 Identifier High Register           */
+
+#define CAN_MB04_DATA0         0xFFC02C80      /* Mailbox 4 Data Word 0 [15:0] Register        */
+#define CAN_MB04_DATA1         0xFFC02C84      /* Mailbox 4 Data Word 1 [31:16] Register       */
+#define CAN_MB04_DATA2         0xFFC02C88      /* Mailbox 4 Data Word 2 [47:32] Register       */
+#define CAN_MB04_DATA3         0xFFC02C8C      /* Mailbox 4 Data Word 3 [63:48] Register       */
+#define CAN_MB04_LENGTH                0xFFC02C90      /* Mailbox 4 Data Length Code Register          */
+#define CAN_MB04_TIMESTAMP     0xFFC02C94      /* Mailbox 4 Time Stamp Value Register          */
+#define CAN_MB04_ID0           0xFFC02C98      /* Mailbox 4 Identifier Low Register            */
+#define CAN_MB04_ID1           0xFFC02C9C      /* Mailbox 4 Identifier High Register           */
+
+#define CAN_MB05_DATA0         0xFFC02CA0      /* Mailbox 5 Data Word 0 [15:0] Register        */
+#define CAN_MB05_DATA1         0xFFC02CA4      /* Mailbox 5 Data Word 1 [31:16] Register       */
+#define CAN_MB05_DATA2         0xFFC02CA8      /* Mailbox 5 Data Word 2 [47:32] Register       */
+#define CAN_MB05_DATA3         0xFFC02CAC      /* Mailbox 5 Data Word 3 [63:48] Register       */
+#define CAN_MB05_LENGTH                0xFFC02CB0      /* Mailbox 5 Data Length Code Register          */
+#define CAN_MB05_TIMESTAMP     0xFFC02CB4      /* Mailbox 5 Time Stamp Value Register          */
+#define CAN_MB05_ID0           0xFFC02CB8      /* Mailbox 5 Identifier Low Register            */
+#define CAN_MB05_ID1           0xFFC02CBC      /* Mailbox 5 Identifier High Register           */
+
+#define CAN_MB06_DATA0         0xFFC02CC0      /* Mailbox 6 Data Word 0 [15:0] Register        */
+#define CAN_MB06_DATA1         0xFFC02CC4      /* Mailbox 6 Data Word 1 [31:16] Register       */
+#define CAN_MB06_DATA2         0xFFC02CC8      /* Mailbox 6 Data Word 2 [47:32] Register       */
+#define CAN_MB06_DATA3         0xFFC02CCC      /* Mailbox 6 Data Word 3 [63:48] Register       */
+#define CAN_MB06_LENGTH                0xFFC02CD0      /* Mailbox 6 Data Length Code Register          */
+#define CAN_MB06_TIMESTAMP     0xFFC02CD4      /* Mailbox 6 Time Stamp Value Register          */
+#define CAN_MB06_ID0           0xFFC02CD8      /* Mailbox 6 Identifier Low Register            */
+#define CAN_MB06_ID1           0xFFC02CDC      /* Mailbox 6 Identifier High Register           */
+
+#define CAN_MB07_DATA0         0xFFC02CE0      /* Mailbox 7 Data Word 0 [15:0] Register        */
+#define CAN_MB07_DATA1         0xFFC02CE4      /* Mailbox 7 Data Word 1 [31:16] Register       */
+#define CAN_MB07_DATA2         0xFFC02CE8      /* Mailbox 7 Data Word 2 [47:32] Register       */
+#define CAN_MB07_DATA3         0xFFC02CEC      /* Mailbox 7 Data Word 3 [63:48] Register       */
+#define CAN_MB07_LENGTH                0xFFC02CF0      /* Mailbox 7 Data Length Code Register          */
+#define CAN_MB07_TIMESTAMP     0xFFC02CF4      /* Mailbox 7 Time Stamp Value Register          */
+#define CAN_MB07_ID0           0xFFC02CF8      /* Mailbox 7 Identifier Low Register            */
+#define CAN_MB07_ID1           0xFFC02CFC      /* Mailbox 7 Identifier High Register           */
+
+#define CAN_MB08_DATA0         0xFFC02D00      /* Mailbox 8 Data Word 0 [15:0] Register        */
+#define CAN_MB08_DATA1         0xFFC02D04      /* Mailbox 8 Data Word 1 [31:16] Register       */
+#define CAN_MB08_DATA2         0xFFC02D08      /* Mailbox 8 Data Word 2 [47:32] Register       */
+#define CAN_MB08_DATA3         0xFFC02D0C      /* Mailbox 8 Data Word 3 [63:48] Register       */
+#define CAN_MB08_LENGTH                0xFFC02D10      /* Mailbox 8 Data Length Code Register          */
+#define CAN_MB08_TIMESTAMP     0xFFC02D14      /* Mailbox 8 Time Stamp Value Register          */
+#define CAN_MB08_ID0           0xFFC02D18      /* Mailbox 8 Identifier Low Register            */
+#define CAN_MB08_ID1           0xFFC02D1C      /* Mailbox 8 Identifier High Register           */
+
+#define CAN_MB09_DATA0         0xFFC02D20      /* Mailbox 9 Data Word 0 [15:0] Register        */
+#define CAN_MB09_DATA1         0xFFC02D24      /* Mailbox 9 Data Word 1 [31:16] Register       */
+#define CAN_MB09_DATA2         0xFFC02D28      /* Mailbox 9 Data Word 2 [47:32] Register       */
+#define CAN_MB09_DATA3         0xFFC02D2C      /* Mailbox 9 Data Word 3 [63:48] Register       */
+#define CAN_MB09_LENGTH                0xFFC02D30      /* Mailbox 9 Data Length Code Register          */
+#define CAN_MB09_TIMESTAMP     0xFFC02D34      /* Mailbox 9 Time Stamp Value Register          */
+#define CAN_MB09_ID0           0xFFC02D38      /* Mailbox 9 Identifier Low Register            */
+#define CAN_MB09_ID1           0xFFC02D3C      /* Mailbox 9 Identifier High Register           */
+
+#define CAN_MB10_DATA0         0xFFC02D40      /* Mailbox 10 Data Word 0 [15:0] Register       */
+#define CAN_MB10_DATA1         0xFFC02D44      /* Mailbox 10 Data Word 1 [31:16] Register      */
+#define CAN_MB10_DATA2         0xFFC02D48      /* Mailbox 10 Data Word 2 [47:32] Register      */
+#define CAN_MB10_DATA3         0xFFC02D4C      /* Mailbox 10 Data Word 3 [63:48] Register      */
+#define CAN_MB10_LENGTH                0xFFC02D50      /* Mailbox 10 Data Length Code Register         */
+#define CAN_MB10_TIMESTAMP     0xFFC02D54      /* Mailbox 10 Time Stamp Value Register         */
+#define CAN_MB10_ID0           0xFFC02D58      /* Mailbox 10 Identifier Low Register           */
+#define CAN_MB10_ID1           0xFFC02D5C      /* Mailbox 10 Identifier High Register          */
+
+#define CAN_MB11_DATA0         0xFFC02D60      /* Mailbox 11 Data Word 0 [15:0] Register       */
+#define CAN_MB11_DATA1         0xFFC02D64      /* Mailbox 11 Data Word 1 [31:16] Register      */
+#define CAN_MB11_DATA2         0xFFC02D68      /* Mailbox 11 Data Word 2 [47:32] Register      */
+#define CAN_MB11_DATA3         0xFFC02D6C      /* Mailbox 11 Data Word 3 [63:48] Register      */
+#define CAN_MB11_LENGTH                0xFFC02D70      /* Mailbox 11 Data Length Code Register         */
+#define CAN_MB11_TIMESTAMP     0xFFC02D74      /* Mailbox 11 Time Stamp Value Register         */
+#define CAN_MB11_ID0           0xFFC02D78      /* Mailbox 11 Identifier Low Register           */
+#define CAN_MB11_ID1           0xFFC02D7C      /* Mailbox 11 Identifier High Register          */
+
+#define CAN_MB12_DATA0         0xFFC02D80      /* Mailbox 12 Data Word 0 [15:0] Register       */
+#define CAN_MB12_DATA1         0xFFC02D84      /* Mailbox 12 Data Word 1 [31:16] Register      */
+#define CAN_MB12_DATA2         0xFFC02D88      /* Mailbox 12 Data Word 2 [47:32] Register      */
+#define CAN_MB12_DATA3         0xFFC02D8C      /* Mailbox 12 Data Word 3 [63:48] Register      */
+#define CAN_MB12_LENGTH                0xFFC02D90      /* Mailbox 12 Data Length Code Register         */
+#define CAN_MB12_TIMESTAMP     0xFFC02D94      /* Mailbox 12 Time Stamp Value Register         */
+#define CAN_MB12_ID0           0xFFC02D98      /* Mailbox 12 Identifier Low Register           */
+#define CAN_MB12_ID1           0xFFC02D9C      /* Mailbox 12 Identifier High Register          */
+
+#define CAN_MB13_DATA0         0xFFC02DA0      /* Mailbox 13 Data Word 0 [15:0] Register       */
+#define CAN_MB13_DATA1         0xFFC02DA4      /* Mailbox 13 Data Word 1 [31:16] Register      */
+#define CAN_MB13_DATA2         0xFFC02DA8      /* Mailbox 13 Data Word 2 [47:32] Register      */
+#define CAN_MB13_DATA3         0xFFC02DAC      /* Mailbox 13 Data Word 3 [63:48] Register      */
+#define CAN_MB13_LENGTH                0xFFC02DB0      /* Mailbox 13 Data Length Code Register         */
+#define CAN_MB13_TIMESTAMP     0xFFC02DB4      /* Mailbox 13 Time Stamp Value Register         */
+#define CAN_MB13_ID0           0xFFC02DB8      /* Mailbox 13 Identifier Low Register           */
+#define CAN_MB13_ID1           0xFFC02DBC      /* Mailbox 13 Identifier High Register          */
+
+#define CAN_MB14_DATA0         0xFFC02DC0      /* Mailbox 14 Data Word 0 [15:0] Register       */
+#define CAN_MB14_DATA1         0xFFC02DC4      /* Mailbox 14 Data Word 1 [31:16] Register      */
+#define CAN_MB14_DATA2         0xFFC02DC8      /* Mailbox 14 Data Word 2 [47:32] Register      */
+#define CAN_MB14_DATA3         0xFFC02DCC      /* Mailbox 14 Data Word 3 [63:48] Register      */
+#define CAN_MB14_LENGTH                0xFFC02DD0      /* Mailbox 14 Data Length Code Register         */
+#define CAN_MB14_TIMESTAMP     0xFFC02DD4      /* Mailbox 14 Time Stamp Value Register         */
+#define CAN_MB14_ID0           0xFFC02DD8      /* Mailbox 14 Identifier Low Register           */
+#define CAN_MB14_ID1           0xFFC02DDC      /* Mailbox 14 Identifier High Register          */
+
+#define CAN_MB15_DATA0         0xFFC02DE0      /* Mailbox 15 Data Word 0 [15:0] Register       */
+#define CAN_MB15_DATA1         0xFFC02DE4      /* Mailbox 15 Data Word 1 [31:16] Register      */
+#define CAN_MB15_DATA2         0xFFC02DE8      /* Mailbox 15 Data Word 2 [47:32] Register      */
+#define CAN_MB15_DATA3         0xFFC02DEC      /* Mailbox 15 Data Word 3 [63:48] Register      */
+#define CAN_MB15_LENGTH                0xFFC02DF0      /* Mailbox 15 Data Length Code Register         */
+#define CAN_MB15_TIMESTAMP     0xFFC02DF4      /* Mailbox 15 Time Stamp Value Register         */
+#define CAN_MB15_ID0           0xFFC02DF8      /* Mailbox 15 Identifier Low Register           */
+#define CAN_MB15_ID1           0xFFC02DFC      /* Mailbox 15 Identifier High Register          */
+
+#define CAN_MB16_DATA0         0xFFC02E00      /* Mailbox 16 Data Word 0 [15:0] Register       */
+#define CAN_MB16_DATA1         0xFFC02E04      /* Mailbox 16 Data Word 1 [31:16] Register      */
+#define CAN_MB16_DATA2         0xFFC02E08      /* Mailbox 16 Data Word 2 [47:32] Register      */
+#define CAN_MB16_DATA3         0xFFC02E0C      /* Mailbox 16 Data Word 3 [63:48] Register      */
+#define CAN_MB16_LENGTH                0xFFC02E10      /* Mailbox 16 Data Length Code Register         */
+#define CAN_MB16_TIMESTAMP     0xFFC02E14      /* Mailbox 16 Time Stamp Value Register         */
+#define CAN_MB16_ID0           0xFFC02E18      /* Mailbox 16 Identifier Low Register           */
+#define CAN_MB16_ID1           0xFFC02E1C      /* Mailbox 16 Identifier High Register          */
+
+#define CAN_MB17_DATA0         0xFFC02E20      /* Mailbox 17 Data Word 0 [15:0] Register       */
+#define CAN_MB17_DATA1         0xFFC02E24      /* Mailbox 17 Data Word 1 [31:16] Register      */
+#define CAN_MB17_DATA2         0xFFC02E28      /* Mailbox 17 Data Word 2 [47:32] Register      */
+#define CAN_MB17_DATA3         0xFFC02E2C      /* Mailbox 17 Data Word 3 [63:48] Register      */
+#define CAN_MB17_LENGTH                0xFFC02E30      /* Mailbox 17 Data Length Code Register         */
+#define CAN_MB17_TIMESTAMP     0xFFC02E34      /* Mailbox 17 Time Stamp Value Register         */
+#define CAN_MB17_ID0           0xFFC02E38      /* Mailbox 17 Identifier Low Register           */
+#define CAN_MB17_ID1           0xFFC02E3C      /* Mailbox 17 Identifier High Register          */
+
+#define CAN_MB18_DATA0         0xFFC02E40      /* Mailbox 18 Data Word 0 [15:0] Register       */
+#define CAN_MB18_DATA1         0xFFC02E44      /* Mailbox 18 Data Word 1 [31:16] Register      */
+#define CAN_MB18_DATA2         0xFFC02E48      /* Mailbox 18 Data Word 2 [47:32] Register      */
+#define CAN_MB18_DATA3         0xFFC02E4C      /* Mailbox 18 Data Word 3 [63:48] Register      */
+#define CAN_MB18_LENGTH                0xFFC02E50      /* Mailbox 18 Data Length Code Register         */
+#define CAN_MB18_TIMESTAMP     0xFFC02E54      /* Mailbox 18 Time Stamp Value Register         */
+#define CAN_MB18_ID0           0xFFC02E58      /* Mailbox 18 Identifier Low Register           */
+#define CAN_MB18_ID1           0xFFC02E5C      /* Mailbox 18 Identifier High Register          */
+
+#define CAN_MB19_DATA0         0xFFC02E60      /* Mailbox 19 Data Word 0 [15:0] Register       */
+#define CAN_MB19_DATA1         0xFFC02E64      /* Mailbox 19 Data Word 1 [31:16] Register      */
+#define CAN_MB19_DATA2         0xFFC02E68      /* Mailbox 19 Data Word 2 [47:32] Register      */
+#define CAN_MB19_DATA3         0xFFC02E6C      /* Mailbox 19 Data Word 3 [63:48] Register      */
+#define CAN_MB19_LENGTH                0xFFC02E70      /* Mailbox 19 Data Length Code Register         */
+#define CAN_MB19_TIMESTAMP     0xFFC02E74      /* Mailbox 19 Time Stamp Value Register         */
+#define CAN_MB19_ID0           0xFFC02E78      /* Mailbox 19 Identifier Low Register           */
+#define CAN_MB19_ID1           0xFFC02E7C      /* Mailbox 19 Identifier High Register          */
+
+#define CAN_MB20_DATA0         0xFFC02E80      /* Mailbox 20 Data Word 0 [15:0] Register       */
+#define CAN_MB20_DATA1         0xFFC02E84      /* Mailbox 20 Data Word 1 [31:16] Register      */
+#define CAN_MB20_DATA2         0xFFC02E88      /* Mailbox 20 Data Word 2 [47:32] Register      */
+#define CAN_MB20_DATA3         0xFFC02E8C      /* Mailbox 20 Data Word 3 [63:48] Register      */
+#define CAN_MB20_LENGTH                0xFFC02E90      /* Mailbox 20 Data Length Code Register         */
+#define CAN_MB20_TIMESTAMP     0xFFC02E94      /* Mailbox 20 Time Stamp Value Register         */
+#define CAN_MB20_ID0           0xFFC02E98      /* Mailbox 20 Identifier Low Register           */
+#define CAN_MB20_ID1           0xFFC02E9C      /* Mailbox 20 Identifier High Register          */
+
+#define CAN_MB21_DATA0         0xFFC02EA0      /* Mailbox 21 Data Word 0 [15:0] Register       */
+#define CAN_MB21_DATA1         0xFFC02EA4      /* Mailbox 21 Data Word 1 [31:16] Register      */
+#define CAN_MB21_DATA2         0xFFC02EA8      /* Mailbox 21 Data Word 2 [47:32] Register      */
+#define CAN_MB21_DATA3         0xFFC02EAC      /* Mailbox 21 Data Word 3 [63:48] Register      */
+#define CAN_MB21_LENGTH                0xFFC02EB0      /* Mailbox 21 Data Length Code Register         */
+#define CAN_MB21_TIMESTAMP     0xFFC02EB4      /* Mailbox 21 Time Stamp Value Register         */
+#define CAN_MB21_ID0           0xFFC02EB8      /* Mailbox 21 Identifier Low Register           */
+#define CAN_MB21_ID1           0xFFC02EBC      /* Mailbox 21 Identifier High Register          */
+
+#define CAN_MB22_DATA0         0xFFC02EC0      /* Mailbox 22 Data Word 0 [15:0] Register       */
+#define CAN_MB22_DATA1         0xFFC02EC4      /* Mailbox 22 Data Word 1 [31:16] Register      */
+#define CAN_MB22_DATA2         0xFFC02EC8      /* Mailbox 22 Data Word 2 [47:32] Register      */
+#define CAN_MB22_DATA3         0xFFC02ECC      /* Mailbox 22 Data Word 3 [63:48] Register      */
+#define CAN_MB22_LENGTH                0xFFC02ED0      /* Mailbox 22 Data Length Code Register         */
+#define CAN_MB22_TIMESTAMP     0xFFC02ED4      /* Mailbox 22 Time Stamp Value Register         */
+#define CAN_MB22_ID0           0xFFC02ED8      /* Mailbox 22 Identifier Low Register           */
+#define CAN_MB22_ID1           0xFFC02EDC      /* Mailbox 22 Identifier High Register          */
+
+#define CAN_MB23_DATA0         0xFFC02EE0      /* Mailbox 23 Data Word 0 [15:0] Register       */
+#define CAN_MB23_DATA1         0xFFC02EE4      /* Mailbox 23 Data Word 1 [31:16] Register      */
+#define CAN_MB23_DATA2         0xFFC02EE8      /* Mailbox 23 Data Word 2 [47:32] Register      */
+#define CAN_MB23_DATA3         0xFFC02EEC      /* Mailbox 23 Data Word 3 [63:48] Register      */
+#define CAN_MB23_LENGTH                0xFFC02EF0      /* Mailbox 23 Data Length Code Register         */
+#define CAN_MB23_TIMESTAMP     0xFFC02EF4      /* Mailbox 23 Time Stamp Value Register         */
+#define CAN_MB23_ID0           0xFFC02EF8      /* Mailbox 23 Identifier Low Register           */
+#define CAN_MB23_ID1           0xFFC02EFC      /* Mailbox 23 Identifier High Register          */
+
+#define CAN_MB24_DATA0         0xFFC02F00      /* Mailbox 24 Data Word 0 [15:0] Register       */
+#define CAN_MB24_DATA1         0xFFC02F04      /* Mailbox 24 Data Word 1 [31:16] Register      */
+#define CAN_MB24_DATA2         0xFFC02F08      /* Mailbox 24 Data Word 2 [47:32] Register      */
+#define CAN_MB24_DATA3         0xFFC02F0C      /* Mailbox 24 Data Word 3 [63:48] Register      */
+#define CAN_MB24_LENGTH                0xFFC02F10      /* Mailbox 24 Data Length Code Register         */
+#define CAN_MB24_TIMESTAMP     0xFFC02F14      /* Mailbox 24 Time Stamp Value Register         */
+#define CAN_MB24_ID0           0xFFC02F18      /* Mailbox 24 Identifier Low Register           */
+#define CAN_MB24_ID1           0xFFC02F1C      /* Mailbox 24 Identifier High Register          */
+
+#define CAN_MB25_DATA0         0xFFC02F20      /* Mailbox 25 Data Word 0 [15:0] Register       */
+#define CAN_MB25_DATA1         0xFFC02F24      /* Mailbox 25 Data Word 1 [31:16] Register      */
+#define CAN_MB25_DATA2         0xFFC02F28      /* Mailbox 25 Data Word 2 [47:32] Register      */
+#define CAN_MB25_DATA3         0xFFC02F2C      /* Mailbox 25 Data Word 3 [63:48] Register      */
+#define CAN_MB25_LENGTH                0xFFC02F30      /* Mailbox 25 Data Length Code Register         */
+#define CAN_MB25_TIMESTAMP     0xFFC02F34      /* Mailbox 25 Time Stamp Value Register         */
+#define CAN_MB25_ID0           0xFFC02F38      /* Mailbox 25 Identifier Low Register           */
+#define CAN_MB25_ID1           0xFFC02F3C      /* Mailbox 25 Identifier High Register          */
+
+#define CAN_MB26_DATA0         0xFFC02F40      /* Mailbox 26 Data Word 0 [15:0] Register       */
+#define CAN_MB26_DATA1         0xFFC02F44      /* Mailbox 26 Data Word 1 [31:16] Register      */
+#define CAN_MB26_DATA2         0xFFC02F48      /* Mailbox 26 Data Word 2 [47:32] Register      */
+#define CAN_MB26_DATA3         0xFFC02F4C      /* Mailbox 26 Data Word 3 [63:48] Register      */
+#define CAN_MB26_LENGTH                0xFFC02F50      /* Mailbox 26 Data Length Code Register         */
+#define CAN_MB26_TIMESTAMP     0xFFC02F54      /* Mailbox 26 Time Stamp Value Register         */
+#define CAN_MB26_ID0           0xFFC02F58      /* Mailbox 26 Identifier Low Register           */
+#define CAN_MB26_ID1           0xFFC02F5C      /* Mailbox 26 Identifier High Register          */
+
+#define CAN_MB27_DATA0         0xFFC02F60      /* Mailbox 27 Data Word 0 [15:0] Register       */
+#define CAN_MB27_DATA1         0xFFC02F64      /* Mailbox 27 Data Word 1 [31:16] Register      */
+#define CAN_MB27_DATA2         0xFFC02F68      /* Mailbox 27 Data Word 2 [47:32] Register      */
+#define CAN_MB27_DATA3         0xFFC02F6C      /* Mailbox 27 Data Word 3 [63:48] Register      */
+#define CAN_MB27_LENGTH                0xFFC02F70      /* Mailbox 27 Data Length Code Register         */
+#define CAN_MB27_TIMESTAMP     0xFFC02F74      /* Mailbox 27 Time Stamp Value Register         */
+#define CAN_MB27_ID0           0xFFC02F78      /* Mailbox 27 Identifier Low Register           */
+#define CAN_MB27_ID1           0xFFC02F7C      /* Mailbox 27 Identifier High Register          */
+
+#define CAN_MB28_DATA0         0xFFC02F80      /* Mailbox 28 Data Word 0 [15:0] Register       */
+#define CAN_MB28_DATA1         0xFFC02F84      /* Mailbox 28 Data Word 1 [31:16] Register      */
+#define CAN_MB28_DATA2         0xFFC02F88      /* Mailbox 28 Data Word 2 [47:32] Register      */
+#define CAN_MB28_DATA3         0xFFC02F8C      /* Mailbox 28 Data Word 3 [63:48] Register      */
+#define CAN_MB28_LENGTH                0xFFC02F90      /* Mailbox 28 Data Length Code Register         */
+#define CAN_MB28_TIMESTAMP     0xFFC02F94      /* Mailbox 28 Time Stamp Value Register         */
+#define CAN_MB28_ID0           0xFFC02F98      /* Mailbox 28 Identifier Low Register           */
+#define CAN_MB28_ID1           0xFFC02F9C      /* Mailbox 28 Identifier High Register          */
+
+#define CAN_MB29_DATA0         0xFFC02FA0      /* Mailbox 29 Data Word 0 [15:0] Register       */
+#define CAN_MB29_DATA1         0xFFC02FA4      /* Mailbox 29 Data Word 1 [31:16] Register      */
+#define CAN_MB29_DATA2         0xFFC02FA8      /* Mailbox 29 Data Word 2 [47:32] Register      */
+#define CAN_MB29_DATA3         0xFFC02FAC      /* Mailbox 29 Data Word 3 [63:48] Register      */
+#define CAN_MB29_LENGTH                0xFFC02FB0      /* Mailbox 29 Data Length Code Register         */
+#define CAN_MB29_TIMESTAMP     0xFFC02FB4      /* Mailbox 29 Time Stamp Value Register         */
+#define CAN_MB29_ID0           0xFFC02FB8      /* Mailbox 29 Identifier Low Register           */
+#define CAN_MB29_ID1           0xFFC02FBC      /* Mailbox 29 Identifier High Register          */
+
+#define CAN_MB30_DATA0         0xFFC02FC0      /* Mailbox 30 Data Word 0 [15:0] Register       */
+#define CAN_MB30_DATA1         0xFFC02FC4      /* Mailbox 30 Data Word 1 [31:16] Register      */
+#define CAN_MB30_DATA2         0xFFC02FC8      /* Mailbox 30 Data Word 2 [47:32] Register      */
+#define CAN_MB30_DATA3         0xFFC02FCC      /* Mailbox 30 Data Word 3 [63:48] Register      */
+#define CAN_MB30_LENGTH                0xFFC02FD0      /* Mailbox 30 Data Length Code Register         */
+#define CAN_MB30_TIMESTAMP     0xFFC02FD4      /* Mailbox 30 Time Stamp Value Register         */
+#define CAN_MB30_ID0           0xFFC02FD8      /* Mailbox 30 Identifier Low Register           */
+#define CAN_MB30_ID1           0xFFC02FDC      /* Mailbox 30 Identifier High Register          */
+
+#define CAN_MB31_DATA0         0xFFC02FE0      /* Mailbox 31 Data Word 0 [15:0] Register       */
+#define CAN_MB31_DATA1         0xFFC02FE4      /* Mailbox 31 Data Word 1 [31:16] Register      */
+#define CAN_MB31_DATA2         0xFFC02FE8      /* Mailbox 31 Data Word 2 [47:32] Register      */
+#define CAN_MB31_DATA3         0xFFC02FEC      /* Mailbox 31 Data Word 3 [63:48] Register      */
+#define CAN_MB31_LENGTH                0xFFC02FF0      /* Mailbox 31 Data Length Code Register         */
+#define CAN_MB31_TIMESTAMP     0xFFC02FF4      /* Mailbox 31 Time Stamp Value Register         */
+#define CAN_MB31_ID0           0xFFC02FF8      /* Mailbox 31 Identifier Low Register           */
+#define CAN_MB31_ID1           0xFFC02FFC      /* Mailbox 31 Identifier High Register          */
+
+/* CAN Mailbox Area Macros                             */
+#define CAN_MB_ID1(x)          (CAN_MB00_ID1+((x)*0x20))
+#define CAN_MB_ID0(x)          (CAN_MB00_ID0+((x)*0x20))
+#define CAN_MB_TIMESTAMP(x)    (CAN_MB00_TIMESTAMP+((x)*0x20))
+#define CAN_MB_LENGTH(x)       (CAN_MB00_LENGTH+((x)*0x20))
+#define CAN_MB_DATA3(x)                (CAN_MB00_DATA3+((x)*0x20))
+#define CAN_MB_DATA2(x)                (CAN_MB00_DATA2+((x)*0x20))
+#define CAN_MB_DATA1(x)                (CAN_MB00_DATA1+((x)*0x20))
+#define CAN_MB_DATA0(x)                (CAN_MB00_DATA0+((x)*0x20))
+
+/* Pin Control Registers       (0xFFC03200 - 0xFFC032FF)                                                                                       */
+#define PORTF_FER                      0xFFC03200      /* Port F Function Enable Register (Alternate/Flag*)    */
+#define PORTG_FER                      0xFFC03204      /* Port G Function Enable Register (Alternate/Flag*)    */
+#define PORTH_FER                      0xFFC03208      /* Port H Function Enable Register (Alternate/Flag*)    */
+#define BFIN_PORT_MUX                  0xFFC0320C      /* Port Multiplexer Control Register                                    */
+
+/* Handshake MDMA Registers    (0xFFC03300 - 0xFFC033FF)                                                                               */
+#define HMDMA0_CONTROL         0xFFC03300      /* Handshake MDMA0 Control Register                                     */
+#define HMDMA0_ECINIT          0xFFC03304      /* HMDMA0 Initial Edge Count Register                           */
+#define HMDMA0_BCINIT          0xFFC03308      /* HMDMA0 Initial Block Count Register                          */
+#define HMDMA0_ECURGENT                0xFFC0330C      /* HMDMA0 Urgent Edge Count Threshhold Register         */
+#define HMDMA0_ECOVERFLOW      0xFFC03310      /* HMDMA0 Edge Count Overflow Interrupt Register        */
+#define HMDMA0_ECOUNT          0xFFC03314      /* HMDMA0 Current Edge Count Register                           */
+#define HMDMA0_BCOUNT          0xFFC03318      /* HMDMA0 Current Block Count Register                          */
+
+#define HMDMA1_CONTROL         0xFFC03340      /* Handshake MDMA1 Control Register                                     */
+#define HMDMA1_ECINIT          0xFFC03344      /* HMDMA1 Initial Edge Count Register                           */
+#define HMDMA1_BCINIT          0xFFC03348      /* HMDMA1 Initial Block Count Register                          */
+#define HMDMA1_ECURGENT                0xFFC0334C      /* HMDMA1 Urgent Edge Count Threshhold Register         */
+#define HMDMA1_ECOVERFLOW      0xFFC03350      /* HMDMA1 Edge Count Overflow Interrupt Register        */
+#define HMDMA1_ECOUNT          0xFFC03354      /* HMDMA1 Current Edge Count Register                           */
+#define HMDMA1_BCOUNT          0xFFC03358      /* HMDMA1 Current Block Count Register                          */
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer: All macros are intended to make C and Assembly code more readable.
+**                             Use these macros carefully, as any that do left shifts for field
+**                             depositing will result in the lower order bits being destroyed.  Any
+**                             macro that shifts left to properly position the bit-field should be
+**                             used as part of an OR to initialize a register and NOT as a dynamic
+**                             modifier UNLESS the lower order bits are saved and ORed back in when
+**                             the macro is used.
+*************************************************************************************/
+/*
+** ********************* PLL AND RESET MASKS ****************************************/
+/* PLL_CTL Masks                                                                                                                                       */
+#define DF                             0x0001  /* 0: PLL = CLKIN, 1: PLL = CLKIN/2                                     */
+#define PLL_OFF                        0x0002  /* PLL Not Powered                                                                      */
+#define STOPCK                 0x0008  /* Core Clock Off                                                                       */
+#define PDWN                   0x0020  /* Enter Deep Sleep Mode                                                        */
+#define        IN_DELAY                0x0040  /* Add 200ps Delay To EBIU Input Latches                        */
+#define        OUT_DELAY               0x0080  /* Add 200ps Delay To EBIU Output Signals                       */
+#define BYPASS                 0x0100  /* Bypass the PLL                                                                       */
+#define        MSEL                    0x7E00  /* Multiplier Select For CCLK/VCO Factors                       */
+/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)                      */
+#define        SET_MSEL(x)             (((x)&0x3F) << 0x9)     /* Set MSEL = 0-63 --> VCO = CLKIN*MSEL         */
+
+/* PLL_DIV Masks                                                                                                               */
+#define SSEL                   0x000F  /* System Select                                                */
+#define        CSEL                    0x0030  /* Core Select                                                  */
+#define CSEL_DIV1              0x0000  /*              CCLK = VCO / 1                                  */
+#define CSEL_DIV2              0x0010  /*              CCLK = VCO / 2                                  */
+#define        CSEL_DIV4               0x0020  /*              CCLK = VCO / 4                                  */
+#define        CSEL_DIV8               0x0030  /*              CCLK = VCO / 8                                  */
+/* PLL_DIV Macros                                                                                                              */
+#define SET_SSEL(x)            ((x)&0xF)       /* Set SSEL = 0-15 --> SCLK = VCO/SSEL  */
+
+/* VR_CTL Masks                                                                                                                                        */
+#define        FREQ                    0x0003  /* Switching Oscillator Frequency For Regulator */
+#define        HIBERNATE               0x0000  /*              Powerdown/Bypass On-Board Regulation    */
+#define        FREQ_333                0x0001  /*              Switching Frequency Is 333 kHz                  */
+#define        FREQ_667                0x0002  /*              Switching Frequency Is 667 kHz                  */
+#define        FREQ_1000               0x0003  /*              Switching Frequency Is 1 MHz                    */
+
+#define GAIN                   0x000C  /* Voltage Level Gain   */
+#define        GAIN_5                  0x0000  /*              GAIN = 5                */
+#define        GAIN_10                 0x0004  /*              GAIN = 10               */
+#define        GAIN_20                 0x0008  /*              GAIN = 20               */
+#define        GAIN_50                 0x000C  /*              GAIN = 50               */
+
+#define        VLEV                    0x00F0  /* Internal Voltage Level                                       */
+#define        VLEV_085                0x0060  /*              VLEV = 0.85 V (-5% - +10% Accuracy)     */
+#define        VLEV_090                0x0070  /*              VLEV = 0.90 V (-5% - +10% Accuracy)     */
+#define        VLEV_095                0x0080  /*              VLEV = 0.95 V (-5% - +10% Accuracy)     */
+#define        VLEV_100                0x0090  /*              VLEV = 1.00 V (-5% - +10% Accuracy)     */
+#define        VLEV_105                0x00A0  /*              VLEV = 1.05 V (-5% - +10% Accuracy)     */
+#define        VLEV_110                0x00B0  /*              VLEV = 1.10 V (-5% - +10% Accuracy)     */
+#define        VLEV_115                0x00C0  /*              VLEV = 1.15 V (-5% - +10% Accuracy)     */
+#define        VLEV_120                0x00D0  /*              VLEV = 1.20 V (-5% - +10% Accuracy)     */
+#define        VLEV_125                0x00E0  /*              VLEV = 1.25 V (-5% - +10% Accuracy)     */
+#define        VLEV_130                0x00F0  /*              VLEV = 1.30 V (-5% - +10% Accuracy)     */
+
+#define        WAKE                    0x0100  /* Enable RTC/Reset Wakeup From Hibernate       */
+#define PHYWE                  0x0200  /* Enable PHY Wakeup From Hibernate                     */
+#define        CANWE                   0x0400  /* Enable CAN Wakeup From Hibernate                     */
+#define        PHYCLKOE                0x4000  /* PHY Clock Output Enable                                      */
+#define        CKELOW                  0x8000  /* Enable Drive CKE Low During Reset            */
+
+/* PLL_STAT Masks                                                                                                                                      */
+#define ACTIVE_PLLENABLED      0x0001  /* Processor In Active Mode With PLL Enabled    */
+#define        FULL_ON                         0x0002  /* Processor In Full On Mode                                    */
+#define ACTIVE_PLLDISABLED     0x0004  /* Processor In Active Mode With PLL Disabled   */
+#define        PLL_LOCKED                      0x0020  /* PLL_LOCKCNT Has Been Reached                                 */
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* SWRST Masks                                                                                                                                         */
+#define SYSTEM_RESET           0x0007  /* Initiates A System Software Reset                    */
+#define        DOUBLE_FAULT            0x0008  /* Core Double Fault Causes Reset                               */
+#define RESET_DOUBLE           0x2000  /* SW Reset Generated By Core Double-Fault              */
+#define RESET_WDOG                     0x4000  /* SW Reset Generated By Watchdog Timer                 */
+#define RESET_SOFTWARE         0x8000  /* SW Reset Occurred Since Last Read Of SWRST   */
+
+/* SYSCR Masks                                                                                                                                                         */
+#define BMODE                          0x0006  /* Boot Mode - Latched During HW Reset From Mode Pins   */
+#define        NOBOOT                          0x0010  /* Execute From L1 or ASYNC Bank 0 When BMODE = 0               */
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
+
+/* SIC_IAR0 Macros                                                                                                                     */
+#define P0_IVG(x)              (((x)&0xF)-7)   /* Peripheral #0 assigned IVG #x        */
+#define P1_IVG(x)              (((x)&0xF)-7) << 0x4    /* Peripheral #1 assigned IVG #x        */
+#define P2_IVG(x)              (((x)&0xF)-7) << 0x8    /* Peripheral #2 assigned IVG #x        */
+#define P3_IVG(x)              (((x)&0xF)-7) << 0xC    /* Peripheral #3 assigned IVG #x        */
+#define P4_IVG(x)              (((x)&0xF)-7) << 0x10   /* Peripheral #4 assigned IVG #x        */
+#define P5_IVG(x)              (((x)&0xF)-7) << 0x14   /* Peripheral #5 assigned IVG #x        */
+#define P6_IVG(x)              (((x)&0xF)-7) << 0x18   /* Peripheral #6 assigned IVG #x        */
+#define P7_IVG(x)              (((x)&0xF)-7) << 0x1C   /* Peripheral #7 assigned IVG #x        */
+
+/* SIC_IAR1 Macros                                                                                                                     */
+#define P8_IVG(x)              (((x)&0xF)-7)   /* Peripheral #8 assigned IVG #x        */
+#define P9_IVG(x)              (((x)&0xF)-7) << 0x4    /* Peripheral #9 assigned IVG #x        */
+#define P10_IVG(x)             (((x)&0xF)-7) << 0x8    /* Peripheral #10 assigned IVG #x       */
+#define P11_IVG(x)             (((x)&0xF)-7) << 0xC    /* Peripheral #11 assigned IVG #x       */
+#define P12_IVG(x)             (((x)&0xF)-7) << 0x10   /* Peripheral #12 assigned IVG #x       */
+#define P13_IVG(x)             (((x)&0xF)-7) << 0x14   /* Peripheral #13 assigned IVG #x       */
+#define P14_IVG(x)             (((x)&0xF)-7) << 0x18   /* Peripheral #14 assigned IVG #x       */
+#define P15_IVG(x)             (((x)&0xF)-7) << 0x1C   /* Peripheral #15 assigned IVG #x       */
+
+/* SIC_IAR2 Macros                                                                                                                     */
+#define P16_IVG(x)             (((x)&0xF)-7)   /* Peripheral #16 assigned IVG #x       */
+#define P17_IVG(x)             (((x)&0xF)-7) << 0x4    /* Peripheral #17 assigned IVG #x       */
+#define P18_IVG(x)             (((x)&0xF)-7) << 0x8    /* Peripheral #18 assigned IVG #x       */
+#define P19_IVG(x)             (((x)&0xF)-7) << 0xC    /* Peripheral #19 assigned IVG #x       */
+#define P20_IVG(x)             (((x)&0xF)-7) << 0x10   /* Peripheral #20 assigned IVG #x       */
+#define P21_IVG(x)             (((x)&0xF)-7) << 0x14   /* Peripheral #21 assigned IVG #x       */
+#define P22_IVG(x)             (((x)&0xF)-7) << 0x18   /* Peripheral #22 assigned IVG #x       */
+#define P23_IVG(x)             (((x)&0xF)-7) << 0x1C   /* Peripheral #23 assigned IVG #x       */
+
+/* SIC_IAR3 Macros                                                                                                                     */
+#define P24_IVG(x)             (((x)&0xF)-7)   /* Peripheral #24 assigned IVG #x       */
+#define P25_IVG(x)             (((x)&0xF)-7) << 0x4    /* Peripheral #25 assigned IVG #x       */
+#define P26_IVG(x)             (((x)&0xF)-7) << 0x8    /* Peripheral #26 assigned IVG #x       */
+#define P27_IVG(x)             (((x)&0xF)-7) << 0xC    /* Peripheral #27 assigned IVG #x       */
+#define P28_IVG(x)             (((x)&0xF)-7) << 0x10   /* Peripheral #28 assigned IVG #x       */
+#define P29_IVG(x)             (((x)&0xF)-7) << 0x14   /* Peripheral #29 assigned IVG #x       */
+#define P30_IVG(x)             (((x)&0xF)-7) << 0x18   /* Peripheral #30 assigned IVG #x       */
+#define P31_IVG(x)             (((x)&0xF)-7) << 0x1C   /* Peripheral #31 assigned IVG #x       */
+
+/* SIC_IMASK Masks                                                                                                                                             */
+#define SIC_UNMASK_ALL 0x00000000      /* Unmask all peripheral interrupts     */
+#define SIC_MASK_ALL   0xFFFFFFFF      /* Mask all peripheral interrupts       */
+#define SIC_MASK(x)            (1 << ((x)&0x1F))       /* Mask Peripheral #x interrupt         */
+#define SIC_UNMASK(x)  (0xFFFFFFFF ^ (1 << ((x)&0x1F)))        /* Unmask Peripheral #x interrupt       */
+
+/* SIC_IWR Masks                                                                                                                                               */
+#define IWR_DISABLE_ALL        0x00000000      /* Wakeup Disable all peripherals       */
+#define IWR_ENABLE_ALL 0xFFFFFFFF      /* Wakeup Enable all peripherals        */
+#define IWR_ENABLE(x)  (1 << ((x)&0x1F))       /* Wakeup Enable Peripheral #x          */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << ((x)&0x1F)))        /* Wakeup Disable Peripheral #x         */
+
+/* ***************  WATCHDOG TIMER MASKS  *******************************************/
+/* WDOG_CTL Masks                                                                                                                                      */
+#define WDOG_RESET             0x0000  /* Generate Reset Event                                                 */
+#define WDOG_NMI               0x0002  /* Generate Non-Maskable Interrupt (NMI) Event  */
+#define WDOG_GPI               0x0004  /* Generate General Purpose (GP) Interrupt              */
+#define WDOG_NONE              0x0006  /* Disable Watchdog Timer Interrupts                    */
+#define TMR_EN                 0x0FF0  /* Watchdog Counter Enable                                              */
+#define        TMR_DIS                 0x0AD0  /* Watchdog Counter Disable                                             */
+#define TRO                    0x8000  /* Watchdog Expired                                                     */
+
+/* ************** UART CONTROLLER MASKS *************************/
+/* UARTx_LCR Masks                                                                                             */
+#define WLS(x)         ((((x)&0x3)-5) & 0x03)  /* Word Length Select   */
+#define STB                    0x04    /* Stop Bits                    */
+#define PEN                    0x08    /* Parity Enable                */
+#define EPS                    0x10    /* Even Parity Select   */
+#define STP                    0x20    /* Stick Parity                 */
+#define SB                     0x40    /* Set Break                    */
+#define DLAB           0x80    /* Divisor Latch Access */
+
+/* UARTx_MCR Mask                                                                              */
+#define LOOP           0x10    /* Loopback Mode Enable         */
+
+/* UARTx_LSR Masks                                                                             */
+#define DR                     0x01    /* Data Ready                           */
+#define OE                     0x02    /* Overrun Error                        */
+#define PE                     0x04    /* Parity Error                         */
+#define FE                     0x08    /* Framing Error                        */
+#define BI                     0x10    /* Break Interrupt                      */
+#define THRE           0x20    /* THR Empty                            */
+#define TEMT           0x40    /* TSR and UART_THR Empty       */
+
+/* UARTx_IER Masks                                                                                                                     */
+#define ERBFI          0x01    /* Enable Receive Buffer Full Interrupt         */
+#define ETBEI          0x02    /* Enable Transmit Buffer Empty Interrupt       */
+#define ELSI           0x04    /* Enable RX Status Interrupt                           */
+
+/* UARTx_IIR Masks                                                                                                             */
+#define NINT           0x01    /* Pending Interrupt                                    */
+#define IIR_TX_READY    0x02   /* UART_THR empty                               */
+#define IIR_RX_READY    0x04   /* Receive data ready                           */
+#define IIR_LINE_CHANGE 0x06   /* Receive line status                          */
+#define IIR_STATUS     0x06
+
+/* UARTx_GCTL Masks                                                                                                    */
+#define UCEN           0x01    /* Enable UARTx Clocks                          */
+#define IREN           0x02    /* Enable IrDA Mode                                     */
+#define TPOLC          0x04    /* IrDA TX Polarity Change                      */
+#define RPOLC          0x08    /* IrDA RX Polarity Change                      */
+#define FPE                    0x10    /* Force Parity Error On Transmit       */
+#define FFE                    0x20    /* Force Framing Error On Transmit      */
+
+/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  ****************************/
+/* SPI_CTL Masks                                                                                                                                       */
+#define        TIMOD           0x0003  /* Transfer Initiate Mode                                                       */
+#define RDBR_CORE      0x0000  /*              RDBR Read Initiates, IRQ When RDBR Full         */
+#define        TDBR_CORE       0x0001  /*              TDBR Write Initiates, IRQ When TDBR Empty       */
+#define RDBR_DMA       0x0002  /*              DMA Read, DMA Until FIFO Empty                          */
+#define TDBR_DMA       0x0003  /*              DMA Write, DMA Until FIFO Full                          */
+#define SZ                     0x0004  /* Send Zero (When TDBR Empty, Send Zero/Last*)         */
+#define GM                     0x0008  /* Get More (When RDBR Full, Overwrite/Discard*)        */
+#define PSSE           0x0010  /* Slave-Select Input Enable                                            */
+#define EMISO          0x0020  /* Enable MISO As Output                                                        */
+#define SPI_SIZE       0x0100  /* Size of Words (16/8* Bits)                                           */
+#define LSBF           0x0200  /* LSB First                                                                            */
+#define CPHA           0x0400  /* Clock Phase                                                                          */
+#define CPOL           0x0800  /* Clock Polarity                                                                       */
+#define MSTR           0x1000  /* Master/Slave*                                                                        */
+#define WOM                    0x2000  /* Write Open Drain Master                                                      */
+#define SPE                    0x4000  /* SPI Enable                                                                           */
+
+/* SPI_FLG Masks                                                                                                                                       */
+#define FLS1           0x0002  /* Enables SPI_FLOUT1 as SPI Slave-Select Output        */
+#define FLS2           0x0004  /* Enables SPI_FLOUT2 as SPI Slave-Select Output        */
+#define FLS3           0x0008  /* Enables SPI_FLOUT3 as SPI Slave-Select Output        */
+#define FLS4           0x0010  /* Enables SPI_FLOUT4 as SPI Slave-Select Output        */
+#define FLS5           0x0020  /* Enables SPI_FLOUT5 as SPI Slave-Select Output        */
+#define FLS6           0x0040  /* Enables SPI_FLOUT6 as SPI Slave-Select Output        */
+#define FLS7           0x0080  /* Enables SPI_FLOUT7 as SPI Slave-Select Output        */
+#define FLG1           0xFDFF  /* Activates SPI_FLOUT1                                                         */
+#define FLG2           0xFBFF  /* Activates SPI_FLOUT2                                                         */
+#define FLG3           0xF7FF  /* Activates SPI_FLOUT3                                                         */
+#define FLG4           0xEFFF  /* Activates SPI_FLOUT4                                                         */
+#define FLG5           0xDFFF  /* Activates SPI_FLOUT5                                                         */
+#define FLG6           0xBFFF  /* Activates SPI_FLOUT6                                                         */
+#define FLG7           0x7FFF  /* Activates SPI_FLOUT7                                                         */
+
+/* SPI_STAT Masks                                                                                                                                                              */
+#define SPIF           0x0001  /* SPI Finished (Single-Word Transfer Complete)                                 */
+#define MODF           0x0002  /* Mode Fault Error (Another Device Tried To Become Master)             */
+#define TXE                    0x0004  /* Transmission Error (Data Sent With No New Data In TDBR)              */
+#define TXS                    0x0008  /* SPI_TDBR Data Buffer Status (Full/Empty*)                                    */
+#define RBSY           0x0010  /* Receive Error (Data Received With RDBR Full)                                 */
+#define RXS                    0x0020  /* SPI_RDBR Data Buffer Status (Full/Empty*)                                    */
+#define TXCOL          0x0040  /* Transmit Collision Error (Corrupt Data May Have Been Sent)   */
+
+/*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
+/* TIMER_ENABLE Masks                                                                                                  */
+#define TIMEN0                 0x0001  /* Enable Timer 0                                       */
+#define TIMEN1                 0x0002  /* Enable Timer 1                                       */
+#define TIMEN2                 0x0004  /* Enable Timer 2                                       */
+#define TIMEN3                 0x0008  /* Enable Timer 3                                       */
+#define TIMEN4                 0x0010  /* Enable Timer 4                                       */
+#define TIMEN5                 0x0020  /* Enable Timer 5                                       */
+#define TIMEN6                 0x0040  /* Enable Timer 6                                       */
+#define TIMEN7                 0x0080  /* Enable Timer 7                                       */
+
+/* TIMER_DISABLE Masks                                                                                                 */
+#define TIMDIS0                        TIMEN0  /* Disable Timer 0                                      */
+#define TIMDIS1                        TIMEN1  /* Disable Timer 1                                      */
+#define TIMDIS2                        TIMEN2  /* Disable Timer 2                                      */
+#define TIMDIS3                        TIMEN3  /* Disable Timer 3                                      */
+#define TIMDIS4                        TIMEN4  /* Disable Timer 4                                      */
+#define TIMDIS5                        TIMEN5  /* Disable Timer 5                                      */
+#define TIMDIS6                        TIMEN6  /* Disable Timer 6                                      */
+#define TIMDIS7                        TIMEN7  /* Disable Timer 7                                      */
+
+/* TIMER_STATUS Masks                                                                                                  */
+#define TIMIL0                 0x00000001      /* Timer 0 Interrupt                            */
+#define TIMIL1                 0x00000002      /* Timer 1 Interrupt                            */
+#define TIMIL2                 0x00000004      /* Timer 2 Interrupt                            */
+#define TIMIL3                 0x00000008      /* Timer 3 Interrupt                            */
+#define TOVL_ERR0              0x00000010      /* Timer 0 Counter Overflow                     */
+#define TOVL_ERR1              0x00000020      /* Timer 1 Counter Overflow                     */
+#define TOVL_ERR2              0x00000040      /* Timer 2 Counter Overflow                     */
+#define TOVL_ERR3              0x00000080      /* Timer 3 Counter Overflow                     */
+#define TRUN0                  0x00001000      /* Timer 0 Slave Enable Status          */
+#define TRUN1                  0x00002000      /* Timer 1 Slave Enable Status          */
+#define TRUN2                  0x00004000      /* Timer 2 Slave Enable Status          */
+#define TRUN3                  0x00008000      /* Timer 3 Slave Enable Status          */
+#define TIMIL4                 0x00010000      /* Timer 4 Interrupt                            */
+#define TIMIL5                 0x00020000      /* Timer 5 Interrupt                            */
+#define TIMIL6                 0x00040000      /* Timer 6 Interrupt                            */
+#define TIMIL7                 0x00080000      /* Timer 7 Interrupt                            */
+#define TOVL_ERR4              0x00100000      /* Timer 4 Counter Overflow                     */
+#define TOVL_ERR5              0x00200000      /* Timer 5 Counter Overflow                     */
+#define TOVL_ERR6              0x00400000      /* Timer 6 Counter Overflow                     */
+#define TOVL_ERR7              0x00800000      /* Timer 7 Counter Overflow                     */
+#define TRUN4                  0x10000000      /* Timer 4 Slave Enable Status          */
+#define TRUN5                  0x20000000      /* Timer 5 Slave Enable Status          */
+#define TRUN6                  0x40000000      /* Timer 6 Slave Enable Status          */
+#define TRUN7                  0x80000000      /* Timer 7 Slave Enable Status          */
+
+/* TIMERx_CONFIG Masks                                                                                                 */
+#define PWM_OUT                        0x0001  /* Pulse-Width Modulation Output Mode   */
+#define WDTH_CAP               0x0002  /* Width Capture Input Mode                             */
+#define EXT_CLK                        0x0003  /* External Clock Mode                                  */
+#define PULSE_HI               0x0004  /* Action Pulse (Positive/Negative*)    */
+#define PERIOD_CNT             0x0008  /* Period Count                                                 */
+#define IRQ_ENA                        0x0010  /* Interrupt Request Enable                             */
+#define TIN_SEL                        0x0020  /* Timer Input Select                                   */
+#define OUT_DIS                        0x0040  /* Output Pad Disable                                   */
+#define CLK_SEL                        0x0080  /* Timer Clock Select                                   */
+#define TOGGLE_HI              0x0100  /* PWM_OUT PULSE_HI Toggle Mode                 */
+#define EMU_RUN                        0x0200  /* Emulation Behavior Select                    */
+#define ERR_TYP                        0xC000  /* Error Type                                                   */
+
+/* ******************   GPIO PORTS F, G, H MASKS  ***********************/
+/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks                                */
+/* Port F Masks                                                                                                                */
+#define PF0            0x0001
+#define PF1            0x0002
+#define PF2            0x0004
+#define PF3            0x0008
+#define PF4            0x0010
+#define PF5            0x0020
+#define PF6            0x0040
+#define PF7            0x0080
+#define PF8            0x0100
+#define PF9            0x0200
+#define PF10   0x0400
+#define PF11   0x0800
+#define PF12   0x1000
+#define PF13   0x2000
+#define PF14   0x4000
+#define PF15   0x8000
+
+/* Port G Masks                                                                                                                        */
+#define PG0            0x0001
+#define PG1            0x0002
+#define PG2            0x0004
+#define PG3            0x0008
+#define PG4            0x0010
+#define PG5            0x0020
+#define PG6            0x0040
+#define PG7            0x0080
+#define PG8            0x0100
+#define PG9            0x0200
+#define PG10   0x0400
+#define PG11   0x0800
+#define PG12   0x1000
+#define PG13   0x2000
+#define PG14   0x4000
+#define PG15   0x8000
+
+/* Port H Masks                                                                                                                        */
+#define PH0            0x0001
+#define PH1            0x0002
+#define PH2            0x0004
+#define PH3            0x0008
+#define PH4            0x0010
+#define PH5            0x0020
+#define PH6            0x0040
+#define PH7            0x0080
+#define PH8            0x0100
+#define PH9            0x0200
+#define PH10   0x0400
+#define PH11   0x0800
+#define PH12   0x1000
+#define PH13   0x2000
+#define PH14   0x4000
+#define PH15   0x8000
+
+/* *******************  SERIAL PORT MASKS  **************************************/
+/* SPORTx_TCR1 Masks                                                                                                                   */
+#define TSPEN          0x0001  /* Transmit Enable                                                              */
+#define ITCLK          0x0002  /* Internal Transmit Clock Select                               */
+#define DTYPE_NORM     0x0004  /* Data Format Normal                                                   */
+#define DTYPE_ULAW     0x0008  /* Compand Using u-Law                                                  */
+#define DTYPE_ALAW     0x000C  /* Compand Using A-Law                                                  */
+#define TLSBIT         0x0010  /* Transmit Bit Order                                                   */
+#define ITFS           0x0200  /* Internal Transmit Frame Sync Select                  */
+#define TFSR           0x0400  /* Transmit Frame Sync Required Select                  */
+#define DITFS          0x0800  /* Data-Independent Transmit Frame Sync Select  */
+#define LTFS           0x1000  /* Low Transmit Frame Sync Select                               */
+#define LATFS          0x2000  /* Late Transmit Frame Sync Select                              */
+#define TCKFE          0x4000  /* Clock Falling Edge Select                                    */
+
+/* SPORTx_TCR2 Masks and Macro                                                                                                 */
+#define SLEN(x)                ((x)&0x1F)      /* SPORT TX Word Length (2 - 31)                                */
+#define TXSE           0x0100  /* TX Secondary Enable                                                  */
+#define TSFSE          0x0200  /* Transmit Stereo Frame Sync Enable                    */
+#define TRFST          0x0400  /* Left/Right Order (1 = Right Channel 1st)             */
+
+/* SPORTx_RCR1 Masks                                                                                                                   */
+#define RSPEN          0x0001  /* Receive Enable                                                               */
+#define IRCLK          0x0002  /* Internal Receive Clock Select                                */
+#define DTYPE_NORM     0x0004  /* Data Format Normal                                                   */
+#define DTYPE_ULAW     0x0008  /* Compand Using u-Law                                                  */
+#define DTYPE_ALAW     0x000C  /* Compand Using A-Law                                                  */
+#define RLSBIT         0x0010  /* Receive Bit Order                                                    */
+#define IRFS           0x0200  /* Internal Receive Frame Sync Select                   */
+#define RFSR           0x0400  /* Receive Frame Sync Required Select                   */
+#define LRFS           0x1000  /* Low Receive Frame Sync Select                                */
+#define LARFS          0x2000  /* Late Receive Frame Sync Select                               */
+#define RCKFE          0x4000  /* Clock Falling Edge Select                                    */
+
+/* SPORTx_RCR2 Masks                                                                                                                   */
+#define SLEN(x)                ((x)&0x1F)      /* SPORT RX Word Length (2 - 31)                                */
+#define RXSE           0x0100  /* RX Secondary Enable                                                  */
+#define RSFSE          0x0200  /* RX Stereo Frame Sync Enable                                  */
+#define RRFST          0x0400  /* Right-First Data Order                                               */
+
+/* SPORTx_STAT Masks                                                                                                                   */
+#define RXNE           0x0001  /* Receive FIFO Not Empty Status                                */
+#define RUVF           0x0002  /* Sticky Receive Underflow Status                              */
+#define ROVF           0x0004  /* Sticky Receive Overflow Status                               */
+#define TXF                    0x0008  /* Transmit FIFO Full Status                                    */
+#define TUVF           0x0010  /* Sticky Transmit Underflow Status                             */
+#define TOVF           0x0020  /* Sticky Transmit Overflow Status                              */
+#define TXHRE          0x0040  /* Transmit Hold Register Empty                                 */
+
+/* SPORTx_MCMC1 Macros                                                                                                                 */
+#define SP_WOFF(x)             ((x) & 0x3FF)   /* Multichannel Window Offset Field                     */
+
+/* Only use WSIZE Macro With Logic OR While Setting Lower Order Bits                                           */
+#define SP_WSIZE(x)    (((((x)>>0x3)-1)&0xF) << 0xC)   /* Multichannel Window Size = (x/8)-1   */
+
+/* SPORTx_MCMC2 Masks                                                                                                                  */
+#define REC_BYPASS     0x0000  /* Bypass Mode (No Clock Recovery)                              */
+#define REC_2FROM4     0x0002  /* Recover 2 MHz Clock from 4 MHz Clock                 */
+#define REC_8FROM16    0x0003  /* Recover 8 MHz Clock from 16 MHz Clock                */
+#define MCDTXPE                0x0004  /* Multichannel DMA Transmit Packing                    */
+#define MCDRXPE                0x0008  /* Multichannel DMA Receive Packing                             */
+#define MCMEN          0x0010  /* Multichannel Frame Mode Enable                               */
+#define FSDR           0x0080  /* Multichannel Frame Sync to Data Relationship */
+#define MFD_0          0x0000  /* Multichannel Frame Delay = 0                                 */
+#define MFD_1          0x1000  /* Multichannel Frame Delay = 1                                 */
+#define MFD_2          0x2000  /* Multichannel Frame Delay = 2                                 */
+#define MFD_3          0x3000  /* Multichannel Frame Delay = 3                                 */
+#define MFD_4          0x4000  /* Multichannel Frame Delay = 4                                 */
+#define MFD_5          0x5000  /* Multichannel Frame Delay = 5                                 */
+#define MFD_6          0x6000  /* Multichannel Frame Delay = 6                                 */
+#define MFD_7          0x7000  /* Multichannel Frame Delay = 7                                 */
+#define MFD_8          0x8000  /* Multichannel Frame Delay = 8                                 */
+#define MFD_9          0x9000  /* Multichannel Frame Delay = 9                                 */
+#define MFD_10         0xA000  /* Multichannel Frame Delay = 10                                */
+#define MFD_11         0xB000  /* Multichannel Frame Delay = 11                                */
+#define MFD_12         0xC000  /* Multichannel Frame Delay = 12                                */
+#define MFD_13         0xD000  /* Multichannel Frame Delay = 13                                */
+#define MFD_14         0xE000  /* Multichannel Frame Delay = 14                                */
+#define MFD_15         0xF000  /* Multichannel Frame Delay = 15                                */
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
+/* EBIU_AMGCTL Masks                                                                                                                                   */
+#define AMCKEN                 0x0001  /* Enable CLKOUT                                                                        */
+#define        AMBEN_NONE              0x0000  /* All Banks Disabled                                                           */
+#define AMBEN_B0               0x0002  /* Enable Async Memory Bank 0 only                                      */
+#define AMBEN_B0_B1            0x0004  /* Enable Async Memory Banks 0 & 1 only                         */
+#define AMBEN_B0_B1_B2 0x0006  /* Enable Async Memory Banks 0, 1, and 2                        */
+#define AMBEN_ALL              0x0008  /* Enable Async Memory Banks (all) 0, 1, 2, and 3       */
+
+/* EBIU_AMBCTL0 Masks                                                                                                                                  */
+#define B0RDYEN                        0x00000001      /* Bank 0 (B0) RDY Enable                                                   */
+#define B0RDYPOL               0x00000002      /* B0 RDY Active High                                                               */
+#define B0TT_1                 0x00000004      /* B0 Transition Time (Read to Write) = 1 cycle             */
+#define B0TT_2                 0x00000008      /* B0 Transition Time (Read to Write) = 2 cycles    */
+#define B0TT_3                 0x0000000C      /* B0 Transition Time (Read to Write) = 3 cycles    */
+#define B0TT_4                 0x00000000      /* B0 Transition Time (Read to Write) = 4 cycles    */
+#define B0ST_1                 0x00000010      /* B0 Setup Time (AOE to Read/Write) = 1 cycle              */
+#define B0ST_2                 0x00000020      /* B0 Setup Time (AOE to Read/Write) = 2 cycles             */
+#define B0ST_3                 0x00000030      /* B0 Setup Time (AOE to Read/Write) = 3 cycles             */
+#define B0ST_4                 0x00000000      /* B0 Setup Time (AOE to Read/Write) = 4 cycles             */
+#define B0HT_1                 0x00000040      /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle             */
+#define B0HT_2                 0x00000080      /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles    */
+#define B0HT_3                 0x000000C0      /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles    */
+#define B0HT_0                 0x00000000      /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles    */
+#define B0RAT_1                        0x00000100      /* B0 Read Access Time = 1 cycle                                    */
+#define B0RAT_2                        0x00000200      /* B0 Read Access Time = 2 cycles                                   */
+#define B0RAT_3                        0x00000300      /* B0 Read Access Time = 3 cycles                                   */
+#define B0RAT_4                        0x00000400      /* B0 Read Access Time = 4 cycles                                   */
+#define B0RAT_5                        0x00000500      /* B0 Read Access Time = 5 cycles                                   */
+#define B0RAT_6                        0x00000600      /* B0 Read Access Time = 6 cycles                                   */
+#define B0RAT_7                        0x00000700      /* B0 Read Access Time = 7 cycles                                   */
+#define B0RAT_8                        0x00000800      /* B0 Read Access Time = 8 cycles                                   */
+#define B0RAT_9                        0x00000900      /* B0 Read Access Time = 9 cycles                                   */
+#define B0RAT_10               0x00000A00      /* B0 Read Access Time = 10 cycles                                  */
+#define B0RAT_11               0x00000B00      /* B0 Read Access Time = 11 cycles                                  */
+#define B0RAT_12               0x00000C00      /* B0 Read Access Time = 12 cycles                                  */
+#define B0RAT_13               0x00000D00      /* B0 Read Access Time = 13 cycles                                  */
+#define B0RAT_14               0x00000E00      /* B0 Read Access Time = 14 cycles                                  */
+#define B0RAT_15               0x00000F00      /* B0 Read Access Time = 15 cycles                                  */
+#define B0WAT_1                        0x00001000      /* B0 Write Access Time = 1 cycle                                   */
+#define B0WAT_2                        0x00002000      /* B0 Write Access Time = 2 cycles                                  */
+#define B0WAT_3                        0x00003000      /* B0 Write Access Time = 3 cycles                                  */
+#define B0WAT_4                        0x00004000      /* B0 Write Access Time = 4 cycles                                  */
+#define B0WAT_5                        0x00005000      /* B0 Write Access Time = 5 cycles                                  */
+#define B0WAT_6                        0x00006000      /* B0 Write Access Time = 6 cycles                                  */
+#define B0WAT_7                        0x00007000      /* B0 Write Access Time = 7 cycles                                  */
+#define B0WAT_8                        0x00008000      /* B0 Write Access Time = 8 cycles                                  */
+#define B0WAT_9                        0x00009000      /* B0 Write Access Time = 9 cycles                                  */
+#define B0WAT_10               0x0000A000      /* B0 Write Access Time = 10 cycles                                 */
+#define B0WAT_11               0x0000B000      /* B0 Write Access Time = 11 cycles                                 */
+#define B0WAT_12               0x0000C000      /* B0 Write Access Time = 12 cycles                                 */
+#define B0WAT_13               0x0000D000      /* B0 Write Access Time = 13 cycles                                 */
+#define B0WAT_14               0x0000E000      /* B0 Write Access Time = 14 cycles                                 */
+#define B0WAT_15               0x0000F000      /* B0 Write Access Time = 15 cycles                                 */
+
+#define B1RDYEN                        0x00010000      /* Bank 1 (B1) RDY Enable                           */
+#define B1RDYPOL               0x00020000      /* B1 RDY Active High                               */
+#define B1TT_1                 0x00040000      /* B1 Transition Time (Read to Write) = 1 cycle     */
+#define B1TT_2                 0x00080000      /* B1 Transition Time (Read to Write) = 2 cycles    */
+#define B1TT_3                 0x000C0000      /* B1 Transition Time (Read to Write) = 3 cycles    */
+#define B1TT_4                 0x00000000      /* B1 Transition Time (Read to Write) = 4 cycles    */
+#define B1ST_1                 0x00100000      /* B1 Setup Time (AOE to Read/Write) = 1 cycle      */
+#define B1ST_2                 0x00200000      /* B1 Setup Time (AOE to Read/Write) = 2 cycles     */
+#define B1ST_3                 0x00300000      /* B1 Setup Time (AOE to Read/Write) = 3 cycles     */
+#define B1ST_4                 0x00000000      /* B1 Setup Time (AOE to Read/Write) = 4 cycles     */
+#define B1HT_1                 0x00400000      /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle     */
+#define B1HT_2                 0x00800000      /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles    */
+#define B1HT_3                 0x00C00000      /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles    */
+#define B1HT_0                 0x00000000      /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles    */
+#define B1RAT_1                        0x01000000      /* B1 Read Access Time = 1 cycle                                    */
+#define B1RAT_2                        0x02000000      /* B1 Read Access Time = 2 cycles                                   */
+#define B1RAT_3                        0x03000000      /* B1 Read Access Time = 3 cycles                                   */
+#define B1RAT_4                        0x04000000      /* B1 Read Access Time = 4 cycles                                   */
+#define B1RAT_5                        0x05000000      /* B1 Read Access Time = 5 cycles                                   */
+#define B1RAT_6                        0x06000000      /* B1 Read Access Time = 6 cycles                                   */
+#define B1RAT_7                        0x07000000      /* B1 Read Access Time = 7 cycles                                   */
+#define B1RAT_8                        0x08000000      /* B1 Read Access Time = 8 cycles                                   */
+#define B1RAT_9                        0x09000000      /* B1 Read Access Time = 9 cycles                                   */
+#define B1RAT_10               0x0A000000      /* B1 Read Access Time = 10 cycles                                  */
+#define B1RAT_11               0x0B000000      /* B1 Read Access Time = 11 cycles                                  */
+#define B1RAT_12               0x0C000000      /* B1 Read Access Time = 12 cycles                                  */
+#define B1RAT_13               0x0D000000      /* B1 Read Access Time = 13 cycles                                  */
+#define B1RAT_14               0x0E000000      /* B1 Read Access Time = 14 cycles                                  */
+#define B1RAT_15               0x0F000000      /* B1 Read Access Time = 15 cycles                                  */
+#define B1WAT_1                        0x10000000      /* B1 Write Access Time = 1 cycle                                   */
+#define B1WAT_2                        0x20000000      /* B1 Write Access Time = 2 cycles                                  */
+#define B1WAT_3                        0x30000000      /* B1 Write Access Time = 3 cycles                                  */
+#define B1WAT_4                        0x40000000      /* B1 Write Access Time = 4 cycles                                  */
+#define B1WAT_5                        0x50000000      /* B1 Write Access Time = 5 cycles                                  */
+#define B1WAT_6                        0x60000000      /* B1 Write Access Time = 6 cycles                                  */
+#define B1WAT_7                        0x70000000      /* B1 Write Access Time = 7 cycles                                  */
+#define B1WAT_8                        0x80000000      /* B1 Write Access Time = 8 cycles                                  */
+#define B1WAT_9                        0x90000000      /* B1 Write Access Time = 9 cycles                                  */
+#define B1WAT_10               0xA0000000      /* B1 Write Access Time = 10 cycles                                 */
+#define B1WAT_11               0xB0000000      /* B1 Write Access Time = 11 cycles                                 */
+#define B1WAT_12               0xC0000000      /* B1 Write Access Time = 12 cycles                                 */
+#define B1WAT_13               0xD0000000      /* B1 Write Access Time = 13 cycles                                 */
+#define B1WAT_14               0xE0000000      /* B1 Write Access Time = 14 cycles                                 */
+#define B1WAT_15               0xF0000000      /* B1 Write Access Time = 15 cycles                                 */
+
+/* EBIU_AMBCTL1 Masks                                                                                                                                  */
+#define B2RDYEN                        0x00000001      /* Bank 2 (B2) RDY Enable                                                   */
+#define B2RDYPOL               0x00000002      /* B2 RDY Active High                                                               */
+#define B2TT_1                 0x00000004      /* B2 Transition Time (Read to Write) = 1 cycle             */
+#define B2TT_2                 0x00000008      /* B2 Transition Time (Read to Write) = 2 cycles    */
+#define B2TT_3                 0x0000000C      /* B2 Transition Time (Read to Write) = 3 cycles    */
+#define B2TT_4                 0x00000000      /* B2 Transition Time (Read to Write) = 4 cycles    */
+#define B2ST_1                 0x00000010      /* B2 Setup Time (AOE to Read/Write) = 1 cycle              */
+#define B2ST_2                 0x00000020      /* B2 Setup Time (AOE to Read/Write) = 2 cycles             */
+#define B2ST_3                 0x00000030      /* B2 Setup Time (AOE to Read/Write) = 3 cycles             */
+#define B2ST_4                 0x00000000      /* B2 Setup Time (AOE to Read/Write) = 4 cycles             */
+#define B2HT_1                 0x00000040      /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle             */
+#define B2HT_2                 0x00000080      /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles    */
+#define B2HT_3                 0x000000C0      /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles    */
+#define B2HT_0                 0x00000000      /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles    */
+#define B2RAT_1                        0x00000100      /* B2 Read Access Time = 1 cycle                                    */
+#define B2RAT_2                        0x00000200      /* B2 Read Access Time = 2 cycles                                   */
+#define B2RAT_3                        0x00000300      /* B2 Read Access Time = 3 cycles                                   */
+#define B2RAT_4                        0x00000400      /* B2 Read Access Time = 4 cycles                                   */
+#define B2RAT_5                        0x00000500      /* B2 Read Access Time = 5 cycles                                   */
+#define B2RAT_6                        0x00000600      /* B2 Read Access Time = 6 cycles                                   */
+#define B2RAT_7                        0x00000700      /* B2 Read Access Time = 7 cycles                                   */
+#define B2RAT_8                        0x00000800      /* B2 Read Access Time = 8 cycles                                   */
+#define B2RAT_9                        0x00000900      /* B2 Read Access Time = 9 cycles                                   */
+#define B2RAT_10               0x00000A00      /* B2 Read Access Time = 10 cycles                                  */
+#define B2RAT_11               0x00000B00      /* B2 Read Access Time = 11 cycles                                  */
+#define B2RAT_12               0x00000C00      /* B2 Read Access Time = 12 cycles                                  */
+#define B2RAT_13               0x00000D00      /* B2 Read Access Time = 13 cycles                                  */
+#define B2RAT_14               0x00000E00      /* B2 Read Access Time = 14 cycles                                  */
+#define B2RAT_15               0x00000F00      /* B2 Read Access Time = 15 cycles                                  */
+#define B2WAT_1                        0x00001000      /* B2 Write Access Time = 1 cycle                                   */
+#define B2WAT_2                        0x00002000      /* B2 Write Access Time = 2 cycles                                  */
+#define B2WAT_3                        0x00003000      /* B2 Write Access Time = 3 cycles                                  */
+#define B2WAT_4                        0x00004000      /* B2 Write Access Time = 4 cycles                                  */
+#define B2WAT_5                        0x00005000      /* B2 Write Access Time = 5 cycles                                  */
+#define B2WAT_6                        0x00006000      /* B2 Write Access Time = 6 cycles                                  */
+#define B2WAT_7                        0x00007000      /* B2 Write Access Time = 7 cycles                                  */
+#define B2WAT_8                        0x00008000      /* B2 Write Access Time = 8 cycles                                  */
+#define B2WAT_9                        0x00009000      /* B2 Write Access Time = 9 cycles                                  */
+#define B2WAT_10               0x0000A000      /* B2 Write Access Time = 10 cycles                                 */
+#define B2WAT_11               0x0000B000      /* B2 Write Access Time = 11 cycles                                 */
+#define B2WAT_12               0x0000C000      /* B2 Write Access Time = 12 cycles                                 */
+#define B2WAT_13               0x0000D000      /* B2 Write Access Time = 13 cycles                                 */
+#define B2WAT_14               0x0000E000      /* B2 Write Access Time = 14 cycles                                 */
+#define B2WAT_15               0x0000F000      /* B2 Write Access Time = 15 cycles                                 */
+
+#define B3RDYEN                        0x00010000      /* Bank 3 (B3) RDY Enable                                                   */
+#define B3RDYPOL               0x00020000      /* B3 RDY Active High                                                               */
+#define B3TT_1                 0x00040000      /* B3 Transition Time (Read to Write) = 1 cycle             */
+#define B3TT_2                 0x00080000      /* B3 Transition Time (Read to Write) = 2 cycles    */
+#define B3TT_3                 0x000C0000      /* B3 Transition Time (Read to Write) = 3 cycles    */
+#define B3TT_4                 0x00000000      /* B3 Transition Time (Read to Write) = 4 cycles    */
+#define B3ST_1                 0x00100000      /* B3 Setup Time (AOE to Read/Write) = 1 cycle              */
+#define B3ST_2                 0x00200000      /* B3 Setup Time (AOE to Read/Write) = 2 cycles             */
+#define B3ST_3                 0x00300000      /* B3 Setup Time (AOE to Read/Write) = 3 cycles             */
+#define B3ST_4                 0x00000000      /* B3 Setup Time (AOE to Read/Write) = 4 cycles             */
+#define B3HT_1                 0x00400000      /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle             */
+#define B3HT_2                 0x00800000      /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles    */
+#define B3HT_3                 0x00C00000      /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles    */
+#define B3HT_0                 0x00000000      /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles    */
+#define B3RAT_1                        0x01000000      /* B3 Read Access Time = 1 cycle                                    */
+#define B3RAT_2                        0x02000000      /* B3 Read Access Time = 2 cycles                                   */
+#define B3RAT_3                        0x03000000      /* B3 Read Access Time = 3 cycles                                   */
+#define B3RAT_4                        0x04000000      /* B3 Read Access Time = 4 cycles                                   */
+#define B3RAT_5                        0x05000000      /* B3 Read Access Time = 5 cycles                                   */
+#define B3RAT_6                        0x06000000      /* B3 Read Access Time = 6 cycles                                   */
+#define B3RAT_7                        0x07000000      /* B3 Read Access Time = 7 cycles                                   */
+#define B3RAT_8                        0x08000000      /* B3 Read Access Time = 8 cycles                                   */
+#define B3RAT_9                        0x09000000      /* B3 Read Access Time = 9 cycles                                   */
+#define B3RAT_10               0x0A000000      /* B3 Read Access Time = 10 cycles                                  */
+#define B3RAT_11               0x0B000000      /* B3 Read Access Time = 11 cycles                                  */
+#define B3RAT_12               0x0C000000      /* B3 Read Access Time = 12 cycles                                  */
+#define B3RAT_13               0x0D000000      /* B3 Read Access Time = 13 cycles                                  */
+#define B3RAT_14               0x0E000000      /* B3 Read Access Time = 14 cycles                                  */
+#define B3RAT_15               0x0F000000      /* B3 Read Access Time = 15 cycles                                  */
+#define B3WAT_1                        0x10000000      /* B3 Write Access Time = 1 cycle                                   */
+#define B3WAT_2                        0x20000000      /* B3 Write Access Time = 2 cycles                                  */
+#define B3WAT_3                        0x30000000      /* B3 Write Access Time = 3 cycles                                  */
+#define B3WAT_4                        0x40000000      /* B3 Write Access Time = 4 cycles                                  */
+#define B3WAT_5                        0x50000000      /* B3 Write Access Time = 5 cycles                                  */
+#define B3WAT_6                        0x60000000      /* B3 Write Access Time = 6 cycles                                  */
+#define B3WAT_7                        0x70000000      /* B3 Write Access Time = 7 cycles                                  */
+#define B3WAT_8                        0x80000000      /* B3 Write Access Time = 8 cycles                                  */
+#define B3WAT_9                        0x90000000      /* B3 Write Access Time = 9 cycles                                  */
+#define B3WAT_10               0xA0000000      /* B3 Write Access Time = 10 cycles                                 */
+#define B3WAT_11               0xB0000000      /* B3 Write Access Time = 11 cycles                                 */
+#define B3WAT_12               0xC0000000      /* B3 Write Access Time = 12 cycles                                 */
+#define B3WAT_13               0xD0000000      /* B3 Write Access Time = 13 cycles                                 */
+#define B3WAT_14               0xE0000000      /* B3 Write Access Time = 14 cycles                                 */
+#define B3WAT_15               0xF0000000      /* B3 Write Access Time = 15 cycles                                 */
+
+/* **********************  SDRAM CONTROLLER MASKS  **********************************************/
+/* EBIU_SDGCTL Masks                                                                                                                                                   */
+#define SCTLE                  0x00000001      /* Enable SDRAM Signals                                                                         */
+#define CL_2                   0x00000008      /* SDRAM CAS Latency = 2 cycles                                                         */
+#define CL_3                   0x0000000C      /* SDRAM CAS Latency = 3 cycles                                                         */
+#define PASR_ALL               0x00000000      /* All 4 SDRAM Banks Refreshed In Self-Refresh                          */
+#define PASR_B0_B1             0x00000010      /* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh            */
+#define PASR_B0                        0x00000020      /* Only SDRAM Bank 0 Is Refreshed In Self-Refresh                       */
+#define TRAS_1                 0x00000040      /* SDRAM tRAS = 1 cycle                                                                         */
+#define TRAS_2                 0x00000080      /* SDRAM tRAS = 2 cycles                                                                        */
+#define TRAS_3                 0x000000C0      /* SDRAM tRAS = 3 cycles                                                                        */
+#define TRAS_4                 0x00000100      /* SDRAM tRAS = 4 cycles                                                                        */
+#define TRAS_5                 0x00000140      /* SDRAM tRAS = 5 cycles                                                                        */
+#define TRAS_6                 0x00000180      /* SDRAM tRAS = 6 cycles                                                                        */
+#define TRAS_7                 0x000001C0      /* SDRAM tRAS = 7 cycles                                                                        */
+#define TRAS_8                 0x00000200      /* SDRAM tRAS = 8 cycles                                                                        */
+#define TRAS_9                 0x00000240      /* SDRAM tRAS = 9 cycles                                                                        */
+#define TRAS_10                        0x00000280      /* SDRAM tRAS = 10 cycles                                                                       */
+#define TRAS_11                        0x000002C0      /* SDRAM tRAS = 11 cycles                                                                       */
+#define TRAS_12                        0x00000300      /* SDRAM tRAS = 12 cycles                                                                       */
+#define TRAS_13                        0x00000340      /* SDRAM tRAS = 13 cycles                                                                       */
+#define TRAS_14                        0x00000380      /* SDRAM tRAS = 14 cycles                                                                       */
+#define TRAS_15                        0x000003C0      /* SDRAM tRAS = 15 cycles                                                                       */
+#define TRP_1                  0x00000800      /* SDRAM tRP = 1 cycle                                                                          */
+#define TRP_2                  0x00001000      /* SDRAM tRP = 2 cycles                                                                         */
+#define TRP_3                  0x00001800      /* SDRAM tRP = 3 cycles                                                                         */
+#define TRP_4                  0x00002000      /* SDRAM tRP = 4 cycles                                                                         */
+#define TRP_5                  0x00002800      /* SDRAM tRP = 5 cycles                                                                         */
+#define TRP_6                  0x00003000      /* SDRAM tRP = 6 cycles                                                                         */
+#define TRP_7                  0x00003800      /* SDRAM tRP = 7 cycles                                                                         */
+#define TRCD_1                 0x00008000      /* SDRAM tRCD = 1 cycle                                                                         */
+#define TRCD_2                 0x00010000      /* SDRAM tRCD = 2 cycles                                                                        */
+#define TRCD_3                 0x00018000      /* SDRAM tRCD = 3 cycles                                                                        */
+#define TRCD_4                 0x00020000      /* SDRAM tRCD = 4 cycles                                                                        */
+#define TRCD_5                 0x00028000      /* SDRAM tRCD = 5 cycles                                                                        */
+#define TRCD_6                 0x00030000      /* SDRAM tRCD = 6 cycles                                                                        */
+#define TRCD_7                 0x00038000      /* SDRAM tRCD = 7 cycles                                                                        */
+#define TWR_1                  0x00080000      /* SDRAM tWR = 1 cycle                                                                          */
+#define TWR_2                  0x00100000      /* SDRAM tWR = 2 cycles                                                                         */
+#define TWR_3                  0x00180000      /* SDRAM tWR = 3 cycles                                                                         */
+#define PUPSD                  0x00200000      /* Power-Up Start Delay (15 SCLK Cycles Delay)                          */
+#define PSM                            0x00400000      /* Power-Up Sequence (Mode Register Before/After* Refresh)      */
+#define PSS                            0x00800000      /* Enable Power-Up Sequence on Next SDRAM Access                        */
+#define SRFS                   0x01000000      /* Enable SDRAM Self-Refresh Mode                                                       */
+#define EBUFE                  0x02000000      /* Enable External Buffering Timing                                                     */
+#define FBBRW                  0x04000000      /* Enable Fast Back-To-Back Read To Write                                       */
+#define EMREN                  0x10000000      /* Extended Mode Register Enable                                                        */
+#define TCSR                   0x20000000      /* Temp-Compensated Self-Refresh Value (85/45* Deg C)           */
+#define CDDBG                  0x40000000      /* Tristate SDRAM Controls During Bus Grant                                     */
+
+/* EBIU_SDBCTL Masks                                                                                                                                           */
+#define EBE                            0x0001  /* Enable SDRAM External Bank                                                   */
+#define EBSZ_16                        0x0000  /* SDRAM External Bank Size = 16MB                                              */
+#define EBSZ_32                        0x0002  /* SDRAM External Bank Size = 32MB                                              */
+#define EBSZ_64                        0x0004  /* SDRAM External Bank Size = 64MB                                              */
+#define EBSZ_128               0x0006  /* SDRAM External Bank Size = 128MB                                             */
+#define EBCAW_8                        0x0000  /* SDRAM External Bank Column Address Width = 8 Bits    */
+#define EBCAW_9                        0x0010  /* SDRAM External Bank Column Address Width = 9 Bits    */
+#define EBCAW_10               0x0020  /* SDRAM External Bank Column Address Width = 10 Bits   */
+#define EBCAW_11               0x0030  /* SDRAM External Bank Column Address Width = 11 Bits   */
+
+/* EBIU_SDSTAT Masks                                                                                                           */
+#define SDCI                   0x0001  /* SDRAM Controller Idle                                */
+#define SDSRA                  0x0002  /* SDRAM Self-Refresh Active                    */
+#define SDPUA                  0x0004  /* SDRAM Power-Up Active                                */
+#define SDRS                   0x0008  /* SDRAM Will Power-Up On Next Access   */
+#define SDEASE                 0x0010  /* SDRAM EAB Sticky Error Status                */
+#define BGSTAT                 0x0020  /* Bus Grant Status                                             */
+
+/* **************************  DMA CONTROLLER MASKS  ********************************/
+/* DMAx_CONFIG, MDMA_yy_CONFIG Masks                                                                                           */
+#define DMAEN                  0x0001  /* DMA Channel Enable                                                   */
+#define WNR                            0x0002  /* Channel Direction (W/R*)                                             */
+#define WDSIZE_8               0x0000  /* Transfer Word Size = 8                                               */
+#define WDSIZE_16              0x0004  /* Transfer Word Size = 16                                              */
+#define WDSIZE_32              0x0008  /* Transfer Word Size = 32                                              */
+#define DMA2D                  0x0010  /* DMA Mode (2D/1D*)                                                    */
+#define RESTART                        0x0020  /* DMA Buffer Clear                                                             */
+#define DI_SEL                 0x0040  /* Data Interrupt Timing Select                                 */
+#define DI_EN                  0x0080  /* Data Interrupt Enable                                                */
+#define NDSIZE_0               0x0000  /* Next Descriptor Size = 0 (Stop/Autobuffer)   */
+#define NDSIZE_1               0x0100  /* Next Descriptor Size = 1                                             */
+#define NDSIZE_2               0x0200  /* Next Descriptor Size = 2                                             */
+#define NDSIZE_3               0x0300  /* Next Descriptor Size = 3                                             */
+#define NDSIZE_4               0x0400  /* Next Descriptor Size = 4                                             */
+#define NDSIZE_5               0x0500  /* Next Descriptor Size = 5                                             */
+#define NDSIZE_6               0x0600  /* Next Descriptor Size = 6                                             */
+#define NDSIZE_7               0x0700  /* Next Descriptor Size = 7                                             */
+#define NDSIZE_8               0x0800  /* Next Descriptor Size = 8                                             */
+#define NDSIZE_9               0x0900  /* Next Descriptor Size = 9                                             */
+#define NDSIZE                 0x0900  /* Next Descriptor Size */
+
+#define DMAFLOW                        0x7000  /* Flow Control */
+#define DMAFLOW_STOP           0x0000  /* Stop Mode */
+#define DMAFLOW_AUTO           0x1000  /* Autobuffer Mode */
+#define DMAFLOW_ARRAY          0x4000  /* Descriptor Array Mode */
+#define DMAFLOW_SMALL          0x6000  /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE          0x7000  /* Large Model Descriptor List Mode */
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks                                                           */
+#define CTYPE                  0x0040  /* DMA Channel Type Indicator (Memory/Peripheral*)      */
+#define PMAP                   0xF000  /* Peripheral Mapped To This Channel                            */
+#define PMAP_PPI               0x0000  /*              PPI Port DMA                                                            */
+#define        PMAP_EMACRX             0x1000  /*              Ethernet Receive DMA                                            */
+#define PMAP_EMACTX            0x2000  /*              Ethernet Transmit DMA                                           */
+#define PMAP_SPORT0RX  0x3000  /*              SPORT0 Receive DMA                                                      */
+#define PMAP_SPORT0TX  0x4000  /*              SPORT0 Transmit DMA                                                     */
+#define PMAP_SPORT1RX  0x5000  /*              SPORT1 Receive DMA                                                      */
+#define PMAP_SPORT1TX  0x6000  /*              SPORT1 Transmit DMA                                                     */
+#define PMAP_SPI               0x7000  /*              SPI Port DMA                                                            */
+#define PMAP_UART0RX   0x8000  /*              UART0 Port Receive DMA                                          */
+#define PMAP_UART0TX   0x9000  /*              UART0 Port Transmit DMA                                         */
+#define        PMAP_UART1RX    0xA000  /*              UART1 Port Receive DMA                                          */
+#define        PMAP_UART1TX    0xB000  /*              UART1 Port Transmit DMA                                         */
+
+/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks                                           */
+#define DMA_DONE               0x0001  /* DMA Completion Interrupt Status      */
+#define DMA_ERR                        0x0002  /* DMA Error Interrupt Status           */
+#define DFETCH                 0x0004  /* DMA Descriptor Fetch Indicator       */
+#define DMA_RUN                        0x0008  /* DMA Channel Running Indicator        */
+
+/*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
+/*  PPI_CONTROL Masks                                                                                                  */
+#define PORT_EN                        0x0001  /* PPI Port Enable                                      */
+#define PORT_DIR               0x0002  /* PPI Port Direction                           */
+#define XFR_TYPE               0x000C  /* PPI Transfer Type                            */
+#define PORT_CFG               0x0030  /* PPI Port Configuration                       */
+#define FLD_SEL                        0x0040  /* PPI Active Field Select                      */
+#define PACK_EN                        0x0080  /* PPI Packing Mode                                     */
+#define DMA32                  0x0100  /* PPI 32-bit DMA Enable                        */
+#define SKIP_EN                        0x0200  /* PPI Skip Element Enable                      */
+#define SKIP_EO                        0x0400  /* PPI Skip Even/Odd Elements           */
+#define DLENGTH         0x3800 /* PPI Data Length  */
+#define DLEN_8                 0x0000  /* Data Length = 8 Bits                         */
+#define DLEN_10                        0x0800  /* Data Length = 10 Bits                        */
+#define DLEN_11                        0x1000  /* Data Length = 11 Bits                        */
+#define DLEN_12                        0x1800  /* Data Length = 12 Bits                        */
+#define DLEN_13                        0x2000  /* Data Length = 13 Bits                        */
+#define DLEN_14                        0x2800  /* Data Length = 14 Bits                        */
+#define DLEN_15                        0x3000  /* Data Length = 15 Bits                        */
+#define DLEN_16                        0x3800  /* Data Length = 16 Bits                        */
+#define POLC                   0x4000  /* PPI Clock Polarity                           */
+#define POLS                   0x8000  /* PPI Frame Sync Polarity                      */
+
+/* PPI_STATUS Masks                                                                                                            */
+#define FLD                            0x0400  /* Field Indicator                                      */
+#define FT_ERR                 0x0800  /* Frame Track Error                            */
+#define OVR                            0x1000  /* FIFO Overflow Error                          */
+#define UNDR                   0x2000  /* FIFO Underrun Error                          */
+#define ERR_DET                        0x4000  /* Error Detected Indicator                     */
+#define ERR_NCOR               0x8000  /* Error Not Corrected Indicator        */
+
+/*  ********************  TWO-WIRE INTERFACE (TWI) MASKS  ***********************/
+/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y);  )                               */
+#define        CLKLOW(x)       ((x) & 0xFF)    /* Periods Clock Is Held Low                    */
+#define CLKHI(y)       (((y)&0xFF)<<0x8)       /* Periods Before New Clock Low                 */
+
+/* TWI_PRESCALE Masks                                                                                                                  */
+#define        PRESCALE        0x007F  /* SCLKs Per Internal Time Reference (10MHz)    */
+#define        TWI_ENA         0x0080  /* TWI Enable                                                                   */
+#define        SCCB            0x0200  /* SCCB Compatibility Enable                                    */
+
+/* TWI_SLAVE_CTRL Masks                                                                                                                        */
+#define        SEN                     0x0001  /* Slave Enable                                                                 */
+#define        SADD_LEN        0x0002  /* Slave Address Length                                                 */
+#define        STDVAL          0x0004  /* Slave Transmit Data Valid                                    */
+#define        NAK                     0x0008  /* NAK/ACK* Generated At Conclusion Of Transfer */
+#define        GEN                     0x0010  /* General Call Adrress Matching Enabled                */
+
+/* TWI_SLAVE_STAT Masks                                                                                                                        */
+#define        SDIR            0x0001  /* Slave Transfer Direction (Transmit/Receive*) */
+#define GCALL          0x0002  /* General Call Indicator                                               */
+
+/* TWI_MASTER_CTRL Masks                                                                                                       */
+#define        MEN                     0x0001  /* Master Mode Enable                                           */
+#define        MADD_LEN        0x0002  /* Master Address Length                                        */
+#define        MDIR            0x0004  /* Master Transmit Direction (RX/TX*)           */
+#define        FAST            0x0008  /* Use Fast Mode Timing Specs                           */
+#define        STOP            0x0010  /* Issue Stop Condition                                         */
+#define        RSTART          0x0020  /* Repeat Start or Stop* At End Of Transfer     */
+#define        DCNT            0x3FC0  /* Data Bytes To Transfer                                       */
+#define        SDAOVR          0x4000  /* Serial Data Override                                         */
+#define        SCLOVR          0x8000  /* Serial Clock Override                                        */
+
+/* TWI_MASTER_STAT Masks                                                                                                               */
+#define        MPROG           0x0001  /* Master Transfer In Progress                                  */
+#define        LOSTARB         0x0002  /* Lost Arbitration Indicator (Xfer Aborted)    */
+#define        ANAK            0x0004  /* Address Not Acknowledged                                             */
+#define        DNAK            0x0008  /* Data Not Acknowledged                                                */
+#define        BUFRDERR        0x0010  /* Buffer Read Error                                                    */
+#define        BUFWRERR        0x0020  /* Buffer Write Error                                                   */
+#define        SDASEN          0x0040  /* Serial Data Sense                                                    */
+#define        SCLSEN          0x0080  /* Serial Clock Sense                                                   */
+#define        BUSBUSY         0x0100  /* Bus Busy Indicator                                                   */
+
+/* TWI_INT_SRC and TWI_INT_ENABLE Masks                                                */
+#define        SINIT           0x0001  /* Slave Transfer Initiated     */
+#define        SCOMP           0x0002  /* Slave Transfer Complete      */
+#define        SERR            0x0004  /* Slave Transfer Error         */
+#define        SOVF            0x0008  /* Slave Overflow                       */
+#define        MCOMP           0x0010  /* Master Transfer Complete     */
+#define        MERR            0x0020  /* Master Transfer Error        */
+#define        XMTSERV         0x0040  /* Transmit FIFO Service        */
+#define        RCVSERV         0x0080  /* Receive FIFO Service         */
+
+/* TWI_FIFO_CTRL Masks                                                                                         */
+#define        XMTFLUSH        0x0001  /* Transmit Buffer Flush                        */
+#define        RCVFLUSH        0x0002  /* Receive Buffer Flush                         */
+#define        XMTINTLEN       0x0004  /* Transmit Buffer Interrupt Length     */
+#define        RCVINTLEN       0x0008  /* Receive Buffer Interrupt Length      */
+
+/* TWI_FIFO_STAT Masks                                                                                                                 */
+#define        XMTSTAT         0x0003  /* Transmit FIFO Status                                                 */
+#define        XMT_EMPTY       0x0000  /*              Transmit FIFO Empty                                             */
+#define        XMT_HALF        0x0001  /*              Transmit FIFO Has 1 Byte To Write               */
+#define        XMT_FULL        0x0003  /*              Transmit FIFO Full (2 Bytes To Write)   */
+
+#define        RCVSTAT         0x000C  /* Receive FIFO Status                                                  */
+#define        RCV_EMPTY       0x0000  /*              Receive FIFO Empty                                              */
+#define        RCV_HALF        0x0004  /*              Receive FIFO Has 1 Byte To Read                 */
+#define        RCV_FULL        0x000C  /*              Receive FIFO Full (2 Bytes To Read)             */
+
+/* ************  CONTROLLER AREA NETWORK (CAN) MASKS  ***************/
+/* CAN_CONTROL Masks                                                                                           */
+#define        SRS                     0x0001  /* Software Reset                                               */
+#define        DNM                     0x0002  /* Device Net Mode                                              */
+#define        ABO                     0x0004  /* Auto-Bus On Enable                                   */
+#define        TXPRIO          0x0008  /* TX Priority (Priority/Mailbox*)              */
+#define        WBA                     0x0010  /* Wake-Up On CAN Bus Activity Enable   */
+#define        SMR                     0x0020  /* Sleep Mode Request                                   */
+#define        CSR                     0x0040  /* CAN Suspend Mode Request                             */
+#define        CCR                     0x0080  /* CAN Configuration Mode Request               */
+
+/* CAN_STATUS Masks                                                                                            */
+#define        WT                      0x0001  /* TX Warning Flag                                      */
+#define        WR                      0x0002  /* RX Warning Flag                                      */
+#define        EP                      0x0004  /* Error Passive Mode                           */
+#define        EBO                     0x0008  /* Error Bus Off Mode                           */
+#define        SMA                     0x0020  /* Sleep Mode Acknowledge                       */
+#define        CSA                     0x0040  /* Suspend Mode Acknowledge                     */
+#define        CCA                     0x0080  /* Configuration Mode Acknowledge       */
+#define        MBPTR           0x1F00  /* Mailbox Pointer                                      */
+#define        TRM                     0x4000  /* Transmit Mode                                        */
+#define        REC                     0x8000  /* Receive Mode                                         */
+
+/* CAN_CLOCK Masks                                                                     */
+#define        BRP                     0x03FF  /* Bit-Rate Pre-Scaler  */
+
+/* CAN_TIMING Masks                                                                                    */
+#define        TSEG1           0x000F  /* Time Segment 1                               */
+#define        TSEG2           0x0070  /* Time Segment 2                               */
+#define        SAM                     0x0080  /* Sampling                                             */
+#define        SJW                     0x0300  /* Synchronization Jump Width   */
+
+/* CAN_DEBUG Masks                                                                                     */
+#define        DEC                     0x0001  /* Disable CAN Error Counters   */
+#define        DRI                     0x0002  /* Disable CAN RX Input                 */
+#define        DTO                     0x0004  /* Disable CAN TX Output                */
+#define        DIL                     0x0008  /* Disable CAN Internal Loop    */
+#define        MAA                     0x0010  /* Mode Auto-Acknowledge Enable */
+#define        MRB                     0x0020  /* Mode Read Back Enable                */
+#define        CDE                     0x8000  /* CAN Debug Enable                             */
+
+/* CAN_CEC Masks                                                                               */
+#define        RXECNT          0x00FF  /* Receive Error Counter        */
+#define        TXECNT          0xFF00  /* Transmit Error Counter       */
+
+/* CAN_INTR Masks                                                                                      */
+#define        MBRIF           0x0001  /* Mailbox Receive Interrupt    */
+#define        MBTIF           0x0002  /* Mailbox Transmit Interrupt   */
+#define        GIRQ            0x0004  /* Global Interrupt                             */
+#define        SMACK           0x0008  /* Sleep Mode Acknowledge               */
+#define        CANTX           0x0040  /* CAN TX Bus Value                             */
+#define        CANRX           0x0080  /* CAN RX Bus Value                             */
+
+/* CAN_MBxx_ID1 and CAN_MBxx_ID0 Masks                                                                         */
+#define DFC                    0xFFFF  /* Data Filtering Code (If Enabled) (ID0)               */
+#define        EXTID_LO        0xFFFF  /* Lower 16 Bits of Extended Identifier (ID0)   */
+#define        EXTID_HI        0x0003  /* Upper 2 Bits of Extended Identifier (ID1)    */
+#define        BASEID          0x1FFC  /* Base Identifier                                                              */
+#define        IDE                     0x2000  /* Identifier Extension                                                 */
+#define        RTR                     0x4000  /* Remote Frame Transmission Request                    */
+#define        AME                     0x8000  /* Acceptance Mask Enable                                               */
+
+/* CAN_MBxx_TIMESTAMP Masks                                    */
+#define TSV                    0xFFFF  /* Timestamp    */
+
+/* CAN_MBxx_LENGTH Masks                                               */
+#define DLC                    0x000F  /* Data Length Code     */
+
+/* CAN_AMxxH and CAN_AMxxL Masks                                                                                               */
+#define DFM                    0xFFFF  /* Data Field Mask (If Enabled) (CAN_AMxxL)                     */
+#define        EXTID_LO        0xFFFF  /* Lower 16 Bits of Extended Identifier (CAN_AMxxL)     */
+#define        EXTID_HI        0x0003  /* Upper 2 Bits of Extended Identifier (CAN_AMxxH)      */
+#define        BASEID          0x1FFC  /* Base Identifier                                                                      */
+#define        AMIDE           0x2000  /* Acceptance Mask ID Extension Enable                          */
+#define        FMD                     0x4000  /* Full Mask Data Field Enable                                          */
+#define        FDF                     0x8000  /* Filter On Data Field Enable                                          */
+
+/* CAN_MC1 Masks                                                                       */
+#define        MC0                     0x0001  /* Enable Mailbox 0             */
+#define        MC1                     0x0002  /* Enable Mailbox 1             */
+#define        MC2                     0x0004  /* Enable Mailbox 2             */
+#define        MC3                     0x0008  /* Enable Mailbox 3             */
+#define        MC4                     0x0010  /* Enable Mailbox 4             */
+#define        MC5                     0x0020  /* Enable Mailbox 5             */
+#define        MC6                     0x0040  /* Enable Mailbox 6             */
+#define        MC7                     0x0080  /* Enable Mailbox 7             */
+#define        MC8                     0x0100  /* Enable Mailbox 8             */
+#define        MC9                     0x0200  /* Enable Mailbox 9             */
+#define        MC10            0x0400  /* Enable Mailbox 10    */
+#define        MC11            0x0800  /* Enable Mailbox 11    */
+#define        MC12            0x1000  /* Enable Mailbox 12    */
+#define        MC13            0x2000  /* Enable Mailbox 13    */
+#define        MC14            0x4000  /* Enable Mailbox 14    */
+#define        MC15            0x8000  /* Enable Mailbox 15    */
+
+/* CAN_MC2 Masks                                                                       */
+#define        MC16            0x0001  /* Enable Mailbox 16    */
+#define        MC17            0x0002  /* Enable Mailbox 17    */
+#define        MC18            0x0004  /* Enable Mailbox 18    */
+#define        MC19            0x0008  /* Enable Mailbox 19    */
+#define        MC20            0x0010  /* Enable Mailbox 20    */
+#define        MC21            0x0020  /* Enable Mailbox 21    */
+#define        MC22            0x0040  /* Enable Mailbox 22    */
+#define        MC23            0x0080  /* Enable Mailbox 23    */
+#define        MC24            0x0100  /* Enable Mailbox 24    */
+#define        MC25            0x0200  /* Enable Mailbox 25    */
+#define        MC26            0x0400  /* Enable Mailbox 26    */
+#define        MC27            0x0800  /* Enable Mailbox 27    */
+#define        MC28            0x1000  /* Enable Mailbox 28    */
+#define        MC29            0x2000  /* Enable Mailbox 29    */
+#define        MC30            0x4000  /* Enable Mailbox 30    */
+#define        MC31            0x8000  /* Enable Mailbox 31    */
+
+/* CAN_MD1 Masks                                                                                               */
+#define        MD0                     0x0001  /* Enable Mailbox 0 For Receive         */
+#define        MD1                     0x0002  /* Enable Mailbox 1 For Receive         */
+#define        MD2                     0x0004  /* Enable Mailbox 2 For Receive         */
+#define        MD3                     0x0008  /* Enable Mailbox 3 For Receive         */
+#define        MD4                     0x0010  /* Enable Mailbox 4 For Receive         */
+#define        MD5                     0x0020  /* Enable Mailbox 5 For Receive         */
+#define        MD6                     0x0040  /* Enable Mailbox 6 For Receive         */
+#define        MD7                     0x0080  /* Enable Mailbox 7 For Receive         */
+#define        MD8                     0x0100  /* Enable Mailbox 8 For Receive         */
+#define        MD9                     0x0200  /* Enable Mailbox 9 For Receive         */
+#define        MD10            0x0400  /* Enable Mailbox 10 For Receive        */
+#define        MD11            0x0800  /* Enable Mailbox 11 For Receive        */
+#define        MD12            0x1000  /* Enable Mailbox 12 For Receive        */
+#define        MD13            0x2000  /* Enable Mailbox 13 For Receive        */
+#define        MD14            0x4000  /* Enable Mailbox 14 For Receive        */
+#define        MD15            0x8000  /* Enable Mailbox 15 For Receive        */
+
+/* CAN_MD2 Masks                                                                                               */
+#define        MD16            0x0001  /* Enable Mailbox 16 For Receive        */
+#define        MD17            0x0002  /* Enable Mailbox 17 For Receive        */
+#define        MD18            0x0004  /* Enable Mailbox 18 For Receive        */
+#define        MD19            0x0008  /* Enable Mailbox 19 For Receive        */
+#define        MD20            0x0010  /* Enable Mailbox 20 For Receive        */
+#define        MD21            0x0020  /* Enable Mailbox 21 For Receive        */
+#define        MD22            0x0040  /* Enable Mailbox 22 For Receive        */
+#define        MD23            0x0080  /* Enable Mailbox 23 For Receive        */
+#define        MD24            0x0100  /* Enable Mailbox 24 For Receive        */
+#define        MD25            0x0200  /* Enable Mailbox 25 For Receive        */
+#define        MD26            0x0400  /* Enable Mailbox 26 For Receive        */
+#define        MD27            0x0800  /* Enable Mailbox 27 For Receive        */
+#define        MD28            0x1000  /* Enable Mailbox 28 For Receive        */
+#define        MD29            0x2000  /* Enable Mailbox 29 For Receive        */
+#define        MD30            0x4000  /* Enable Mailbox 30 For Receive        */
+#define        MD31            0x8000  /* Enable Mailbox 31 For Receive        */
+
+/* CAN_RMP1 Masks                                                                                              */
+#define        RMP0            0x0001  /* RX Message Pending In Mailbox 0      */
+#define        RMP1            0x0002  /* RX Message Pending In Mailbox 1      */
+#define        RMP2            0x0004  /* RX Message Pending In Mailbox 2      */
+#define        RMP3            0x0008  /* RX Message Pending In Mailbox 3      */
+#define        RMP4            0x0010  /* RX Message Pending In Mailbox 4      */
+#define        RMP5            0x0020  /* RX Message Pending In Mailbox 5      */
+#define        RMP6            0x0040  /* RX Message Pending In Mailbox 6      */
+#define        RMP7            0x0080  /* RX Message Pending In Mailbox 7      */
+#define        RMP8            0x0100  /* RX Message Pending In Mailbox 8      */
+#define        RMP9            0x0200  /* RX Message Pending In Mailbox 9      */
+#define        RMP10           0x0400  /* RX Message Pending In Mailbox 10     */
+#define        RMP11           0x0800  /* RX Message Pending In Mailbox 11     */
+#define        RMP12           0x1000  /* RX Message Pending In Mailbox 12     */
+#define        RMP13           0x2000  /* RX Message Pending In Mailbox 13     */
+#define        RMP14           0x4000  /* RX Message Pending In Mailbox 14     */
+#define        RMP15           0x8000  /* RX Message Pending In Mailbox 15     */
+
+/* CAN_RMP2 Masks                                                                                              */
+#define        RMP16           0x0001  /* RX Message Pending In Mailbox 16     */
+#define        RMP17           0x0002  /* RX Message Pending In Mailbox 17     */
+#define        RMP18           0x0004  /* RX Message Pending In Mailbox 18     */
+#define        RMP19           0x0008  /* RX Message Pending In Mailbox 19     */
+#define        RMP20           0x0010  /* RX Message Pending In Mailbox 20     */
+#define        RMP21           0x0020  /* RX Message Pending In Mailbox 21     */
+#define        RMP22           0x0040  /* RX Message Pending In Mailbox 22     */
+#define        RMP23           0x0080  /* RX Message Pending In Mailbox 23     */
+#define        RMP24           0x0100  /* RX Message Pending In Mailbox 24     */
+#define        RMP25           0x0200  /* RX Message Pending In Mailbox 25     */
+#define        RMP26           0x0400  /* RX Message Pending In Mailbox 26     */
+#define        RMP27           0x0800  /* RX Message Pending In Mailbox 27     */
+#define        RMP28           0x1000  /* RX Message Pending In Mailbox 28     */
+#define        RMP29           0x2000  /* RX Message Pending In Mailbox 29     */
+#define        RMP30           0x4000  /* RX Message Pending In Mailbox 30     */
+#define        RMP31           0x8000  /* RX Message Pending In Mailbox 31     */
+
+/* CAN_RML1 Masks                                                                                              */
+#define        RML0            0x0001  /* RX Message Lost In Mailbox 0         */
+#define        RML1            0x0002  /* RX Message Lost In Mailbox 1         */
+#define        RML2            0x0004  /* RX Message Lost In Mailbox 2         */
+#define        RML3            0x0008  /* RX Message Lost In Mailbox 3         */
+#define        RML4            0x0010  /* RX Message Lost In Mailbox 4         */
+#define        RML5            0x0020  /* RX Message Lost In Mailbox 5         */
+#define        RML6            0x0040  /* RX Message Lost In Mailbox 6         */
+#define        RML7            0x0080  /* RX Message Lost In Mailbox 7         */
+#define        RML8            0x0100  /* RX Message Lost In Mailbox 8         */
+#define        RML9            0x0200  /* RX Message Lost In Mailbox 9         */
+#define        RML10           0x0400  /* RX Message Lost In Mailbox 10        */
+#define        RML11           0x0800  /* RX Message Lost In Mailbox 11        */
+#define        RML12           0x1000  /* RX Message Lost In Mailbox 12        */
+#define        RML13           0x2000  /* RX Message Lost In Mailbox 13        */
+#define        RML14           0x4000  /* RX Message Lost In Mailbox 14        */
+#define        RML15           0x8000  /* RX Message Lost In Mailbox 15        */
+
+/* CAN_RML2 Masks                                                                                              */
+#define        RML16           0x0001  /* RX Message Lost In Mailbox 16        */
+#define        RML17           0x0002  /* RX Message Lost In Mailbox 17        */
+#define        RML18           0x0004  /* RX Message Lost In Mailbox 18        */
+#define        RML19           0x0008  /* RX Message Lost In Mailbox 19        */
+#define        RML20           0x0010  /* RX Message Lost In Mailbox 20        */
+#define        RML21           0x0020  /* RX Message Lost In Mailbox 21        */
+#define        RML22           0x0040  /* RX Message Lost In Mailbox 22        */
+#define        RML23           0x0080  /* RX Message Lost In Mailbox 23        */
+#define        RML24           0x0100  /* RX Message Lost In Mailbox 24        */
+#define        RML25           0x0200  /* RX Message Lost In Mailbox 25        */
+#define        RML26           0x0400  /* RX Message Lost In Mailbox 26        */
+#define        RML27           0x0800  /* RX Message Lost In Mailbox 27        */
+#define        RML28           0x1000  /* RX Message Lost In Mailbox 28        */
+#define        RML29           0x2000  /* RX Message Lost In Mailbox 29        */
+#define        RML30           0x4000  /* RX Message Lost In Mailbox 30        */
+#define        RML31           0x8000  /* RX Message Lost In Mailbox 31        */
+
+/* CAN_OPSS1 Masks                                                                                                                                                             */
+#define        OPSS0           0x0001  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 0       */
+#define        OPSS1           0x0002  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 1       */
+#define        OPSS2           0x0004  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 2       */
+#define        OPSS3           0x0008  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 3       */
+#define        OPSS4           0x0010  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 4       */
+#define        OPSS5           0x0020  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 5       */
+#define        OPSS6           0x0040  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 6       */
+#define        OPSS7           0x0080  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 7       */
+#define        OPSS8           0x0100  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 8       */
+#define        OPSS9           0x0200  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 9       */
+#define        OPSS10          0x0400  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 10      */
+#define        OPSS11          0x0800  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 11      */
+#define        OPSS12          0x1000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 12      */
+#define        OPSS13          0x2000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 13      */
+#define        OPSS14          0x4000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 14      */
+#define        OPSS15          0x8000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 15      */
+
+/* CAN_OPSS2 Masks                                                                                                                                                             */
+#define        OPSS16          0x0001  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 16      */
+#define        OPSS17          0x0002  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 17      */
+#define        OPSS18          0x0004  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 18      */
+#define        OPSS19          0x0008  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 19      */
+#define        OPSS20          0x0010  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 20      */
+#define        OPSS21          0x0020  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 21      */
+#define        OPSS22          0x0040  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 22      */
+#define        OPSS23          0x0080  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 23      */
+#define        OPSS24          0x0100  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 24      */
+#define        OPSS25          0x0200  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 25      */
+#define        OPSS26          0x0400  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 26      */
+#define        OPSS27          0x0800  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 27      */
+#define        OPSS28          0x1000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 28      */
+#define        OPSS29          0x2000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 29      */
+#define        OPSS30          0x4000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 30      */
+#define        OPSS31          0x8000  /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 31      */
+
+/* CAN_TRR1 Masks                                                                                                              */
+#define        TRR0            0x0001  /* Deny But Don't Lock Access To Mailbox 0      */
+#define        TRR1            0x0002  /* Deny But Don't Lock Access To Mailbox 1      */
+#define        TRR2            0x0004  /* Deny But Don't Lock Access To Mailbox 2      */
+#define        TRR3            0x0008  /* Deny But Don't Lock Access To Mailbox 3      */
+#define        TRR4            0x0010  /* Deny But Don't Lock Access To Mailbox 4      */
+#define        TRR5            0x0020  /* Deny But Don't Lock Access To Mailbox 5      */
+#define        TRR6            0x0040  /* Deny But Don't Lock Access To Mailbox 6      */
+#define        TRR7            0x0080  /* Deny But Don't Lock Access To Mailbox 7      */
+#define        TRR8            0x0100  /* Deny But Don't Lock Access To Mailbox 8      */
+#define        TRR9            0x0200  /* Deny But Don't Lock Access To Mailbox 9      */
+#define        TRR10           0x0400  /* Deny But Don't Lock Access To Mailbox 10     */
+#define        TRR11           0x0800  /* Deny But Don't Lock Access To Mailbox 11     */
+#define        TRR12           0x1000  /* Deny But Don't Lock Access To Mailbox 12     */
+#define        TRR13           0x2000  /* Deny But Don't Lock Access To Mailbox 13     */
+#define        TRR14           0x4000  /* Deny But Don't Lock Access To Mailbox 14     */
+#define        TRR15           0x8000  /* Deny But Don't Lock Access To Mailbox 15     */
+
+/* CAN_TRR2 Masks                                                                                                              */
+#define        TRR16           0x0001  /* Deny But Don't Lock Access To Mailbox 16     */
+#define        TRR17           0x0002  /* Deny But Don't Lock Access To Mailbox 17     */
+#define        TRR18           0x0004  /* Deny But Don't Lock Access To Mailbox 18     */
+#define        TRR19           0x0008  /* Deny But Don't Lock Access To Mailbox 19     */
+#define        TRR20           0x0010  /* Deny But Don't Lock Access To Mailbox 20     */
+#define        TRR21           0x0020  /* Deny But Don't Lock Access To Mailbox 21     */
+#define        TRR22           0x0040  /* Deny But Don't Lock Access To Mailbox 22     */
+#define        TRR23           0x0080  /* Deny But Don't Lock Access To Mailbox 23     */
+#define        TRR24           0x0100  /* Deny But Don't Lock Access To Mailbox 24     */
+#define        TRR25           0x0200  /* Deny But Don't Lock Access To Mailbox 25     */
+#define        TRR26           0x0400  /* Deny But Don't Lock Access To Mailbox 26     */
+#define        TRR27           0x0800  /* Deny But Don't Lock Access To Mailbox 27     */
+#define        TRR28           0x1000  /* Deny But Don't Lock Access To Mailbox 28     */
+#define        TRR29           0x2000  /* Deny But Don't Lock Access To Mailbox 29     */
+#define        TRR30           0x4000  /* Deny But Don't Lock Access To Mailbox 30     */
+#define        TRR31           0x8000  /* Deny But Don't Lock Access To Mailbox 31     */
+
+/* CAN_TRS1 Masks                                                                                                      */
+#define        TRS0            0x0001  /* Remote Frame Request For Mailbox 0   */
+#define        TRS1            0x0002  /* Remote Frame Request For Mailbox 1   */
+#define        TRS2            0x0004  /* Remote Frame Request For Mailbox 2   */
+#define        TRS3            0x0008  /* Remote Frame Request For Mailbox 3   */
+#define        TRS4            0x0010  /* Remote Frame Request For Mailbox 4   */
+#define        TRS5            0x0020  /* Remote Frame Request For Mailbox 5   */
+#define        TRS6            0x0040  /* Remote Frame Request For Mailbox 6   */
+#define        TRS7            0x0080  /* Remote Frame Request For Mailbox 7   */
+#define        TRS8            0x0100  /* Remote Frame Request For Mailbox 8   */
+#define        TRS9            0x0200  /* Remote Frame Request For Mailbox 9   */
+#define        TRS10           0x0400  /* Remote Frame Request For Mailbox 10  */
+#define        TRS11           0x0800  /* Remote Frame Request For Mailbox 11  */
+#define        TRS12           0x1000  /* Remote Frame Request For Mailbox 12  */
+#define        TRS13           0x2000  /* Remote Frame Request For Mailbox 13  */
+#define        TRS14           0x4000  /* Remote Frame Request For Mailbox 14  */
+#define        TRS15           0x8000  /* Remote Frame Request For Mailbox 15  */
+
+/* CAN_TRS2 Masks                                                                                                      */
+#define        TRS16           0x0001  /* Remote Frame Request For Mailbox 16  */
+#define        TRS17           0x0002  /* Remote Frame Request For Mailbox 17  */
+#define        TRS18           0x0004  /* Remote Frame Request For Mailbox 18  */
+#define        TRS19           0x0008  /* Remote Frame Request For Mailbox 19  */
+#define        TRS20           0x0010  /* Remote Frame Request For Mailbox 20  */
+#define        TRS21           0x0020  /* Remote Frame Request For Mailbox 21  */
+#define        TRS22           0x0040  /* Remote Frame Request For Mailbox 22  */
+#define        TRS23           0x0080  /* Remote Frame Request For Mailbox 23  */
+#define        TRS24           0x0100  /* Remote Frame Request For Mailbox 24  */
+#define        TRS25           0x0200  /* Remote Frame Request For Mailbox 25  */
+#define        TRS26           0x0400  /* Remote Frame Request For Mailbox 26  */
+#define        TRS27           0x0800  /* Remote Frame Request For Mailbox 27  */
+#define        TRS28           0x1000  /* Remote Frame Request For Mailbox 28  */
+#define        TRS29           0x2000  /* Remote Frame Request For Mailbox 29  */
+#define        TRS30           0x4000  /* Remote Frame Request For Mailbox 30  */
+#define        TRS31           0x8000  /* Remote Frame Request For Mailbox 31  */
+
+/* CAN_AA1 Masks                                                                                               */
+#define        AA0                     0x0001  /* Aborted Message In Mailbox 0         */
+#define        AA1                     0x0002  /* Aborted Message In Mailbox 1         */
+#define        AA2                     0x0004  /* Aborted Message In Mailbox 2         */
+#define        AA3                     0x0008  /* Aborted Message In Mailbox 3         */
+#define        AA4                     0x0010  /* Aborted Message In Mailbox 4         */
+#define        AA5                     0x0020  /* Aborted Message In Mailbox 5         */
+#define        AA6                     0x0040  /* Aborted Message In Mailbox 6         */
+#define        AA7                     0x0080  /* Aborted Message In Mailbox 7         */
+#define        AA8                     0x0100  /* Aborted Message In Mailbox 8         */
+#define        AA9                     0x0200  /* Aborted Message In Mailbox 9         */
+#define        AA10            0x0400  /* Aborted Message In Mailbox 10        */
+#define        AA11            0x0800  /* Aborted Message In Mailbox 11        */
+#define        AA12            0x1000  /* Aborted Message In Mailbox 12        */
+#define        AA13            0x2000  /* Aborted Message In Mailbox 13        */
+#define        AA14            0x4000  /* Aborted Message In Mailbox 14        */
+#define        AA15            0x8000  /* Aborted Message In Mailbox 15        */
+
+/* CAN_AA2 Masks                                                                                               */
+#define        AA16            0x0001  /* Aborted Message In Mailbox 16        */
+#define        AA17            0x0002  /* Aborted Message In Mailbox 17        */
+#define        AA18            0x0004  /* Aborted Message In Mailbox 18        */
+#define        AA19            0x0008  /* Aborted Message In Mailbox 19        */
+#define        AA20            0x0010  /* Aborted Message In Mailbox 20        */
+#define        AA21            0x0020  /* Aborted Message In Mailbox 21        */
+#define        AA22            0x0040  /* Aborted Message In Mailbox 22        */
+#define        AA23            0x0080  /* Aborted Message In Mailbox 23        */
+#define        AA24            0x0100  /* Aborted Message In Mailbox 24        */
+#define        AA25            0x0200  /* Aborted Message In Mailbox 25        */
+#define        AA26            0x0400  /* Aborted Message In Mailbox 26        */
+#define        AA27            0x0800  /* Aborted Message In Mailbox 27        */
+#define        AA28            0x1000  /* Aborted Message In Mailbox 28        */
+#define        AA29            0x2000  /* Aborted Message In Mailbox 29        */
+#define        AA30            0x4000  /* Aborted Message In Mailbox 30        */
+#define        AA31            0x8000  /* Aborted Message In Mailbox 31        */
+
+/* CAN_TA1 Masks                                                                                                       */
+#define        TA0                     0x0001  /* Transmit Successful From Mailbox 0   */
+#define        TA1                     0x0002  /* Transmit Successful From Mailbox 1   */
+#define        TA2                     0x0004  /* Transmit Successful From Mailbox 2   */
+#define        TA3                     0x0008  /* Transmit Successful From Mailbox 3   */
+#define        TA4                     0x0010  /* Transmit Successful From Mailbox 4   */
+#define        TA5                     0x0020  /* Transmit Successful From Mailbox 5   */
+#define        TA6                     0x0040  /* Transmit Successful From Mailbox 6   */
+#define        TA7                     0x0080  /* Transmit Successful From Mailbox 7   */
+#define        TA8                     0x0100  /* Transmit Successful From Mailbox 8   */
+#define        TA9                     0x0200  /* Transmit Successful From Mailbox 9   */
+#define        TA10            0x0400  /* Transmit Successful From Mailbox 10  */
+#define        TA11            0x0800  /* Transmit Successful From Mailbox 11  */
+#define        TA12            0x1000  /* Transmit Successful From Mailbox 12  */
+#define        TA13            0x2000  /* Transmit Successful From Mailbox 13  */
+#define        TA14            0x4000  /* Transmit Successful From Mailbox 14  */
+#define        TA15            0x8000  /* Transmit Successful From Mailbox 15  */
+
+/* CAN_TA2 Masks                                                                                                       */
+#define        TA16            0x0001  /* Transmit Successful From Mailbox 16  */
+#define        TA17            0x0002  /* Transmit Successful From Mailbox 17  */
+#define        TA18            0x0004  /* Transmit Successful From Mailbox 18  */
+#define        TA19            0x0008  /* Transmit Successful From Mailbox 19  */
+#define        TA20            0x0010  /* Transmit Successful From Mailbox 20  */
+#define        TA21            0x0020  /* Transmit Successful From Mailbox 21  */
+#define        TA22            0x0040  /* Transmit Successful From Mailbox 22  */
+#define        TA23            0x0080  /* Transmit Successful From Mailbox 23  */
+#define        TA24            0x0100  /* Transmit Successful From Mailbox 24  */
+#define        TA25            0x0200  /* Transmit Successful From Mailbox 25  */
+#define        TA26            0x0400  /* Transmit Successful From Mailbox 26  */
+#define        TA27            0x0800  /* Transmit Successful From Mailbox 27  */
+#define        TA28            0x1000  /* Transmit Successful From Mailbox 28  */
+#define        TA29            0x2000  /* Transmit Successful From Mailbox 29  */
+#define        TA30            0x4000  /* Transmit Successful From Mailbox 30  */
+#define        TA31            0x8000  /* Transmit Successful From Mailbox 31  */
+
+/* CAN_MBTD Masks                                                                                              */
+#define TDPTR          0x001F  /* Mailbox To Temporarily Disable       */
+#define        TDA                     0x0040  /* Temporary Disable Acknowledge        */
+#define        TDR                     0x0080  /* Temporary Disable Request            */
+
+/* CAN_RFH1 Masks                                                                                                                                              */
+#define        RFH0            0x0001  /* Enable Automatic Remote Frame Handling For Mailbox 0         */
+#define        RFH1            0x0002  /* Enable Automatic Remote Frame Handling For Mailbox 1         */
+#define        RFH2            0x0004  /* Enable Automatic Remote Frame Handling For Mailbox 2         */
+#define        RFH3            0x0008  /* Enable Automatic Remote Frame Handling For Mailbox 3         */
+#define        RFH4            0x0010  /* Enable Automatic Remote Frame Handling For Mailbox 4         */
+#define        RFH5            0x0020  /* Enable Automatic Remote Frame Handling For Mailbox 5         */
+#define        RFH6            0x0040  /* Enable Automatic Remote Frame Handling For Mailbox 6         */
+#define        RFH7            0x0080  /* Enable Automatic Remote Frame Handling For Mailbox 7         */
+#define        RFH8            0x0100  /* Enable Automatic Remote Frame Handling For Mailbox 8         */
+#define        RFH9            0x0200  /* Enable Automatic Remote Frame Handling For Mailbox 9         */
+#define        RFH10           0x0400  /* Enable Automatic Remote Frame Handling For Mailbox 10        */
+#define        RFH11           0x0800  /* Enable Automatic Remote Frame Handling For Mailbox 11        */
+#define        RFH12           0x1000  /* Enable Automatic Remote Frame Handling For Mailbox 12        */
+#define        RFH13           0x2000  /* Enable Automatic Remote Frame Handling For Mailbox 13        */
+#define        RFH14           0x4000  /* Enable Automatic Remote Frame Handling For Mailbox 14        */
+#define        RFH15           0x8000  /* Enable Automatic Remote Frame Handling For Mailbox 15        */
+
+/* CAN_RFH2 Masks                                                                                                                                              */
+#define        RFH16           0x0001  /* Enable Automatic Remote Frame Handling For Mailbox 16        */
+#define        RFH17           0x0002  /* Enable Automatic Remote Frame Handling For Mailbox 17        */
+#define        RFH18           0x0004  /* Enable Automatic Remote Frame Handling For Mailbox 18        */
+#define        RFH19           0x0008  /* Enable Automatic Remote Frame Handling For Mailbox 19        */
+#define        RFH20           0x0010  /* Enable Automatic Remote Frame Handling For Mailbox 20        */
+#define        RFH21           0x0020  /* Enable Automatic Remote Frame Handling For Mailbox 21        */
+#define        RFH22           0x0040  /* Enable Automatic Remote Frame Handling For Mailbox 22        */
+#define        RFH23           0x0080  /* Enable Automatic Remote Frame Handling For Mailbox 23        */
+#define        RFH24           0x0100  /* Enable Automatic Remote Frame Handling For Mailbox 24        */
+#define        RFH25           0x0200  /* Enable Automatic Remote Frame Handling For Mailbox 25        */
+#define        RFH26           0x0400  /* Enable Automatic Remote Frame Handling For Mailbox 26        */
+#define        RFH27           0x0800  /* Enable Automatic Remote Frame Handling For Mailbox 27        */
+#define        RFH28           0x1000  /* Enable Automatic Remote Frame Handling For Mailbox 28        */
+#define        RFH29           0x2000  /* Enable Automatic Remote Frame Handling For Mailbox 29        */
+#define        RFH30           0x4000  /* Enable Automatic Remote Frame Handling For Mailbox 30        */
+#define        RFH31           0x8000  /* Enable Automatic Remote Frame Handling For Mailbox 31        */
+
+/* CAN_MBTIF1 Masks                                                                                                    */
+#define        MBTIF0          0x0001  /* TX Interrupt Active In Mailbox 0             */
+#define        MBTIF1          0x0002  /* TX Interrupt Active In Mailbox 1             */
+#define        MBTIF2          0x0004  /* TX Interrupt Active In Mailbox 2             */
+#define        MBTIF3          0x0008  /* TX Interrupt Active In Mailbox 3             */
+#define        MBTIF4          0x0010  /* TX Interrupt Active In Mailbox 4             */
+#define        MBTIF5          0x0020  /* TX Interrupt Active In Mailbox 5             */
+#define        MBTIF6          0x0040  /* TX Interrupt Active In Mailbox 6             */
+#define        MBTIF7          0x0080  /* TX Interrupt Active In Mailbox 7             */
+#define        MBTIF8          0x0100  /* TX Interrupt Active In Mailbox 8             */
+#define        MBTIF9          0x0200  /* TX Interrupt Active In Mailbox 9             */
+#define        MBTIF10         0x0400  /* TX Interrupt Active In Mailbox 10    */
+#define        MBTIF11         0x0800  /* TX Interrupt Active In Mailbox 11    */
+#define        MBTIF12         0x1000  /* TX Interrupt Active In Mailbox 12    */
+#define        MBTIF13         0x2000  /* TX Interrupt Active In Mailbox 13    */
+#define        MBTIF14         0x4000  /* TX Interrupt Active In Mailbox 14    */
+#define        MBTIF15         0x8000  /* TX Interrupt Active In Mailbox 15    */
+
+/* CAN_MBTIF2 Masks                                                                                                    */
+#define        MBTIF16         0x0001  /* TX Interrupt Active In Mailbox 16    */
+#define        MBTIF17         0x0002  /* TX Interrupt Active In Mailbox 17    */
+#define        MBTIF18         0x0004  /* TX Interrupt Active In Mailbox 18    */
+#define        MBTIF19         0x0008  /* TX Interrupt Active In Mailbox 19    */
+#define        MBTIF20         0x0010  /* TX Interrupt Active In Mailbox 20    */
+#define        MBTIF21         0x0020  /* TX Interrupt Active In Mailbox 21    */
+#define        MBTIF22         0x0040  /* TX Interrupt Active In Mailbox 22    */
+#define        MBTIF23         0x0080  /* TX Interrupt Active In Mailbox 23    */
+#define        MBTIF24         0x0100  /* TX Interrupt Active In Mailbox 24    */
+#define        MBTIF25         0x0200  /* TX Interrupt Active In Mailbox 25    */
+#define        MBTIF26         0x0400  /* TX Interrupt Active In Mailbox 26    */
+#define        MBTIF27         0x0800  /* TX Interrupt Active In Mailbox 27    */
+#define        MBTIF28         0x1000  /* TX Interrupt Active In Mailbox 28    */
+#define        MBTIF29         0x2000  /* TX Interrupt Active In Mailbox 29    */
+#define        MBTIF30         0x4000  /* TX Interrupt Active In Mailbox 30    */
+#define        MBTIF31         0x8000  /* TX Interrupt Active In Mailbox 31    */
+
+/* CAN_MBRIF1 Masks                                                                                                    */
+#define        MBRIF0          0x0001  /* RX Interrupt Active In Mailbox 0             */
+#define        MBRIF1          0x0002  /* RX Interrupt Active In Mailbox 1             */
+#define        MBRIF2          0x0004  /* RX Interrupt Active In Mailbox 2             */
+#define        MBRIF3          0x0008  /* RX Interrupt Active In Mailbox 3             */
+#define        MBRIF4          0x0010  /* RX Interrupt Active In Mailbox 4             */
+#define        MBRIF5          0x0020  /* RX Interrupt Active In Mailbox 5             */
+#define        MBRIF6          0x0040  /* RX Interrupt Active In Mailbox 6             */
+#define        MBRIF7          0x0080  /* RX Interrupt Active In Mailbox 7             */
+#define        MBRIF8          0x0100  /* RX Interrupt Active In Mailbox 8             */
+#define        MBRIF9          0x0200  /* RX Interrupt Active In Mailbox 9             */
+#define        MBRIF10         0x0400  /* RX Interrupt Active In Mailbox 10    */
+#define        MBRIF11         0x0800  /* RX Interrupt Active In Mailbox 11    */
+#define        MBRIF12         0x1000  /* RX Interrupt Active In Mailbox 12    */
+#define        MBRIF13         0x2000  /* RX Interrupt Active In Mailbox 13    */
+#define        MBRIF14         0x4000  /* RX Interrupt Active In Mailbox 14    */
+#define        MBRIF15         0x8000  /* RX Interrupt Active In Mailbox 15    */
+
+/* CAN_MBRIF2 Masks                                                                                                    */
+#define        MBRIF16         0x0001  /* RX Interrupt Active In Mailbox 16    */
+#define        MBRIF17         0x0002  /* RX Interrupt Active In Mailbox 17    */
+#define        MBRIF18         0x0004  /* RX Interrupt Active In Mailbox 18    */
+#define        MBRIF19         0x0008  /* RX Interrupt Active In Mailbox 19    */
+#define        MBRIF20         0x0010  /* RX Interrupt Active In Mailbox 20    */
+#define        MBRIF21         0x0020  /* RX Interrupt Active In Mailbox 21    */
+#define        MBRIF22         0x0040  /* RX Interrupt Active In Mailbox 22    */
+#define        MBRIF23         0x0080  /* RX Interrupt Active In Mailbox 23    */
+#define        MBRIF24         0x0100  /* RX Interrupt Active In Mailbox 24    */
+#define        MBRIF25         0x0200  /* RX Interrupt Active In Mailbox 25    */
+#define        MBRIF26         0x0400  /* RX Interrupt Active In Mailbox 26    */
+#define        MBRIF27         0x0800  /* RX Interrupt Active In Mailbox 27    */
+#define        MBRIF28         0x1000  /* RX Interrupt Active In Mailbox 28    */
+#define        MBRIF29         0x2000  /* RX Interrupt Active In Mailbox 29    */
+#define        MBRIF30         0x4000  /* RX Interrupt Active In Mailbox 30    */
+#define        MBRIF31         0x8000  /* RX Interrupt Active In Mailbox 31    */
+
+/* CAN_MBIM1 Masks                                                                                             */
+#define        MBIM0           0x0001  /* Enable Interrupt For Mailbox 0       */
+#define        MBIM1           0x0002  /* Enable Interrupt For Mailbox 1       */
+#define        MBIM2           0x0004  /* Enable Interrupt For Mailbox 2       */
+#define        MBIM3           0x0008  /* Enable Interrupt For Mailbox 3       */
+#define        MBIM4           0x0010  /* Enable Interrupt For Mailbox 4       */
+#define        MBIM5           0x0020  /* Enable Interrupt For Mailbox 5       */
+#define        MBIM6           0x0040  /* Enable Interrupt For Mailbox 6       */
+#define        MBIM7           0x0080  /* Enable Interrupt For Mailbox 7       */
+#define        MBIM8           0x0100  /* Enable Interrupt For Mailbox 8       */
+#define        MBIM9           0x0200  /* Enable Interrupt For Mailbox 9       */
+#define        MBIM10          0x0400  /* Enable Interrupt For Mailbox 10      */
+#define        MBIM11          0x0800  /* Enable Interrupt For Mailbox 11      */
+#define        MBIM12          0x1000  /* Enable Interrupt For Mailbox 12      */
+#define        MBIM13          0x2000  /* Enable Interrupt For Mailbox 13      */
+#define        MBIM14          0x4000  /* Enable Interrupt For Mailbox 14      */
+#define        MBIM15          0x8000  /* Enable Interrupt For Mailbox 15      */
+
+/* CAN_MBIM2 Masks                                                                                             */
+#define        MBIM16          0x0001  /* Enable Interrupt For Mailbox 16      */
+#define        MBIM17          0x0002  /* Enable Interrupt For Mailbox 17      */
+#define        MBIM18          0x0004  /* Enable Interrupt For Mailbox 18      */
+#define        MBIM19          0x0008  /* Enable Interrupt For Mailbox 19      */
+#define        MBIM20          0x0010  /* Enable Interrupt For Mailbox 20      */
+#define        MBIM21          0x0020  /* Enable Interrupt For Mailbox 21      */
+#define        MBIM22          0x0040  /* Enable Interrupt For Mailbox 22      */
+#define        MBIM23          0x0080  /* Enable Interrupt For Mailbox 23      */
+#define        MBIM24          0x0100  /* Enable Interrupt For Mailbox 24      */
+#define        MBIM25          0x0200  /* Enable Interrupt For Mailbox 25      */
+#define        MBIM26          0x0400  /* Enable Interrupt For Mailbox 26      */
+#define        MBIM27          0x0800  /* Enable Interrupt For Mailbox 27      */
+#define        MBIM28          0x1000  /* Enable Interrupt For Mailbox 28      */
+#define        MBIM29          0x2000  /* Enable Interrupt For Mailbox 29      */
+#define        MBIM30          0x4000  /* Enable Interrupt For Mailbox 30      */
+#define        MBIM31          0x8000  /* Enable Interrupt For Mailbox 31      */
+
+/* CAN_GIM Masks                                                                                                                               */
+#define        EWTIM           0x0001  /* Enable TX Error Count Interrupt                                      */
+#define        EWRIM           0x0002  /* Enable RX Error Count Interrupt                                      */
+#define        EPIM            0x0004  /* Enable Error-Passive Mode Interrupt                          */
+#define        BOIM            0x0008  /* Enable Bus Off Interrupt                                                     */
+#define        WUIM            0x0010  /* Enable Wake-Up Interrupt                                                     */
+#define        UIAIM           0x0020  /* Enable Access To Unimplemented Address Interrupt     */
+#define        AAIM            0x0040  /* Enable Abort Acknowledge Interrupt                           */
+#define        RMLIM           0x0080  /* Enable RX Message Lost Interrupt                                     */
+#define        UCEIM           0x0100  /* Enable Universal Counter Overflow Interrupt          */
+#define        EXTIM           0x0200  /* Enable External Trigger Output Interrupt                     */
+#define        ADIM            0x0400  /* Enable Access Denied Interrupt                                       */
+
+/* CAN_GIS Masks                                                                                                                       */
+#define        EWTIS           0x0001  /* TX Error Count IRQ Status                                    */
+#define        EWRIS           0x0002  /* RX Error Count IRQ Status                                    */
+#define        EPIS            0x0004  /* Error-Passive Mode IRQ Status                                */
+#define        BOIS            0x0008  /* Bus Off IRQ Status                                                   */
+#define        WUIS            0x0010  /* Wake-Up IRQ Status                                                   */
+#define        UIAIS           0x0020  /* Access To Unimplemented Address IRQ Status   */
+#define        AAIS            0x0040  /* Abort Acknowledge IRQ Status                                 */
+#define        RMLIS           0x0080  /* RX Message Lost IRQ Status                                   */
+#define        UCEIS           0x0100  /* Universal Counter Overflow IRQ Status                */
+#define        EXTIS           0x0200  /* External Trigger Output IRQ Status                   */
+#define        ADIS            0x0400  /* Access Denied IRQ Status                                             */
+
+/* CAN_GIF Masks                                                                                                                       */
+#define        EWTIF           0x0001  /* TX Error Count IRQ Flag                                              */
+#define        EWRIF           0x0002  /* RX Error Count IRQ Flag                                              */
+#define        EPIF            0x0004  /* Error-Passive Mode IRQ Flag                                  */
+#define        BOIF            0x0008  /* Bus Off IRQ Flag                                                             */
+#define        WUIF            0x0010  /* Wake-Up IRQ Flag                                                             */
+#define        UIAIF           0x0020  /* Access To Unimplemented Address IRQ Flag             */
+#define        AAIF            0x0040  /* Abort Acknowledge IRQ Flag                                   */
+#define        RMLIF           0x0080  /* RX Message Lost IRQ Flag                                             */
+#define        UCEIF           0x0100  /* Universal Counter Overflow IRQ Flag                  */
+#define        EXTIF           0x0200  /* External Trigger Output IRQ Flag                             */
+#define        ADIF            0x0400  /* Access Denied IRQ Flag                                               */
+
+/* CAN_UCCNF Masks                                                                                                                     */
+#define        UCCNF           0x000F  /* Universal Counter Mode                                               */
+#define UC_STAMP       0x0001  /*              Timestamp Mode                                                  */
+#define UC_WDOG                0x0002  /*              Watchdog Mode                                                   */
+#define UC_AUTOTX      0x0003  /*              Auto-Transmit Mode                                              */
+#define UC_ERROR       0x0006  /*              CAN Error Frame Count                                   */
+#define UC_OVER                0x0007  /*              CAN Overload Frame Count                                */
+#define UC_LOST                0x0008  /*              Arbitration Lost During TX Count                */
+#define UC_AA          0x0009  /*              TX Abort Count                                                  */
+#define UC_TA          0x000A  /*              TX Successful Count                                             */
+#define UC_REJECT      0x000B  /*              RX Message Rejected Count                               */
+#define UC_RML         0x000C  /*              RX Message Lost Count                                   */
+#define UC_RX          0x000D  /*              Total Successful RX Messages Count              */
+#define UC_RMP         0x000E  /*              Successful RX W/Matching ID Count               */
+#define UC_ALL         0x000F  /*              Correct Message On CAN Bus Line Count   */
+#define        UCRC            0x0020  /* Universal Counter Reload/Clear                               */
+#define        UCCT            0x0040  /* Universal Counter CAN Trigger                                */
+#define        UCE                     0x0080  /* Universal Counter Enable                                             */
+
+/* CAN_ESR Masks                                                                               */
+#define        ACKE            0x0004  /* Acknowledge Error            */
+#define        SER                     0x0008  /* Stuff Error                          */
+#define        CRCE            0x0010  /* CRC Error                            */
+#define        SA0                     0x0020  /* Stuck At Dominant Error      */
+#define        BEF                     0x0040  /* Bit Error Flag                       */
+#define        FER                     0x0080  /* Form Error Flag                      */
+
+/* CAN_EWR Masks                                                                                               */
+#define        EWLREC          0x00FF  /* RX Error Count Limit (For EWRIS)     */
+#define        EWLTEC          0xFF00  /* TX Error Count Limit (For EWTIS)     */
+
+/*  *******************  PIN CONTROL REGISTER MASKS  ************************/
+/* PORT_MUX Masks                                                                                                                      */
+#define        PJSE                    0x0001  /* Port J SPI/SPORT Enable                      */
+#define        PJSE_SPORT              0x0000  /*              Enable TFS0/DT0PRI                      */
+#define        PJSE_SPI                0x0001  /*              Enable SPI_SSEL3:2                      */
+
+#define        PJCE(x)                 (((x)&0x3)<<1)  /* Port J CAN/SPI/SPORT Enable          */
+#define        PJCE_SPORT              0x0000  /*              Enable DR0SEC/DT0SEC            */
+#define        PJCE_CAN                0x0002  /*              Enable CAN RX/TX                        */
+#define        PJCE_SPI                0x0004  /*              Enable SPI_SSEL7                        */
+
+#define        PFDE                    0x0008  /* Port F DMA Request Enable            */
+#define        PGDE_UART               0x0000  /*              Enable UART0 RX/TX                      */
+#define        PGDE_DMA                0x0008  /*              Enable DMAR1:0                          */
+
+#define        PFTE                    0x0010  /* Port F Timer Enable                          */
+#define        PFTE_UART               0x0000  /*              Enable UART1 RX/TX                      */
+#define        PFTE_TIMER              0x0010  /*              Enable TMR7:6                           */
+
+#define        PFS6E                   0x0020  /* Port F SPI SSEL 6 Enable                     */
+#define        PFS6E_TIMER             0x0000  /*              Enable TMR5                                     */
+#define        PFS6E_SPI               0x0020  /*              Enable SPI_SSEL6                        */
+
+#define        PFS5E                   0x0040  /* Port F SPI SSEL 5 Enable                     */
+#define        PFS5E_TIMER             0x0000  /*              Enable TMR4                                     */
+#define        PFS5E_SPI               0x0040  /*              Enable SPI_SSEL5                        */
+
+#define        PFS4E                   0x0080  /* Port F SPI SSEL 4 Enable                     */
+#define        PFS4E_TIMER             0x0000  /*              Enable TMR3                                     */
+#define        PFS4E_SPI               0x0080  /*              Enable SPI_SSEL4                        */
+
+#define        PFFE                    0x0100  /* Port F PPI Frame Sync Enable         */
+#define        PFFE_TIMER              0x0000  /*              Enable TMR2                                     */
+#define        PFFE_PPI                0x0100  /*              Enable PPI FS3                          */
+
+#define        PGSE                    0x0200  /* Port G SPORT1 Secondary Enable       */
+#define        PGSE_PPI                0x0000  /*              Enable PPI D9:8                         */
+#define        PGSE_SPORT              0x0200  /*              Enable DR1SEC/DT1SEC            */
+
+#define        PGRE                    0x0400  /* Port G SPORT1 Receive Enable         */
+#define        PGRE_PPI                0x0000  /*              Enable PPI D12:10                       */
+#define        PGRE_SPORT              0x0400  /*              Enable DR1PRI/RFS1/RSCLK1       */
+
+#define        PGTE                    0x0800  /* Port G SPORT1 Transmit Enable        */
+#define        PGTE_PPI                0x0000  /*              Enable PPI D15:13                       */
+#define        PGTE_SPORT              0x0800  /*              Enable DT1PRI/TFS1/TSCLK1       */
+
+/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
+/* HDMAx_CTL Masks                                                                                                             */
+#define        HMDMAEN         0x0001  /* Enable Handshake DMA 0/1                                     */
+#define        REP                     0x0002  /* HDMA Request Polarity                                        */
+#define        UTE                     0x0004  /* Urgency Threshold Enable                                     */
+#define        OIE                     0x0010  /* Overflow Interrupt Enable                            */
+#define        BDIE            0x0020  /* Block Done Interrupt Enable                          */
+#define        MBDI            0x0040  /* Mask Block Done IRQ If Pending ECNT          */
+#define        DRQ                     0x0300  /* HDMA Request Type                                            */
+#define        DRQ_NONE        0x0000  /*              No Request                                                      */
+#define        DRQ_SINGLE      0x0100  /*              Channels Request Single                         */
+#define        DRQ_MULTI       0x0200  /*              Channels Request Multi (Default)        */
+#define        DRQ_URGENT      0x0300  /*              Channels Request Multi Urgent           */
+#define        RBC                     0x1000  /* Reload BCNT With IBCNT                                       */
+#define        PS                      0x2000  /* HDMA Pin Status                                                      */
+#define        OI                      0x4000  /* Overflow Interrupt Generated                         */
+#define        BDI                     0x8000  /* Block Done Interrupt Generated                       */
+
+#endif                         /* _DEF_BF534_H */
diff --git a/include/asm-blackfin/mach-bf537/defBF537.h b/include/asm-blackfin/mach-bf537/defBF537.h
new file mode 100644 (file)
index 0000000..26f9c02
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * file:         include/asm-blackfin/mach-bf537/defbf537.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _DEF_BF537_H
+#define _DEF_BF537_H
+
+/*include all Core registers and bit definitions*/
+#include "defBF537.h"
+
+/*include core specific register pointer definitions*/
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/************************************************************************************
+** Define EMAC Section Unique to BF536/BF537
+*************************************************************************************/
+
+/* 10/100 Ethernet Controller  (0xFFC03000 - 0xFFC031FF)                                                                               */
+#define        EMAC_OPMODE                     0xFFC03000      /* Operating Mode Register                                                              */
+#define EMAC_ADDRLO                    0xFFC03004      /* Address Low (32 LSBs) Register                                               */
+#define EMAC_ADDRHI                    0xFFC03008      /* Address High (16 MSBs) Register                                              */
+#define EMAC_HASHLO                    0xFFC0300C      /* Multicast Hash Table Low (Bins 31-0) Register                */
+#define EMAC_HASHHI                    0xFFC03010      /* Multicast Hash Table High (Bins 63-32) Register              */
+#define EMAC_STAADD                    0xFFC03014      /* Station Management Address Register                                  */
+#define EMAC_STADAT                    0xFFC03018      /* Station Management Data Register                                     */
+#define EMAC_FLC                       0xFFC0301C      /* Flow Control Register                                                                */
+#define EMAC_VLAN1                     0xFFC03020      /* VLAN1 Tag Register                                                                   */
+#define EMAC_VLAN2                     0xFFC03024      /* VLAN2 Tag Register                                                                   */
+#define EMAC_WKUP_CTL          0xFFC0302C      /* Wake-Up Control/Status Register                                              */
+#define EMAC_WKUP_FFMSK0       0xFFC03030      /* Wake-Up Frame Filter 0 Byte Mask Register                    */
+#define EMAC_WKUP_FFMSK1       0xFFC03034      /* Wake-Up Frame Filter 1 Byte Mask Register                    */
+#define EMAC_WKUP_FFMSK2       0xFFC03038      /* Wake-Up Frame Filter 2 Byte Mask Register                    */
+#define EMAC_WKUP_FFMSK3       0xFFC0303C      /* Wake-Up Frame Filter 3 Byte Mask Register                    */
+#define EMAC_WKUP_FFCMD                0xFFC03040      /* Wake-Up Frame Filter Commands Register                               */
+#define EMAC_WKUP_FFOFF                0xFFC03044      /* Wake-Up Frame Filter Offsets Register                                */
+#define EMAC_WKUP_FFCRC0       0xFFC03048      /* Wake-Up Frame Filter 0,1 CRC-16 Register                             */
+#define EMAC_WKUP_FFCRC1       0xFFC0304C      /* Wake-Up Frame Filter 2,3 CRC-16 Register                             */
+
+#define        EMAC_SYSCTL                     0xFFC03060      /* EMAC System Control Register                                                 */
+#define EMAC_SYSTAT                    0xFFC03064      /* EMAC System Status Register                                                  */
+#define EMAC_RX_STAT           0xFFC03068      /* RX Current Frame Status Register                                             */
+#define EMAC_RX_STKY           0xFFC0306C      /* RX Sticky Frame Status Register                                              */
+#define EMAC_RX_IRQE           0xFFC03070      /* RX Frame Status Interrupt Enables Register                   */
+#define EMAC_TX_STAT           0xFFC03074      /* TX Current Frame Status Register                                             */
+#define EMAC_TX_STKY           0xFFC03078      /* TX Sticky Frame Status Register                                              */
+#define EMAC_TX_IRQE           0xFFC0307C      /* TX Frame Status Interrupt Enables Register                   */
+
+#define EMAC_MMC_CTL           0xFFC03080      /* MMC Counter Control Register                                                 */
+#define EMAC_MMC_RIRQS         0xFFC03084      /* MMC RX Interrupt Status Register                                             */
+#define EMAC_MMC_RIRQE         0xFFC03088      /* MMC RX Interrupt Enables Register                                    */
+#define EMAC_MMC_TIRQS         0xFFC0308C      /* MMC TX Interrupt Status Register                                             */
+#define EMAC_MMC_TIRQE         0xFFC03090      /* MMC TX Interrupt Enables Register                                    */
+
+#define EMAC_RXC_OK                    0xFFC03100      /* RX Frame Successful Count                                                    */
+#define EMAC_RXC_FCS           0xFFC03104      /* RX Frame FCS Failure Count                                                   */
+#define EMAC_RXC_ALIGN         0xFFC03108      /* RX Alignment Error Count                                                             */
+#define EMAC_RXC_OCTET         0xFFC0310C      /* RX Octets Successfully Received Count                                */
+#define EMAC_RXC_DMAOVF                0xFFC03110      /* Internal MAC Sublayer Error RX Frame Count                   */
+#define EMAC_RXC_UNICST                0xFFC03114      /* Unicast RX Frame Count                                                               */
+#define EMAC_RXC_MULTI         0xFFC03118      /* Multicast RX Frame Count                                                             */
+#define EMAC_RXC_BROAD         0xFFC0311C      /* Broadcast RX Frame Count                                                             */
+#define EMAC_RXC_LNERRI                0xFFC03120      /* RX Frame In Range Error Count                                                */
+#define EMAC_RXC_LNERRO                0xFFC03124      /* RX Frame Out Of Range Error Count                                    */
+#define EMAC_RXC_LONG          0xFFC03128      /* RX Frame Too Long Count                                                              */
+#define EMAC_RXC_MACCTL                0xFFC0312C      /* MAC Control RX Frame Count                                                   */
+#define EMAC_RXC_OPCODE                0xFFC03130      /* Unsupported Op-Code RX Frame Count                                   */
+#define EMAC_RXC_PAUSE         0xFFC03134      /* MAC Control Pause RX Frame Count                                             */
+#define EMAC_RXC_ALLFRM                0xFFC03138      /* Overall RX Frame Count                                                               */
+#define EMAC_RXC_ALLOCT                0xFFC0313C      /* Overall RX Octet Count                                                               */
+#define EMAC_RXC_TYPED         0xFFC03140      /* Type/Length Consistent RX Frame Count                                */
+#define EMAC_RXC_SHORT         0xFFC03144      /* RX Frame Fragment Count - Byte Count x < 64                  */
+#define EMAC_RXC_EQ64          0xFFC03148      /* Good RX Frame Count - Byte Count x = 64                              */
+#define EMAC_RXC_LT128         0xFFC0314C      /* Good RX Frame Count - Byte Count  64 <= x < 128              */
+#define EMAC_RXC_LT256         0xFFC03150      /* Good RX Frame Count - Byte Count 128 <= x < 256              */
+#define EMAC_RXC_LT512         0xFFC03154      /* Good RX Frame Count - Byte Count 256 <= x < 512              */
+#define EMAC_RXC_LT1024                0xFFC03158      /* Good RX Frame Count - Byte Count 512 <= x < 1024             */
+#define EMAC_RXC_GE1024                0xFFC0315C      /* Good RX Frame Count - Byte Count x >= 1024                   */
+
+#define EMAC_TXC_OK                    0xFFC03180      /* TX Frame Successful Count                                                    */
+#define EMAC_TXC_1COL          0xFFC03184      /* TX Frames Successful After Single Collision Count    */
+#define EMAC_TXC_GT1COL                0xFFC03188      /* TX Frames Successful After Multiple Collisions Count */
+#define EMAC_TXC_OCTET         0xFFC0318C      /* TX Octets Successfully Received Count                                */
+#define EMAC_TXC_DEFER         0xFFC03190      /* TX Frame Delayed Due To Busy Count                                   */
+#define EMAC_TXC_LATECL                0xFFC03194      /* Late TX Collisions Count                                                             */
+#define EMAC_TXC_XS_COL                0xFFC03198      /* TX Frame Failed Due To Excessive Collisions Count    */
+#define EMAC_TXC_DMAUND                0xFFC0319C      /* Internal MAC Sublayer Error TX Frame Count                   */
+#define EMAC_TXC_CRSERR                0xFFC031A0      /* Carrier Sense Deasserted During TX Frame Count               */
+#define EMAC_TXC_UNICST                0xFFC031A4      /* Unicast TX Frame Count                                                               */
+#define EMAC_TXC_MULTI         0xFFC031A8      /* Multicast TX Frame Count                                                             */
+#define EMAC_TXC_BROAD         0xFFC031AC      /* Broadcast TX Frame Count                                                             */
+#define EMAC_TXC_XS_DFR                0xFFC031B0      /* TX Frames With Excessive Deferral Count                              */
+#define EMAC_TXC_MACCTL                0xFFC031B4      /* MAC Control TX Frame Count                                                   */
+#define EMAC_TXC_ALLFRM                0xFFC031B8      /* Overall TX Frame Count                                                               */
+#define EMAC_TXC_ALLOCT                0xFFC031BC      /* Overall TX Octet Count                                                               */
+#define EMAC_TXC_EQ64          0xFFC031C0      /* Good TX Frame Count - Byte Count x = 64                              */
+#define EMAC_TXC_LT128         0xFFC031C4      /* Good TX Frame Count - Byte Count  64 <= x < 128              */
+#define EMAC_TXC_LT256         0xFFC031C8      /* Good TX Frame Count - Byte Count 128 <= x < 256              */
+#define EMAC_TXC_LT512         0xFFC031CC      /* Good TX Frame Count - Byte Count 256 <= x < 512              */
+#define EMAC_TXC_LT1024                0xFFC031D0      /* Good TX Frame Count - Byte Count 512 <= x < 1024             */
+#define EMAC_TXC_GE1024                0xFFC031D4      /* Good TX Frame Count - Byte Count x >= 1024                   */
+#define EMAC_TXC_ABORT         0xFFC031D8      /* Total TX Frames Aborted Count                                                */
+
+/* Listing for IEEE-Supported Count Registers                                                                                                                                  */
+#define FramesReceivedOK                               EMAC_RXC_OK     /* RX Frame Successful Count                                                    */
+#define FrameCheckSequenceErrors               EMAC_RXC_FCS    /* RX Frame FCS Failure Count                                                   */
+#define AlignmentErrors                                        EMAC_RXC_ALIGN  /* RX Alignment Error Count                                                             */
+#define OctetsReceivedOK                               EMAC_RXC_OCTET  /* RX Octets Successfully Received Count                                */
+#define FramesLostDueToIntMACRcvError  EMAC_RXC_DMAOVF /* Internal MAC Sublayer Error RX Frame Count                   */
+#define UnicastFramesReceivedOK                        EMAC_RXC_UNICST /* Unicast RX Frame Count                                                               */
+#define MulticastFramesReceivedOK              EMAC_RXC_MULTI  /* Multicast RX Frame Count                                                             */
+#define BroadcastFramesReceivedOK              EMAC_RXC_BROAD  /* Broadcast RX Frame Count                                                             */
+#define InRangeLengthErrors                            EMAC_RXC_LNERRI /* RX Frame In Range Error Count                                                */
+#define OutOfRangeLengthField                  EMAC_RXC_LNERRO /* RX Frame Out Of Range Error Count                                    */
+#define FrameTooLongErrors                             EMAC_RXC_LONG   /* RX Frame Too Long Count                                                              */
+#define MACControlFramesReceived               EMAC_RXC_MACCTL /* MAC Control RX Frame Count                                                   */
+#define UnsupportedOpcodesReceived             EMAC_RXC_OPCODE /* Unsupported Op-Code RX Frame Count                                   */
+#define PAUSEMACCtrlFramesReceived             EMAC_RXC_PAUSE  /* MAC Control Pause RX Frame Count                                             */
+#define FramesReceivedAll                              EMAC_RXC_ALLFRM /* Overall RX Frame Count                                                               */
+#define OctetsReceivedAll                              EMAC_RXC_ALLOCT /* Overall RX Octet Count                                                               */
+#define TypedFramesReceived                            EMAC_RXC_TYPED  /* Type/Length Consistent RX Frame Count                                */
+#define FramesLenLt64Received                  EMAC_RXC_SHORT  /* RX Frame Fragment Count - Byte Count x < 64                  */
+#define FramesLenEq64Received                  EMAC_RXC_EQ64   /* Good RX Frame Count - Byte Count x = 64                              */
+#define FramesLen65_127Received                        EMAC_RXC_LT128  /* Good RX Frame Count - Byte Count  64 <= x < 128              */
+#define FramesLen128_255Received               EMAC_RXC_LT256  /* Good RX Frame Count - Byte Count 128 <= x < 256              */
+#define FramesLen256_511Received               EMAC_RXC_LT512  /* Good RX Frame Count - Byte Count 256 <= x < 512              */
+#define FramesLen512_1023Received              EMAC_RXC_LT1024 /* Good RX Frame Count - Byte Count 512 <= x < 1024             */
+#define FramesLen1024_MaxReceived              EMAC_RXC_GE1024 /* Good RX Frame Count - Byte Count x >= 1024                   */
+
+#define FramesTransmittedOK                            EMAC_TXC_OK     /* TX Frame Successful Count                                                    */
+#define SingleCollisionFrames                  EMAC_TXC_1COL   /* TX Frames Successful After Single Collision Count    */
+#define MultipleCollisionFrames                        EMAC_TXC_GT1COL /* TX Frames Successful After Multiple Collisions Count */
+#define OctetsTransmittedOK                            EMAC_TXC_OCTET  /* TX Octets Successfully Received Count                                */
+#define FramesWithDeferredXmissions            EMAC_TXC_DEFER  /* TX Frame Delayed Due To Busy Count                                   */
+#define LateCollisions                                 EMAC_TXC_LATECL /* Late TX Collisions Count                                                             */
+#define FramesAbortedDueToXSColls              EMAC_TXC_XS_COL /* TX Frame Failed Due To Excessive Collisions Count    */
+#define FramesLostDueToIntMacXmitError EMAC_TXC_DMAUND /* Internal MAC Sublayer Error TX Frame Count                   */
+#define CarrierSenseErrors                             EMAC_TXC_CRSERR /* Carrier Sense Deasserted During TX Frame Count               */
+#define UnicastFramesXmittedOK                 EMAC_TXC_UNICST /* Unicast TX Frame Count                                                               */
+#define MulticastFramesXmittedOK               EMAC_TXC_MULTI  /* Multicast TX Frame Count                                                             */
+#define BroadcastFramesXmittedOK               EMAC_TXC_BROAD  /* Broadcast TX Frame Count                                                             */
+#define FramesWithExcessiveDeferral            EMAC_TXC_XS_DFR /* TX Frames With Excessive Deferral Count                              */
+#define MACControlFramesTransmitted            EMAC_TXC_MACCTL /* MAC Control TX Frame Count                                                   */
+#define FramesTransmittedAll                   EMAC_TXC_ALLFRM /* Overall TX Frame Count                                                               */
+#define OctetsTransmittedAll                   EMAC_TXC_ALLOCT /* Overall TX Octet Count                                                               */
+#define FramesLenEq64Transmitted               EMAC_TXC_EQ64   /* Good TX Frame Count - Byte Count x = 64                              */
+#define FramesLen65_127Transmitted             EMAC_TXC_LT128  /* Good TX Frame Count - Byte Count  64 <= x < 128              */
+#define FramesLen128_255Transmitted            EMAC_TXC_LT256  /* Good TX Frame Count - Byte Count 128 <= x < 256              */
+#define FramesLen256_511Transmitted            EMAC_TXC_LT512  /* Good TX Frame Count - Byte Count 256 <= x < 512              */
+#define FramesLen512_1023Transmitted   EMAC_TXC_LT1024 /* Good TX Frame Count - Byte Count 512 <= x < 1024             */
+#define FramesLen1024_MaxTransmitted   EMAC_TXC_GE1024 /* Good TX Frame Count - Byte Count x >= 1024                   */
+#define TxAbortedFrames                                        EMAC_TXC_ABORT  /* Total TX Frames Aborted Count                                                */
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer: All macros are intended to make C and Assembly code more readable.
+**                             Use these macros carefully, as any that do left shifts for field
+**                             depositing will result in the lower order bits being destroyed.  Any
+**                             macro that shifts left to properly position the bit-field should be
+**                             used as part of an OR to initialize a register and NOT as a dynamic
+**                             modifier UNLESS the lower order bits are saved and ORed back in when
+**                             the macro is used.
+*************************************************************************************/
+/************************  ETHERNET 10/100 CONTROLLER MASKS  ************************/
+/* EMAC_OPMODE Masks                                                                                                                           */
+#define        RE                      0x00000001      /* Receiver Enable                                                                      */
+#define        ASTP            0x00000002      /* Enable Automatic Pad Stripping On RX Frames          */
+#define        HU                      0x00000010      /* Hash Filter Unicast Address                                          */
+#define        HM                      0x00000020      /* Hash Filter Multicast Address                                        */
+#define        PAM                     0x00000040      /* Pass-All-Multicast Mode Enable                                       */
+#define        PR                      0x00000080      /* Promiscuous Mode Enable                                                      */
+#define        IFE                     0x00000100      /* Inverse Filtering Enable                                                     */
+#define        DBF                     0x00000200      /* Disable Broadcast Frame Reception                            */
+#define        PBF                     0x00000400      /* Pass Bad Frames Enable                                                       */
+#define        PSF                     0x00000800      /* Pass Short Frames Enable                                                     */
+#define        RAF                     0x00001000      /* Receive-All Mode                                                                     */
+#define        TE                      0x00010000      /* Transmitter Enable                                                           */
+#define        DTXPAD          0x00020000      /* Disable Automatic TX Padding                                         */
+#define        DTXCRC          0x00040000      /* Disable Automatic TX CRC Generation                          */
+#define        DC                      0x00080000      /* Deferral Check                                                                       */
+#define        BOLMT           0x00300000      /* Back-Off Limit                                                                       */
+#define        BOLMT_10        0x00000000      /*              10-bit range                                                            */
+#define        BOLMT_8         0x00100000      /*              8-bit range                                                                     */
+#define        BOLMT_4         0x00200000      /*              4-bit range                                                                     */
+#define        BOLMT_1         0x00300000      /*              1-bit range                                                                     */
+#define        DRTY            0x00400000      /* Disable TX Retry On Collision                                        */
+#define        LCTRE           0x00800000      /* Enable TX Retry On Late Collision                            */
+#define        RMII            0x01000000      /* RMII/MII* Mode                                                                       */
+#define        RMII_10         0x02000000      /* Speed Select for RMII Port (10MBit/100MBit*)         */
+#define        FDMODE          0x04000000      /* Duplex Mode Enable (Full/Half*)                                      */
+#define        LB                      0x08000000      /* Internal Loopback Enable                                                     */
+#define        DRO                     0x10000000      /* Disable Receive Own Frames (Half-Duplex Mode)        */
+
+/* EMAC_STAADD Masks                                                                                                                           */
+#define        STABUSY         0x00000001      /* Initiate Station Mgt Reg Access / STA Busy Stat      */
+#define        STAOP           0x00000002      /* Station Management Operation Code (Write/Read*)      */
+#define        STADISPRE       0x00000004      /* Disable Preamble Generation                                          */
+#define        STAIE           0x00000008      /* Station Mgt. Transfer Done Interrupt Enable          */
+#define        REGAD           0x000007C0      /* STA Register Address                                                         */
+#define        PHYAD           0x0000F800      /* PHY Device Address                                                           */
+
+#define        SET_REGAD(x)    (((x)&0x1F)<<  6 )      /* Set STA Register Address                             */
+#define        SET_PHYAD(x)    (((x)&0x1F)<< 11 )      /* Set PHY Device Address                               */
+
+/* EMAC_STADAT Mask                                                                                    */
+#define        STADATA         0x0000FFFF      /* Station Management Data      */
+
+/* EMAC_FLC Masks                                                                                                                                      */
+#define        FLCBUSY         0x00000001      /* Send Flow Ctrl Frame / Flow Ctrl Busy Status         */
+#define        FLCE            0x00000002      /* Flow Control Enable                                                          */
+#define        PCF                     0x00000004      /* Pass Control Frames                                                          */
+#define        BKPRSEN         0x00000008      /* Enable Backpressure                                                          */
+#define        FLCPAUSE        0xFFFF0000      /* Pause Time                                                                           */
+
+#define        SET_FLCPAUSE(x) (((x)&0xFFFF)<< 16)     /* Set Pause Time                                               */
+
+/* EMAC_WKUP_CTL Masks                                                                                                                         */
+#define        CAPWKFRM        0x00000001      /* Capture Wake-Up Frames                                                       */
+#define        MPKE            0x00000002      /* Magic Packet Enable                                                          */
+#define        RWKE            0x00000004      /* Remote Wake-Up Frame Enable                                          */
+#define        GUWKE           0x00000008      /* Global Unicast Wake Enable                                           */
+#define        MPKS            0x00000020      /* Magic Packet Received Status                                         */
+#define        RWKS            0x00000F00      /* Wake-Up Frame Received Status, Filters 3:0           */
+
+/* EMAC_WKUP_FFCMD Masks                                                                                                                       */
+#define        WF0_E           0x00000001      /* Enable Wake-Up Filter 0                                                      */
+#define        WF0_T           0x00000008      /* Wake-Up Filter 0 Addr Type (Multicast/Unicast*)      */
+#define        WF1_E           0x00000100      /* Enable Wake-Up Filter 1                                                      */
+#define        WF1_T           0x00000800      /* Wake-Up Filter 1 Addr Type (Multicast/Unicast*)      */
+#define        WF2_E           0x00010000      /* Enable Wake-Up Filter 2                                                      */
+#define        WF2_T           0x00080000      /* Wake-Up Filter 2 Addr Type (Multicast/Unicast*)      */
+#define        WF3_E           0x01000000      /* Enable Wake-Up Filter 3                                                      */
+#define        WF3_T           0x08000000      /* Wake-Up Filter 3 Addr Type (Multicast/Unicast*)      */
+
+/* EMAC_WKUP_FFOFF Masks                                                                                                                       */
+#define        WF0_OFF         0x000000FF      /* Wake-Up Filter 0 Pattern Offset                                      */
+#define        WF1_OFF         0x0000FF00      /* Wake-Up Filter 1 Pattern Offset                                      */
+#define        WF2_OFF         0x00FF0000      /* Wake-Up Filter 2 Pattern Offset                                      */
+#define        WF3_OFF         0xFF000000      /* Wake-Up Filter 3 Pattern Offset                                      */
+
+#define        SET_WF0_OFF(x) (((x)&0xFF)<<  0 )       /* Set Wake-Up Filter 0 Byte Offset           */
+#define        SET_WF1_OFF(x) (((x)&0xFF)<<  8 )       /* Set Wake-Up Filter 1 Byte Offset           */
+#define        SET_WF2_OFF(x) (((x)&0xFF)<< 16 )       /* Set Wake-Up Filter 2 Byte Offset           */
+#define        SET_WF3_OFF(x) (((x)&0xFF)<< 24 )       /* Set Wake-Up Filter 3 Byte Offset           */
+/* Set ALL Offsets                                                                                                                                     */
+#define        SET_WF_OFFS(x0,x1,x2,x3)        (SET_WF0_OFF((x0))|SET_WF1_OFF((x1))|SET_WF2_OFF((x2))|SET_WF3_OFF((x3)))
+
+/* EMAC_WKUP_FFCRC0 Masks                                                                                                                      */
+#define        WF0_CRC         0x0000FFFF      /* Wake-Up Filter 0 Pattern CRC                                         */
+#define        WF1_CRC         0xFFFF0000      /* Wake-Up Filter 1 Pattern CRC                                         */
+
+#define        SET_WF0_CRC(x) (((x)&0xFFFF)<<   0 )    /* Set Wake-Up Filter 0 Target CRC         */
+#define        SET_WF1_CRC(x) (((x)&0xFFFF)<<  16 )    /* Set Wake-Up Filter 1 Target CRC         */
+
+/* EMAC_WKUP_FFCRC1 Masks                                                                                                                      */
+#define        WF2_CRC         0x0000FFFF      /* Wake-Up Filter 2 Pattern CRC                                         */
+#define        WF3_CRC         0xFFFF0000      /* Wake-Up Filter 3 Pattern CRC                                         */
+
+#define        SET_WF2_CRC(x) (((x)&0xFFFF)<<   0 )    /* Set Wake-Up Filter 2 Target CRC         */
+#define        SET_WF3_CRC(x) (((x)&0xFFFF)<<  16 )    /* Set Wake-Up Filter 3 Target CRC         */
+
+/* EMAC_SYSCTL Masks                                                                                                                           */
+#define        PHYIE           0x00000001      /* PHY_INT Interrupt Enable                                                     */
+#define        RXDWA           0x00000002      /* Receive Frame DMA Word Alignment (Odd/Even*)         */
+#define        RXCKS           0x00000004      /* Enable RX Frame TCP/UDP Checksum Computation         */
+#define        MDCDIV          0x00003F00      /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))]          */
+
+#define        SET_MDCDIV(x)   (((x)&0x3F)<< 8)        /* Set MDC Clock Divisor                                */
+
+/* EMAC_SYSTAT Masks                                                                                                                   */
+#define        PHYINT          0x00000001      /* PHY_INT Interrupt Status                                             */
+#define        MMCINT          0x00000002      /* MMC Counter Interrupt Status                                 */
+#define        RXFSINT         0x00000004      /* RX Frame-Status Interrupt Status                             */
+#define        TXFSINT         0x00000008      /* TX Frame-Status Interrupt Status                             */
+#define        WAKEDET         0x00000010      /* Wake-Up Detected Status                                              */
+#define        RXDMAERR        0x00000020      /* RX DMA Direction Error Status                                */
+#define        TXDMAERR        0x00000040      /* TX DMA Direction Error Status                                */
+#define        STMDONE         0x00000080      /* Station Mgt. Transfer Done Interrupt Status  */
+
+/* EMAC_RX_STAT, EMAC_RX_STKY, and EMAC_RX_IRQE Masks                                                  */
+#define        RX_FRLEN        0x000007FF      /* Frame Length In Bytes                                                */
+#define        RX_COMP         0x00001000      /* RX Frame Complete                                                    */
+#define        RX_OK           0x00002000      /* RX Frame Received With No Errors                             */
+#define        RX_LONG         0x00004000      /* RX Frame Too Long Error                                              */
+#define        RX_ALIGN        0x00008000      /* RX Frame Alignment Error                                             */
+#define        RX_CRC          0x00010000      /* RX Frame CRC Error                                                   */
+#define        RX_LEN          0x00020000      /* RX Frame Length Error                                                */
+#define        RX_FRAG         0x00040000      /* RX Frame Fragment Error                                              */
+#define        RX_ADDR         0x00080000      /* RX Frame Address Filter Failed Error                 */
+#define        RX_DMAO         0x00100000      /* RX Frame DMA Overrun Error                                   */
+#define        RX_PHY          0x00200000      /* RX Frame PHY Error                                                   */
+#define        RX_LATE         0x00400000      /* RX Frame Late Collision Error                                */
+#define        RX_RANGE        0x00800000      /* RX Frame Length Field Out of Range Error             */
+#define        RX_MULTI        0x01000000      /* RX Multicast Frame Indicator                                 */
+#define        RX_BROAD        0x02000000      /* RX Broadcast Frame Indicator                                 */
+#define        RX_CTL          0x04000000      /* RX Control Frame Indicator                                   */
+#define        RX_UCTL         0x08000000      /* Unsupported RX Control Frame Indicator               */
+#define        RX_TYPE         0x10000000      /* RX Typed Frame Indicator                                             */
+#define        RX_VLAN1        0x20000000      /* RX VLAN1 Frame Indicator                                             */
+#define        RX_VLAN2        0x40000000      /* RX VLAN2 Frame Indicator                                             */
+#define        RX_ACCEPT       0x80000000      /* RX Frame Accepted Indicator                                  */
+
+/*  EMAC_TX_STAT, EMAC_TX_STKY, and EMAC_TX_IRQE Masks                                                 */
+#define        TX_COMP         0x00000001      /* TX Frame Complete                                                    */
+#define        TX_OK           0x00000002      /* TX Frame Sent With No Errors                                 */
+#define        TX_ECOLL        0x00000004      /* TX Frame Excessive Collision Error                   */
+#define        TX_LATE         0x00000008      /* TX Frame Late Collision Error                                */
+#define        TX_DMAU         0x00000010      /* TX Frame DMA Underrun Error (STAT)                   */
+#define        TX_MACE         0x00000010      /* Internal MAC Error Detected (STKY and IRQE)  */
+#define        TX_EDEFER       0x00000020      /* TX Frame Excessive Deferral Error                    */
+#define        TX_BROAD        0x00000040      /* TX Broadcast Frame Indicator                                 */
+#define        TX_MULTI        0x00000080      /* TX Multicast Frame Indicator                                 */
+#define        TX_CCNT         0x00000F00      /* TX Frame Collision Count                                             */
+#define        TX_DEFER        0x00001000      /* TX Frame Deferred Indicator                                  */
+#define        TX_CRS          0x00002000      /* TX Frame Carrier Sense Not Asserted Error    */
+#define        TX_LOSS         0x00004000      /* TX Frame Carrier Lost During TX Error                */
+#define        TX_RETRY        0x00008000      /* TX Frame Successful After Retry                              */
+#define        TX_FRLEN        0x07FF0000      /* TX Frame Length (Bytes)                                              */
+
+/* EMAC_MMC_CTL Masks                                                                                                                  */
+#define        RSTC            0x00000001      /* Reset All Counters                                                   */
+#define        CROLL           0x00000002      /* Counter Roll-Over Enable                                             */
+#define        CCOR            0x00000004      /* Counter Clear-On-Read Mode Enable                    */
+#define        MMCE            0x00000008      /* Enable MMC Counter Operation                                 */
+
+/* EMAC_MMC_RIRQS and EMAC_MMC_RIRQE Masks                                                                                     */
+#define        RX_OK_CNT               0x00000001      /* RX Frames Received With No Errors                    */
+#define        RX_FCS_CNT              0x00000002      /* RX Frames W/Frame Check Sequence Errors              */
+#define        RX_ALIGN_CNT    0x00000004      /* RX Frames With Alignment Errors                              */
+#define        RX_OCTET_CNT    0x00000008      /* RX Octets Received OK                                                */
+#define        RX_LOST_CNT             0x00000010      /* RX Frames Lost Due To Internal MAC RX Error  */
+#define        RX_UNI_CNT              0x00000020      /* Unicast RX Frames Received OK                                */
+#define        RX_MULTI_CNT    0x00000040      /* Multicast RX Frames Received OK                              */
+#define        RX_BROAD_CNT    0x00000080      /* Broadcast RX Frames Received OK                              */
+#define        RX_IRL_CNT              0x00000100      /* RX Frames With In-Range Length Errors                */
+#define        RX_ORL_CNT              0x00000200      /* RX Frames With Out-Of-Range Length Errors    */
+#define        RX_LONG_CNT             0x00000400      /* RX Frames With Frame Too Long Errors                 */
+#define        RX_MACCTL_CNT   0x00000800      /* MAC Control RX Frames Received                               */
+#define        RX_OPCODE_CTL   0x00001000      /* Unsupported Op-Code RX Frames Received               */
+#define        RX_PAUSE_CNT    0x00002000      /* PAUSEMAC Control RX Frames Received                  */
+#define        RX_ALLF_CNT             0x00004000      /* All RX Frames Received                                               */
+#define        RX_ALLO_CNT             0x00008000      /* All RX Octets Received                                               */
+#define        RX_TYPED_CNT    0x00010000      /* Typed RX Frames Received                                             */
+#define        RX_SHORT_CNT    0x00020000      /* RX Frame Fragments (< 64 Bytes) Received             */
+#define        RX_EQ64_CNT             0x00040000      /* 64-Byte RX Frames Received                                   */
+#define        RX_LT128_CNT    0x00080000      /* 65-127-Byte RX Frames Received                               */
+#define        RX_LT256_CNT    0x00100000      /* 128-255-Byte RX Frames Received                              */
+#define        RX_LT512_CNT    0x00200000      /* 256-511-Byte RX Frames Received                              */
+#define        RX_LT1024_CNT   0x00400000      /* 512-1023-Byte RX Frames Received                             */
+#define        RX_GE1024_CNT   0x00800000      /* 1024-Max-Byte RX Frames Received                             */
+
+/* EMAC_MMC_TIRQS and EMAC_MMC_TIRQE Masks                                                                                     */
+#define        TX_OK_CNT               0x00000001      /* TX Frames Sent OK                                                    */
+#define        TX_SCOLL_CNT    0x00000002      /* TX Frames With Single Collisions                             */
+#define        TX_MCOLL_CNT    0x00000004      /* TX Frames With Multiple Collisions                   */
+#define        TX_OCTET_CNT    0x00000008      /* TX Octets Sent OK                                                    */
+#define        TX_DEFER_CNT    0x00000010      /* TX Frames With Deferred Transmission                 */
+#define        TX_LATE_CNT             0x00000020      /* TX Frames With Late Collisions                               */
+#define        TX_ABORTC_CNT   0x00000040      /* TX Frames Aborted Due To Excess Collisions   */
+#define        TX_LOST_CNT             0x00000080      /* TX Frames Lost Due To Internal MAC TX Error  */
+#define        TX_CRS_CNT              0x00000100      /* TX Frames With Carrier Sense Errors                  */
+#define        TX_UNI_CNT              0x00000200      /* Unicast TX Frames Sent                                               */
+#define        TX_MULTI_CNT    0x00000400      /* Multicast TX Frames Sent                                             */
+#define        TX_BROAD_CNT    0x00000800      /* Broadcast TX Frames Sent                                             */
+#define        TX_EXDEF_CTL    0x00001000      /* TX Frames With Excessive Deferral                    */
+#define        TX_MACCTL_CNT   0x00002000      /* MAC Control TX Frames Sent                                   */
+#define        TX_ALLF_CNT             0x00004000      /* All TX Frames Sent                                                   */
+#define        TX_ALLO_CNT             0x00008000      /* All TX Octets Sent                                                   */
+#define        TX_EQ64_CNT             0x00010000      /* 64-Byte TX Frames Sent                                               */
+#define        TX_LT128_CNT    0x00020000      /* 65-127-Byte TX Frames Sent                                   */
+#define        TX_LT256_CNT    0x00040000      /* 128-255-Byte TX Frames Sent                                  */
+#define        TX_LT512_CNT    0x00080000      /* 256-511-Byte TX Frames Sent                                  */
+#define        TX_LT1024_CNT   0x00100000      /* 512-1023-Byte TX Frames Sent                                 */
+#define        TX_GE1024_CNT   0x00200000      /* 1024-Max-Byte TX Frames Sent                                 */
+#define        TX_ABORT_CNT    0x00400000      /* TX Frames Aborted                                                    */
+
+#endif                         /* _DEF_BF537_H */
diff --git a/include/asm-blackfin/mach-bf537/dma.h b/include/asm-blackfin/mach-bf537/dma.h
new file mode 100644 (file)
index 0000000..7a96404
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * file:         include/asm-blackfin/mach-bf537/dma.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define MAX_BLACKFIN_DMA_CHANNEL 16
+
+#define CH_PPI                             0
+#define CH_EMAC_RX                 1
+#define CH_EMAC_TX                 2
+#define CH_SPORT0_RX           3
+#define CH_SPORT0_TX           4
+#define CH_SPORT1_RX           5
+#define CH_SPORT1_TX           6
+#define CH_SPI                             7
+#define CH_UART0_RX            8
+#define CH_UART0_TX            9
+#define CH_UART1_RX            10
+#define CH_UART1_TX            11
+
+#define CH_MEM_STREAM0_DEST    12       /* TX */
+#define CH_MEM_STREAM0_SRC     13       /* RX */
+#define CH_MEM_STREAM1_DEST    14       /* TX */
+#define CH_MEM_STREAM1_SRC     15       /* RX */
+
+#endif
diff --git a/include/asm-blackfin/mach-bf537/irq.h b/include/asm-blackfin/mach-bf537/irq.h
new file mode 100644 (file)
index 0000000..8af2a83
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * file:         include/asm-blackfin/mach-bf537/irq.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF537_IRQ_H_
+#define _BF537_IRQ_H_
+
+/*
+ * Interrupt source definitions
+             Event Source    Core Event Name
+Core        Emulation               **
+ Events         (highest priority)  EMU         0
+            Reset                   RST         1
+            NMI                     NMI         2
+            Exception               EVX         3
+            Reserved                --          4
+            Hardware Error          IVHW        5
+            Core Timer              IVTMR       6 *
+
+.....
+
+            Software Interrupt 1    IVG14       31
+            Software Interrupt 2    --
+                 (lowest priority)  IVG15       32 *
+ */
+
+#define SYS_IRQS        41
+#define NR_PERI_INTS    32
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU             0  /*Emulation */
+#define IRQ_RST             1  /*reset */
+#define IRQ_NMI             2  /*Non Maskable */
+#define IRQ_EVX             3  /*Exception */
+#define IRQ_UNUSED          4  /*- unused interrupt*/
+#define IRQ_HWERR           5  /*Hardware Error */
+#define IRQ_CORETMR         6  /*Core timer */
+
+#define IRQ_PLL_WAKEUP      7  /*PLL Wakeup Interrupt */
+#define IRQ_DMA_ERROR       8  /*DMA Error (general) */
+#define IRQ_GENERIC_ERROR   9  /*GENERIC Error Interrupt */
+#define IRQ_RTC             10 /*RTC Interrupt */
+#define IRQ_PPI             11 /*DMA0 Interrupt (PPI) */
+#define IRQ_SPORT0_RX       12 /*DMA3 Interrupt (SPORT0 RX) */
+#define IRQ_SPORT0_TX       13 /*DMA4 Interrupt (SPORT0 TX) */
+#define IRQ_SPORT1_RX       14 /*DMA5 Interrupt (SPORT1 RX) */
+#define IRQ_SPORT1_TX       15 /*DMA6 Interrupt (SPORT1 TX) */
+#define IRQ_TWI             16 /*TWI Interrupt */
+#define IRQ_SPI             17 /*DMA7 Interrupt (SPI) */
+#define IRQ_UART0_RX        18 /*DMA8 Interrupt (UART0 RX) */
+#define IRQ_UART0_TX        19 /*DMA9 Interrupt (UART0 TX) */
+#define IRQ_UART1_RX        20 /*DMA10 Interrupt (UART1 RX) */
+#define IRQ_UART1_TX        21 /*DMA11 Interrupt (UART1 TX) */
+#define IRQ_CAN_RX          22 /*CAN Receive Interrupt */
+#define IRQ_CAN_TX          23 /*CAN Transmit Interrupt */
+#define IRQ_MAC_RX          24 /*DMA1 (Ethernet RX) Interrupt */
+#define IRQ_MAC_TX          25 /*DMA2 (Ethernet TX) Interrupt */
+#define IRQ_TMR0            26 /*Timer 0 */
+#define IRQ_TMR1            27 /*Timer 1 */
+#define IRQ_TMR2            28 /*Timer 2 */
+#define IRQ_TMR3            29 /*Timer 3 */
+#define IRQ_TMR4            30 /*Timer 4 */
+#define IRQ_TMR5            31 /*Timer 5 */
+#define IRQ_TMR6            32 /*Timer 6 */
+#define IRQ_TMR7            33 /*Timer 7 */
+#define IRQ_PROG_INTA       34 /* PF Ports F&G (PF15:0) Interrupt A */
+#define IRQ_PORTG_INTB      35 /* PF Port G (PF15:0) Interrupt B */
+#define IRQ_MEM_DMA0        36 /*(Memory DMA Stream 0) */
+#define IRQ_MEM_DMA1        37 /*(Memory DMA Stream 1) */
+#define IRQ_PROG_INTB      38  /* PF Ports F (PF15:0) Interrupt B */
+#define IRQ_WATCH           38 /*Watch Dog Timer */
+#define IRQ_SW_INT1         40 /*Software Int 1 */
+#define IRQ_SW_INT2         41 /*Software Int 2 (reserved for SYSCALL) */
+
+#define IRQ_PPI_ERROR       42 /*PPI Error Interrupt */
+#define IRQ_CAN_ERROR       43 /*CAN Error Interrupt */
+#define IRQ_MAC_ERROR       44 /*PPI Error Interrupt */
+#define IRQ_SPORT0_ERROR    45 /*SPORT0 Error Interrupt */
+#define IRQ_SPORT1_ERROR    46 /*SPORT1 Error Interrupt */
+#define IRQ_SPI_ERROR       47 /*SPI Error Interrupt */
+#define IRQ_UART0_ERROR     48 /*UART Error Interrupt */
+#define IRQ_UART1_ERROR     49 /*UART Error Interrupt */
+
+#define IRQ_PF0         50
+#define IRQ_PF1         51
+#define IRQ_PF2         52
+#define IRQ_PF3         53
+#define IRQ_PF4         54
+#define IRQ_PF5         55
+#define IRQ_PF6         56
+#define IRQ_PF7         57
+#define IRQ_PF8         58
+#define IRQ_PF9         59
+#define IRQ_PF10        60
+#define IRQ_PF11        61
+#define IRQ_PF12        62
+#define IRQ_PF13        63
+#define IRQ_PF14        64
+#define IRQ_PF15        65
+
+#define IRQ_PG0         66
+#define IRQ_PG1         67
+#define IRQ_PG2         68
+#define IRQ_PG3         69
+#define IRQ_PG4         70
+#define IRQ_PG5         71
+#define IRQ_PG6         72
+#define IRQ_PG7         73
+#define IRQ_PG8         74
+#define IRQ_PG9         75
+#define IRQ_PG10        76
+#define IRQ_PG11        77
+#define IRQ_PG12        78
+#define IRQ_PG13        79
+#define IRQ_PG14        80
+#define IRQ_PG15        81
+
+#define IRQ_PH0         82
+#define IRQ_PH1         83
+#define IRQ_PH2         84
+#define IRQ_PH3         85
+#define IRQ_PH4         86
+#define IRQ_PH5         87
+#define IRQ_PH6         88
+#define IRQ_PH7         89
+#define IRQ_PH8         90
+#define IRQ_PH9         91
+#define IRQ_PH10        92
+#define IRQ_PH11        93
+#define IRQ_PH12        94
+#define IRQ_PH13        95
+#define IRQ_PH14        96
+#define IRQ_PH15        97
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define NR_IRQS     (IRQ_PH15+1)
+#else
+#define NR_IRQS     (IRQ_UART1_ERROR+1)
+#endif
+
+#define IVG7            7
+#define IVG8            8
+#define IVG9            9
+#define IVG10           10
+#define IVG11           11
+#define IVG12           12
+#define IVG13           13
+#define IVG14           14
+#define IVG15           15
+
+/* IAR0 BIT FIELDS*/
+#define IRQ_PLL_WAKEUP_POS  0
+#define IRQ_DMA_ERROR_POS   4
+#define IRQ_ERROR_POS       8
+#define IRQ_RTC_POS         12
+#define IRQ_PPI_POS         16
+#define IRQ_SPORT0_RX_POS   20
+#define IRQ_SPORT0_TX_POS   24
+#define IRQ_SPORT1_RX_POS   28
+
+/* IAR1 BIT FIELDS*/
+#define IRQ_SPORT1_TX_POS   0
+#define IRQ_TWI_POS         4
+#define IRQ_SPI_POS         8
+#define IRQ_UART0_RX_POS    12
+#define IRQ_UART0_TX_POS    16
+#define IRQ_UART1_RX_POS    20
+#define IRQ_UART1_TX_POS    24
+#define IRQ_CAN_RX_POS      28
+
+/* IAR2 BIT FIELDS*/
+#define IRQ_CAN_TX_POS      0
+#define IRQ_MAC_RX_POS      4
+#define IRQ_MAC_TX_POS      8
+#define IRQ_TMR0_POS        12
+#define IRQ_TMR1_POS        16
+#define IRQ_TMR2_POS        20
+#define IRQ_TMR3_POS        24
+#define IRQ_TMR4_POS        28
+
+/* IAR3 BIT FIELDS*/
+#define IRQ_TMR5_POS        0
+#define IRQ_TMR6_POS        4
+#define IRQ_TMR7_POS        8
+#define IRQ_PROG_INTA_POS   12
+#define IRQ_PORTG_INTB_POS   16
+#define IRQ_MEM_DMA0_POS    20
+#define IRQ_MEM_DMA1_POS    24
+#define IRQ_WATCH_POS       28
+
+#endif                         /* _BF537_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf537/mem_init.h b/include/asm-blackfin/mach-bf537/mem_init.h
new file mode 100644 (file)
index 0000000..9ad979d
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * File:         include/asm-blackfin/mach-bf537/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_MT48LC16M8A2TG_75 || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC32M8A2_75)
+#if (CONFIG_SCLK_HZ > 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_7
+#define SDRAM_tRAS_num  7
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_6
+#define SDRAM_tRAS_num  6
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_5
+#define SDRAM_tRAS_num  5
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  4
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_2
+#define SDRAM_tRAS_num  2
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ <= 29850746)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_1
+#define SDRAM_tRAS_num  1
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#endif
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC16M8A2TG_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   4096       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC32M8A2_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_GENERIC_BOARD)
+  /*SDRAM INFORMATION: Modify this for your board */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_SIZE == 128)
+#define SDRAM_SIZE      EBSZ_128
+#endif
+#if (CONFIG_MEM_SIZE == 64)
+#define SDRAM_SIZE      EBSZ_64
+#endif
+#if (CONFIG_MEM_SIZE == 32)
+#define SDRAM_SIZE      EBSZ_32
+#endif
+#if (CONFIG_MEM_SIZE == 16)
+#define SDRAM_SIZE      EBSZ_16
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 11)
+#define SDRAM_WIDTH     EBCAW_11
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 10)
+#define SDRAM_WIDTH     EBCAW_10
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 9)
+#define SDRAM_WIDTH     EBCAW_9
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 8)
+#define SDRAM_WIDTH     EBCAW_8
+#endif
+
+#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EBE)
+
+/* Equation from section 17 (p17-46) of BF533 HRM */
+#define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
+
+/* Enable SCLK Out */
+#define mem_SDGCTL        (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF       1
+#else
+#define CLKIN_HALF       0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS      1
+#else
+#define PLL_BYPASS       0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT  ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT  ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT   ((CONFIG_FLASH_SPEED_BHT  * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST   ((CONFIG_FLASH_SPEED_BST  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT   ((CONFIG_FLASH_SPEED_BTT  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0  \
+       (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+        flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf537/mem_map.h b/include/asm-blackfin/mach-bf537/mem_map.h
new file mode 100644 (file)
index 0000000..2a808c1
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * file:         include/asm-blackfin/mach-bf537/mem_map.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     Memory MAP Common header file for blackfin BF537/6/4 of processors.
+ * rev:
+ *
+ * modified:
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MEM_MAP_537_H_
+#define _MEM_MAP_537_H_
+
+#define COREMMR_BASE           0xFFE00000       /* Core MMRs */
+#define SYSMMR_BASE            0xFFC00000       /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE       0x20300000       /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE       0x00100000      /* 1M */
+#define ASYNC_BANK2_BASE       0x20200000       /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE       0x00100000      /* 1M */
+#define ASYNC_BANK1_BASE       0x20100000       /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE       0x00100000      /* 1M */
+#define ASYNC_BANK0_BASE       0x20000000       /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE       0x00100000      /* 1M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START         0xEF000000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF537 processors */
+
+#ifdef CONFIG_BLKFIN_CACHE
+#define BLKFIN_ICACHESIZE      (16*1024)
+#else
+#define BLKFIN_ICACHESIZE      (0*1024)
+#endif
+
+
+#ifdef CONFIG_BF537
+#define L1_CODE_START       0xFFA00000
+#define L1_DATA_A_START     0xFF800000
+#define L1_DATA_B_START     0xFF900000
+
+#define L1_CODE_LENGTH      0xC000
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x8000
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+
+#endif /*CONFIG_BF537*/
+
+/* Memory Map for ADSP-BF536 processors */
+
+#ifdef CONFIG_BF536
+#define L1_CODE_START       0xFFA00000
+#define L1_DATA_A_START     0xFF804000
+#define L1_DATA_B_START     0xFF904000
+
+#define L1_CODE_LENGTH      0xC000
+
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x4000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x4000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x4000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x4000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x4000
+#define L1_DATA_B_LENGTH      0x4000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+
+#endif
+
+/* Memory Map for ADSP-BF534 processors */
+
+#ifdef CONFIG_BF534
+#define L1_CODE_START       0xFFA00000
+#define L1_DATA_A_START     0xFF800000
+#define L1_DATA_B_START     0xFF900000
+
+#define L1_CODE_LENGTH      0xC000
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x8000
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+
+#endif
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
+#define L1_SCRATCH_START       0xFFB00000
+#define L1_SCRATCH_LENGTH      0x1000
+#endif
+
+#endif                         /* _MEM_MAP_537_H_ */
diff --git a/include/asm-blackfin/mach-bf561/anomaly.h b/include/asm-blackfin/mach-bf561/anomaly.h
new file mode 100644 (file)
index 0000000..f5b32d6
--- /dev/null
@@ -0,0 +1,184 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf561/anomaly.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This file shoule be up to date with:
+ *  - Revision L, 10Aug2006; ADSP-BF561 Silicon Anomaly List
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+
+/* We do not support 0.1 or 0.4 silicon - sorry */
+#if (defined(CONFIG_BF_REV_0_1) || defined(CONFIG_BF_REV_0_2) || defined(CONFIG_BF_REV_0_4))
+#error Kernel will not work on BF561 Version 0.1, 0.2, or 0.4
+#endif
+
+/* Issues that are common to 0.5 and  0.3 silicon */
+#if  (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_3))
+#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
+                            slot1 and store of a P register in slot 2 is not
+                            supported */
+#define ANOMALY_05000099 /* UART Line Status Register (UART_LSR) bits are not
+                            updated at the same time. */
+#define ANOMALY_05000120 /* Testset instructions restricted to 32-bit aligned
+                            memory locations */
+#define ANOMALY_05000122 /* Rx.H cannot be used to access 16-bit System MMR
+                            registers */
+#define ANOMALY_05000127 /* Signbits instruction not functional under certain
+                            conditions */
+#define ANOMALY_05000149 /* IMDMA S1/D1 channel may stall */
+#define ANOMALY_05000166 /* PPI Data Lengths Between 8 and 16 do not zero out
+                            upper bits */
+#define ANOMALY_05000167 /* Turning Serial Ports on With External Frame Syncs */
+#define ANOMALY_05000180 /* PPI_DELAY not functional in PPI modes with 0 frame
+                            syncs */
+#define ANOMALY_05000182 /* IMDMA does not operate to full speed for 600MHz
+                            and higher devices */
+#define ANOMALY_05000187 /* IMDMA Corrupted Data after a Halt */
+#define ANOMALY_05000190 /* PPI not functional at core voltage < 1Volt */
+#define ANOMALY_05000208 /* VSTAT status bit in PLL_STAT register is not
+                            functional */
+#define ANOMALY_05000245 /* Spurious Hardware Error from an access in the
+                            shadow of a conditional branch */
+#define ANOMALY_05000257 /* Interrupt/Exception during short hardware loop
+                            may cause bad instruction fetches */
+#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on
+                            external SPORT TX and RX clocks */
+#define ANOMALY_05000267 /* IMDMA may corrupt data under certain conditions */
+#define ANOMALY_05000269 /* High I/O activity causes output voltage of internal
+                            voltage regulator (VDDint) to increase */
+#define ANOMALY_05000270 /* High I/O activity causes output voltage of internal
+                            voltage regulator (VDDint) to decrease */
+#define ANOMALY_05000272 /* Certain data cache write through modes fail for
+                            VDDint <=0.9V */
+#define ANOMALY_05000274 /* Data cache write back to external synchronous memory
+                            may be lost */
+#define ANOMALY_05000275 /* PPI Timing and sampling informaton updates */
+#define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
+                           registers are interrupted */
+
+#endif /*  (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_3)) */
+
+#if  (defined(CONFIG_BF_REV_0_5))
+#define ANOMALY_05000254 /* Incorrect Timer Pulse Width in Single-Shot PWM_OUT
+                            mode with external clock */
+#define ANOMALY_05000266 /* IMDMA destination IRQ status must be read prior to
+                            using IMDMA */
+#endif
+
+#if  (defined(CONFIG_BF_REV_0_3))
+#define ANOMALY_05000156 /* Timers in PWM-Out Mode with PPI GP Receive (Input)
+                            Mode with 0 Frame Syncs */
+#define ANOMALY_05000168 /* SDRAM auto-refresh and subsequent Power Ups */
+#define ANOMALY_05000169 /* DATA CPLB page miss can result in lost write-through
+                            cache data writes */
+#define ANOMALY_05000171 /* Boot-ROM code modifies SICA_IWRx wakeup registers */
+#define ANOMALY_05000174 /* Cache Fill Buffer Data lost */
+#define ANOMALY_05000175 /* Overlapping Sequencer and Memory Stalls */
+#define ANOMALY_05000176 /* Multiplication of (-1) by (-1) followed by an
+                            accumulator saturation */
+#define ANOMALY_05000179 /* PPI_COUNT cannot be programmed to 0 in General
+                            Purpose TX or RX modes */
+#define ANOMALY_05000181 /* Disabling the PPI resets the PPI configuration
+                            registers */
+#define ANOMALY_05000184 /* Timer Pin limitations for PPI TX Modes with
+                            External Frame Syncs */
+#define ANOMALY_05000185 /* PPI TX Mode with 2 External Frame Syncs */
+#define ANOMALY_05000186 /* PPI packing with Data Length greater than 8 bits
+                            (not a meaningful mode) */
+#define ANOMALY_05000188 /* IMDMA Restrictions on Descriptor and Buffer
+                            Placement in Memory */
+#define ANOMALY_05000189 /* False Protection Exception */
+#define ANOMALY_05000193 /* False Flag Pin Interrupts on Edge Sensitive Inputs
+                            when polarity setting is changed */
+#define ANOMALY_05000194 /* Restarting SPORT in specific modes may cause data
+                            corruption */
+#define ANOMALY_05000198 /* Failing MMR accesses when stalled by preceding
+                            memory read */
+#define ANOMALY_05000199 /* DMA current address shows wrong value during carry
+                            fix */
+#define ANOMALY_05000200 /* SPORT TFS and DT are incorrectly driven during
+                            inactive channels in certain conditions */
+#define ANOMALY_05000202 /* Possible infinite stall with specific dual-DAG
+                            situation */
+#define ANOMALY_05000204 /* Incorrect data read with write-through cache and
+                            allocate cache lines on reads only mode */
+#define ANOMALY_05000205 /* Specific sequence that can cause DMA error or DMA
+                            stopping */
+#define ANOMALY_05000207 /* Recovery from "brown-out" condition */
+#define ANOMALY_05000209 /* Speed-Path in computational unit affects certain
+                            instructions */
+#define ANOMALY_05000215 /* UART TX Interrupt masked erroneously */
+#define ANOMALY_05000219 /* NMI event at boot time results in unpredictable
+                            state */
+#define ANOMALY_05000220 /* Data Corruption with Cached External Memory and
+                            Non-Cached On-Chip L2 Memory */
+#define ANOMALY_05000225 /* Incorrect pulse-width of UART start-bit */
+#define ANOMALY_05000227 /* Scratchpad memory bank reads may return incorrect
+                            data */
+#define ANOMALY_05000230 /* UART Receiver is less robust against Baudrate
+                            Differences in certain Conditions */
+#define ANOMALY_05000231 /* UART STB bit incorrectly affects receiver setting */
+#define ANOMALY_05000232 /* SPORT data transmit lines are incorrectly driven in
+                            multichannel mode */
+#define ANOMALY_05000242 /* DF bit in PLL_CTL register does not respond to
+                            hardware reset */
+#define ANOMALY_05000244 /* If i-cache is on, CSYNC/SSYNC/IDLE around Change of
+                            Control causes failures */
+#define ANOMALY_05000248 /* TESTSET operation forces stall on the other core */
+#define ANOMALY_05000250 /* Incorrect Bit-Shift of Data Word in Multichannel
+                            (TDM) mode in certain conditions */
+#define ANOMALY_05000251 /* Exception not generated for MMR accesses in
+                            reserved region */
+#define ANOMALY_05000253 /* Maximum external clock speed for Timers */
+#define ANOMALY_05000258 /* Instruction Cache is corrupted when bits 9 and 12
+                            of the ICPLB Data registers differ */
+#define ANOMALY_05000260 /* ICPLB_STATUS MMR register may be corrupted */
+#define ANOMALY_05000261 /* DCPLB_FAULT_ADDR MMR register may be corrupted */
+#define ANOMALY_05000262 /* Stores to data cache may be lost */
+#define ANOMALY_05000263 /* Hardware loop corrupted when taking an ICPLB
+                            exception */
+#define ANOMALY_05000264 /* CSYNC/SSYNC/IDLE causes infinite stall in second
+                            to last instruction in hardware loop */
+#define ANOMALY_05000276 /* Timing requirements change for External Frame
+                            Sync PPI Modes with non-zero PPI_DELAY */
+#define ANOMALY_05000278 /* Disabling Peripherals with DMA running may cause
+                            DMA system instability */
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context is
+                            not restored */
+#define ANOMALY_05000283 /* An MMR write is stalled indefinitely when killed
+                            in a particular stage */
+#define ANOMALY_05000287 /* A read will receive incorrect data under certain
+                            conditions */
+#define ANOMALY_05000288 /* SPORTs may receive bad data if FIFOs fill up */
+#endif
+
+#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf561/bf561.h b/include/asm-blackfin/mach-bf561/bf561.h
new file mode 100644 (file)
index 0000000..96a5d3a
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * File:         include/asm-blackfin/mach-bf561/bf561.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __MACH_BF561_H__
+#define __MACH_BF561_H__
+
+#define SUPPORTED_REVID                0x3
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+#define L1_ISRAM               0xFFA00000
+#define L1_ISRAM_END           0xFFA04000
+#define DATA_BANKA_SRAM                0xFF800000
+#define DATA_BANKA_SRAM_END    0xFF804000
+#define DATA_BANKB_SRAM                0xFF900000
+#define DATA_BANKB_SRAM_END    0xFF904000
+#define L1_DSRAMA              0xFF800000
+#define L1_DSRAMA_END          0xFF804000
+#define L1_DSRAMB              0xFF900000
+#define L1_DSRAMB_END          0xFF904000
+#define L2_SRAM                        0xFEB00000
+#define L2_SRAM_END            0xFEB20000
+#define AMB_FLASH              0x20000000
+#define AMB_FLASH_END          0x21000000
+#define AMB_FLASH_LENGTH       0x01000000
+#define L1_ISRAM_LENGTH                0x4000
+#define L1_DSRAMA_LENGTH       0x4000
+#define L1_DSRAMB_LENGTH       0x4000
+#define L2_SRAM_LENGTH         0x20000
+
+/*some misc defines*/
+#define IMASK_IVG15            0x8000
+#define IMASK_IVG14            0x4000
+#define IMASK_IVG13            0x2000
+#define IMASK_IVG12            0x1000
+
+#define IMASK_IVG11            0x0800
+#define IMASK_IVG10            0x0400
+#define IMASK_IVG9             0x0200
+#define IMASK_IVG8             0x0100
+
+#define IMASK_IVG7             0x0080
+#define IMASK_IVGTMR           0x0040
+#define IMASK_IVGHW            0x0020
+
+/***************************
+ * Blackfin Cache setup
+ */
+
+
+#define BLKFIN_ISUBBANKS       4
+#define BLKFIN_IWAYS           4
+#define BLKFIN_ILINES          32
+
+#define BLKFIN_DSUBBANKS       4
+#define BLKFIN_DWAYS           2
+#define BLKFIN_DLINES          64
+
+#define WAY0_L                 0x1
+#define WAY1_L                 0x2
+#define WAY01_L                        0x3
+#define WAY2_L                 0x4
+#define WAY02_L                        0x5
+#define        WAY12_L                 0x6
+#define        WAY012_L                0x7
+
+#define        WAY3_L                  0x8
+#define        WAY03_L                 0x9
+#define        WAY13_L                 0xA
+#define        WAY013_L                0xB
+
+#define        WAY32_L                 0xC
+#define        WAY320_L                0xD
+#define        WAY321_L                0xE
+#define        WAYALL_L                0xF
+
+#define DMC_ENABLE (2<<2)      /*yes, 2, not 1 */
+
+/* IAR0 BIT FIELDS */
+#define        PLL_WAKEUP_BIT          0xFFFFFFFF
+#define        DMA1_ERROR_BIT          0xFFFFFF0F
+#define        DMA2_ERROR_BIT          0xFFFFF0FF
+#define IMDMA_ERROR_BIT                0xFFFF0FFF
+#define        PPI1_ERROR_BIT          0xFFF0FFFF
+#define        PPI2_ERROR_BIT          0xFF0FFFFF
+#define        SPORT0_ERROR_BIT        0xF0FFFFFF
+#define        SPORT1_ERROR_BIT        0x0FFFFFFF
+/* IAR1 BIT FIELDS */
+#define        SPI_ERROR_BIT           0xFFFFFFFF
+#define        UART_ERROR_BIT          0xFFFFFF0F
+#define RESERVED_ERROR_BIT     0xFFFFF0FF
+#define        DMA1_0_BIT              0xFFFF0FFF
+#define        DMA1_1_BIT              0xFFF0FFFF
+#define        DMA1_2_BIT              0xFF0FFFFF
+#define        DMA1_3_BIT              0xF0FFFFFF
+#define        DMA1_4_BIT              0x0FFFFFFF
+/* IAR2 BIT FIELDS */
+#define        DMA1_5_BIT              0xFFFFFFFF
+#define        DMA1_6_BIT              0xFFFFFF0F
+#define        DMA1_7_BIT              0xFFFFF0FF
+#define        DMA1_8_BIT              0xFFFF0FFF
+#define        DMA1_9_BIT              0xFFF0FFFF
+#define        DMA1_10_BIT             0xFF0FFFFF
+#define        DMA1_11_BIT             0xF0FFFFFF
+#define        DMA2_0_BIT              0x0FFFFFFF
+/* IAR3 BIT FIELDS */
+#define        DMA2_1_BIT              0xFFFFFFFF
+#define        DMA2_2_BIT              0xFFFFFF0F
+#define        DMA2_3_BIT              0xFFFFF0FF
+#define        DMA2_4_BIT              0xFFFF0FFF
+#define        DMA2_5_BIT              0xFFF0FFFF
+#define        DMA2_6_BIT              0xFF0FFFFF
+#define        DMA2_7_BIT              0xF0FFFFFF
+#define        DMA2_8_BIT              0x0FFFFFFF
+/* IAR4 BIT FIELDS */
+#define        DMA2_9_BIT              0xFFFFFFFF
+#define        DMA2_10_BIT             0xFFFFFF0F
+#define        DMA2_11_BIT             0xFFFFF0FF
+#define TIMER0_BIT             0xFFFF0FFF
+#define TIMER1_BIT              0xFFF0FFFF
+#define TIMER2_BIT              0xFF0FFFFF
+#define TIMER3_BIT              0xF0FFFFFF
+#define TIMER4_BIT              0x0FFFFFFF
+/* IAR5 BIT FIELDS */
+#define TIMER5_BIT             0xFFFFFFFF
+#define TIMER6_BIT              0xFFFFFF0F
+#define TIMER7_BIT              0xFFFFF0FF
+#define TIMER8_BIT              0xFFFF0FFF
+#define TIMER9_BIT              0xFFF0FFFF
+#define TIMER10_BIT             0xFF0FFFFF
+#define TIMER11_BIT             0xF0FFFFFF
+#define        PROG0_INTA_BIT          0x0FFFFFFF
+/* IAR6 BIT FIELDS */
+#define        PROG0_INTB_BIT          0xFFFFFFFF
+#define        PROG1_INTA_BIT          0xFFFFFF0F
+#define        PROG1_INTB_BIT          0xFFFFF0FF
+#define        PROG2_INTA_BIT          0xFFFF0FFF
+#define        PROG2_INTB_BIT          0xFFF0FFFF
+#define DMA1_WRRD0_BIT          0xFF0FFFFF
+#define DMA1_WRRD1_BIT          0xF0FFFFFF
+#define DMA2_WRRD0_BIT          0x0FFFFFFF
+/* IAR7 BIT FIELDS */
+#define DMA2_WRRD1_BIT         0xFFFFFFFF
+#define IMDMA_WRRD0_BIT         0xFFFFFF0F
+#define IMDMA_WRRD1_BIT         0xFFFFF0FF
+#define        WATCH_BIT               0xFFFF0FFF
+#define RESERVED_1_BIT         0xFFF0FFFF
+#define RESERVED_2_BIT         0xFF0FFFFF
+#define SUPPLE_0_BIT           0xF0FFFFFF
+#define SUPPLE_1_BIT           0x0FFFFFFF
+
+/* Miscellaneous Values */
+
+/****************************** EBIU Settings ********************************/
+#define AMBCTL0VAL     ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL     ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#if defined(CONFIG_C_AMBEN_ALL)
+#define V_AMBEN AMBEN_ALL
+#elif defined(CONFIG_C_AMBEN)
+#define V_AMBEN 0x0
+#elif defined(CONFIG_C_AMBEN_B0)
+#define V_AMBEN AMBEN_B0
+#elif defined(CONFIG_C_AMBEN_B0_B1)
+#define V_AMBEN AMBEN_B0_B1
+#elif defined(CONFIG_C_AMBEN_B0_B1_B2)
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+
+#ifdef CONFIG_C_B0PEN
+#define V_B0PEN 0x10
+#else
+#define V_B0PEN 0x00
+#endif
+
+#ifdef CONFIG_C_B1PEN
+#define V_B1PEN 0x20
+#else
+#define V_B1PEN 0x00
+#endif
+
+#ifdef CONFIG_C_B2PEN
+#define V_B2PEN 0x40
+#else
+#define V_B2PEN 0x00
+#endif
+
+#ifdef CONFIG_C_B3PEN
+#define V_B3PEN 0x80
+#else
+#define V_B3PEN 0x00
+#endif
+
+#ifdef CONFIG_C_CDPRIO
+#define V_CDPRIO 0x100
+#else
+#define V_CDPRIO 0x0
+#endif
+
+#define AMGCTLVAL      (V_AMBEN | V_AMCKEN | V_CDPRIO | V_B0PEN | V_B1PEN | V_B2PEN | V_B3PEN | 0x0002)
+
+#define MAX_VC 600000000
+#define MIN_VC 50000000
+
+/******************************* PLL Settings ********************************/
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
+#if (CONFIG_VCO_MULT < 0)
+#error "VCO Multiplier is less than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT == 0)
+#error "VCO Multiplier should be greater than 0. Please select a different value"
+#endif
+
+#ifndef CONFIG_CLKIN_HALF
+#define CONFIG_VCO_HZ  (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)
+#else
+#define CONFIG_VCO_HZ  ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2)
+#endif
+
+#ifndef CONFIG_PLL_BYPASS
+#define CONFIG_CCLK_HZ (CONFIG_VCO_HZ/CONFIG_CCLK_DIV)
+#define CONFIG_SCLK_HZ (CONFIG_VCO_HZ/CONFIG_SCLK_DIV)
+#else
+#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ
+#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ
+#endif
+
+#if (CONFIG_SCLK_DIV < 1)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_SCLK_DIV > 15)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_CCLK_DIV != 1)
+#if (CONFIG_CCLK_DIV != 2)
+#if (CONFIG_CCLK_DIV != 4)
+#if (CONFIG_CCLK_DIV != 8)
+#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value"
+#endif
+#endif
+#endif
+#endif
+
+#if (CONFIG_VCO_HZ > MAX_VC)
+#error "VCO selected is more than maximum value. Please change the VCO multipler"
+#endif
+
+#if (CONFIG_SCLK_HZ > 133000000)
+#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ < 27000000)
+#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ >= CONFIG_CCLK_HZ)
+#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ)
+#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ)
+#error "Please select sclk less than cclk"
+#endif
+#endif
+#endif
+
+#if (CONFIG_CCLK_DIV == 1)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV1
+#endif
+#if (CONFIG_CCLK_DIV == 2)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV2
+#endif
+#if (CONFIG_CCLK_DIV == 4)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV4
+#endif
+#if (CONFIG_CCLK_DIV == 8)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV8
+#endif
+#ifndef CONFIG_CCLK_ACT_DIV
+#define CONFIG_CCLK_ACT_DIV   CONFIG_CCLK_DIV_not_defined_properly
+#endif
+
+#if defined(ANOMALY_05000273) && (CONFIG_CCLK_DIV == 1)
+#error ANOMALY 05000273, please make sure CCLK is at least 2x SCLK
+#endif
+
+#endif                         /* CONFIG_BFIN_KERNEL_CLOCK */
+
+#ifdef CONFIG_BF561
+#define CPU "BF561"
+#define CPUID 0x027bb000
+#endif
+#ifndef CPU
+#define CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#if (CONFIG_MEM_SIZE % 4)
+#error "SDRAM memory size must be a multiple of 4MB!"
+#endif
+#define SDRAM_IGENERIC    (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
+#define SDRAM_IKERNEL     (SDRAM_IGENERIC | CPLB_LOCK)
+#define L1_IMEMORY        (               CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
+#define SDRAM_INON_CHBL   (               CPLB_USER_RD | CPLB_VALID)
+
+/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/
+
+#define ANOMALY_05000158_WORKAROUND            0x200
+#ifdef CONFIG_BLKFIN_WB                /*Write Back Policy */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_DIRTY \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#else                          /*Write Through */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_DIRTY \
+                       | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#endif
+
+
+#define L1_DMEMORY       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
+#define SDRAM_DNON_CHBL  (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY)
+#define SDRAM_EBIU       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY)
+#define SDRAM_OOPS      (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
+
+#define L2_MEMORY      (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY)
+
+#define SIZE_1K 0x00000400     /* 1K */
+#define SIZE_4K 0x00001000     /* 4K */
+#define SIZE_1M 0x00100000     /* 1M */
+#define SIZE_4M 0x00400000     /* 4M */
+
+#define MAX_CPLBS (16 * 2)
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* 1 for L2 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 64 for ASYNC Memory
+*/
+
+
+#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1 + 64) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* 1 for L2 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+
+#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1 + 1) * 2)
+
+#if 0                          /* comment by mhfan */
+/* Event Vector Table Address */
+#define EVT_EMULATION_ADDR      0xffe02000
+#define EVT_RESET_ADDR          0xffe02004
+#define EVT_NMI_ADDR            0xffe02008
+#define EVT_EXCEPTION_ADDR      0xffe0200c
+#define EVT_GLOBAL_INT_ENB_ADDR 0xffe02010
+#define EVT_HARDWARE_ERROR_ADDR 0xffe02014
+#define EVT_TIMER_ADDR          0xffe02018
+#define EVT_IVG7_ADDR           0xffe0201c
+#define EVT_IVG8_ADDR           0xffe02020
+#define EVT_IVG9_ADDR           0xffe02024
+#define EVT_IVG10_ADDR          0xffe02028
+#define EVT_IVG11_ADDR          0xffe0202c
+#define EVT_IVG12_ADDR          0xffe02030
+#define EVT_IVG13_ADDR          0xffe02034
+#define EVT_IVG14_ADDR          0xffe02038
+#define EVT_IVG15_ADDR          0xffe0203c
+#define EVT_OVERRIDE_ADDR       0xffe02100
+#endif                         /* comment by mhfan */
+
+#endif                         /* __MACH_BF561_H__  */
diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
new file mode 100644 (file)
index 0000000..23bf76a
--- /dev/null
@@ -0,0 +1,108 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+
+#define NR_PORTS                1
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
+
+#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+#define UART_GET_DLH(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
+#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
+#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
+#define UART_PUT_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER),v)
+#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
+#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
+
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+# define CONFIG_SERIAL_BFIN_CTSRTS
+# ifndef CONFIG_UART0_CTS_PIN
+#  define CONFIG_UART0_CTS_PIN -1
+# endif
+# ifndef CONFIG_UART0_RTS_PIN
+#  define CONFIG_UART0_RTS_PIN -1
+# endif
+#endif
+
+struct bfin_serial_port {
+        struct uart_port        port;
+        unsigned int            old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       int                     tx_done;
+       int                     tx_count;
+       struct circ_buf         rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+       struct work_struct      tx_dma_workqueue;
+#else
+       struct work_struct      cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int                     cts_pin;
+       int                     rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+       unsigned long   uart_base_addr;
+       int             uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       unsigned int    uart_tx_dma_channel;
+       unsigned int    uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       int             uart_cts_pin;
+       int             uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+       0xFFC00400,
+       IRQ_UART_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+       CH_UART_TX,
+       CH_UART_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+       CONFIG_UART0_CTS_PIN,
+       CONFIG_UART0_RTS_PIN,
+#endif
+};
+
+
+int nr_ports = NR_PORTS;
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       if (uart->cts_pin >= 0) {
+               gpio_request(uart->cts_pin, NULL);
+               gpio_direction_input(uart->cts_pin);
+       }
+       if (uart->rts_pin >= 0) {
+               gpio_request(uart->rts_pin, NULL);
+               gpio_direction_input(uart->rts_pin);
+       }
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf561/blackfin.h b/include/asm-blackfin/mach-bf561/blackfin.h
new file mode 100644 (file)
index 0000000..2537c84
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * File:         include/asm-blackfin/mach-bf561/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF561_FAMILY
+
+#include "bf561.h"
+#include "mem_map.h"
+#include "defBF561.h"
+#include "anomaly.h"
+
+#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY))
+#include "cdefBF561.h"
+#endif
+
+#define bfin_read_FIO_FLAG_D() bfin_read_FIO0_FLAG_D()
+#define bfin_write_FIO_FLAG_D(val) bfin_write_FIO0_FLAG_D(val)
+#define bfin_read_FIO_DIR() bfin_read_FIO0_DIR()
+#define bfin_write_FIO_DIR(val) bfin_write_FIO0_DIR(val)
+#define bfin_read_FIO_INEN() bfin_read_FIO0_INEN()
+#define bfin_write_FIO_INEN(val) bfin_write_FIO0_INEN(val)
+
+#endif                         /* _MACH_BLACKFIN_H_ */
diff --git a/include/asm-blackfin/mach-bf561/cdefBF561.h b/include/asm-blackfin/mach-bf561/cdefBF561.h
new file mode 100644 (file)
index 0000000..5dc0ed8
--- /dev/null
@@ -0,0 +1,1543 @@
+/*
+ * File:         include/asm-blackfin/mach-bf561/cdefBF561.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  C POINTERS TO SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF561_H
+#define _CDEF_BF561_H
+
+/*
+#if !defined(__ADSPBF561__)
+#warning cdefBF561.h should only be included for BF561 chip.
+#endif
+*/
+/* include all Core registers and bit definitions */
+#include "defBF561.h"
+
+/*include core specific register pointer definitions*/
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+#include <asm/system.h>
+
+/*********************************************************************************** */
+/* System MMR Register Map */
+/*********************************************************************************** */
+
+/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+#define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
+#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+#define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
+#define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       bfin_write16(VR_CTL, val);
+       __builtin_bfin_ssync();
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SICA_IWR0);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+       local_irq_save(flags);
+       asm("IDLE;");
+       local_irq_restore(flags);
+       bfin_write32(SICA_IWR0, iwr);
+}
+#define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
+#define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)          bfin_write16(PLL_LOCKCNT,val)
+#define bfin_read_CHIPID()                   bfin_read32(CHIPID)
+
+/* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
+#define bfin_read_SICA_SWRST()               bfin_read16(SICA_SWRST)
+#define bfin_write_SICA_SWRST(val)           bfin_write16(SICA_SWRST,val)
+#define bfin_read_SICA_SYSCR()               bfin_read16(SICA_SYSCR)
+#define bfin_write_SICA_SYSCR(val)           bfin_write16(SICA_SYSCR,val)
+#define bfin_read_SICA_RVECT()               bfin_read16(SICA_RVECT)
+#define bfin_write_SICA_RVECT(val)           bfin_write16(SICA_RVECT,val)
+#define bfin_read_SICA_IMASK()               bfin_read32(SICA_IMASK)
+#define bfin_write_SICA_IMASK(val)           bfin_write32(SICA_IMASK,val)
+#define bfin_read_SICA_IMASK0()              bfin_read32(SICA_IMASK0)
+#define bfin_write_SICA_IMASK0(val)          bfin_write32(SICA_IMASK0,val)
+#define bfin_read_SICA_IMASK1()              bfin_read32(SICA_IMASK1)
+#define bfin_write_SICA_IMASK1(val)          bfin_write32(SICA_IMASK1,val)
+#define bfin_read_SICA_IAR0()                bfin_read32(SICA_IAR0)
+#define bfin_write_SICA_IAR0(val)            bfin_write32(SICA_IAR0,val)
+#define bfin_read_SICA_IAR1()                bfin_read32(SICA_IAR1)
+#define bfin_write_SICA_IAR1(val)            bfin_write32(SICA_IAR1,val)
+#define bfin_read_SICA_IAR2()                bfin_read32(SICA_IAR2)
+#define bfin_write_SICA_IAR2(val)            bfin_write32(SICA_IAR2,val)
+#define bfin_read_SICA_IAR3()                bfin_read32(SICA_IAR3)
+#define bfin_write_SICA_IAR3(val)            bfin_write32(SICA_IAR3,val)
+#define bfin_read_SICA_IAR4()                bfin_read32(SICA_IAR4)
+#define bfin_write_SICA_IAR4(val)            bfin_write32(SICA_IAR4,val)
+#define bfin_read_SICA_IAR5()                bfin_read32(SICA_IAR5)
+#define bfin_write_SICA_IAR5(val)            bfin_write32(SICA_IAR5,val)
+#define bfin_read_SICA_IAR6()                bfin_read32(SICA_IAR6)
+#define bfin_write_SICA_IAR6(val)            bfin_write32(SICA_IAR6,val)
+#define bfin_read_SICA_IAR7()                bfin_read32(SICA_IAR7)
+#define bfin_write_SICA_IAR7(val)            bfin_write32(SICA_IAR7,val)
+#define bfin_read_SICA_ISR0()                bfin_read32(SICA_ISR0)
+#define bfin_write_SICA_ISR0(val)            bfin_write32(SICA_ISR0,val)
+#define bfin_read_SICA_ISR1()                bfin_read32(SICA_ISR1)
+#define bfin_write_SICA_ISR1(val)            bfin_write32(SICA_ISR1,val)
+#define bfin_read_SICA_IWR0()                bfin_read32(SICA_IWR0)
+#define bfin_write_SICA_IWR0(val)            bfin_write32(SICA_IWR0,val)
+#define bfin_read_SICA_IWR1()                bfin_read32(SICA_IWR1)
+#define bfin_write_SICA_IWR1(val)            bfin_write32(SICA_IWR1,val)
+
+/* System Reset and Interrupt Controller registers for Core B (0xFFC0 1100-0xFFC0 11FF) */
+#define bfin_read_SICB_SWRST()               bfin_read16(SICB_SWRST)
+#define bfin_write_SICB_SWRST(val)           bfin_write16(SICB_SWRST,val)
+#define bfin_read_SICB_SYSCR()               bfin_read16(SICB_SYSCR)
+#define bfin_write_SICB_SYSCR(val)           bfin_write16(SICB_SYSCR,val)
+#define bfin_read_SICB_RVECT()               bfin_read16(SICB_RVECT)
+#define bfin_write_SICB_RVECT(val)           bfin_write16(SICB_RVECT,val)
+#define bfin_read_SICB_IMASK0()              bfin_read32(SICB_IMASK0)
+#define bfin_write_SICB_IMASK0(val)          bfin_write32(SICB_IMASK0,val)
+#define bfin_read_SICB_IMASK1()              bfin_read32(SICB_IMASK1)
+#define bfin_write_SICB_IMASK1(val)          bfin_write32(SICB_IMASK1,val)
+#define bfin_read_SICB_IAR0()                bfin_read32(SICB_IAR0)
+#define bfin_write_SICB_IAR0(val)            bfin_write32(SICB_IAR0,val)
+#define bfin_read_SICB_IAR1()                bfin_read32(SICB_IAR1)
+#define bfin_write_SICB_IAR1(val)            bfin_write32(SICB_IAR1,val)
+#define bfin_read_SICB_IAR2()                bfin_read32(SICB_IAR2)
+#define bfin_write_SICB_IAR2(val)            bfin_write32(SICB_IAR2,val)
+#define bfin_read_SICB_IAR3()                bfin_read32(SICB_IAR3)
+#define bfin_write_SICB_IAR3(val)            bfin_write32(SICB_IAR3,val)
+#define bfin_read_SICB_IAR4()                bfin_read32(SICB_IAR4)
+#define bfin_write_SICB_IAR4(val)            bfin_write32(SICB_IAR4,val)
+#define bfin_read_SICB_IAR5()                bfin_read32(SICB_IAR5)
+#define bfin_write_SICB_IAR5(val)            bfin_write32(SICB_IAR5,val)
+#define bfin_read_SICB_IAR6()                bfin_read32(SICB_IAR6)
+#define bfin_write_SICB_IAR6(val)            bfin_write32(SICB_IAR6,val)
+#define bfin_read_SICB_IAR7()                bfin_read32(SICB_IAR7)
+#define bfin_write_SICB_IAR7(val)            bfin_write32(SICB_IAR7,val)
+#define bfin_read_SICB_ISR0()                bfin_read32(SICB_ISR0)
+#define bfin_write_SICB_ISR0(val)            bfin_write32(SICB_ISR0,val)
+#define bfin_read_SICB_ISR1()                bfin_read32(SICB_ISR1)
+#define bfin_write_SICB_ISR1(val)            bfin_write32(SICB_ISR1,val)
+#define bfin_read_SICB_IWR0()                bfin_read32(SICB_IWR0)
+#define bfin_write_SICB_IWR0(val)            bfin_write32(SICB_IWR0,val)
+#define bfin_read_SICB_IWR1()                bfin_read32(SICB_IWR1)
+#define bfin_write_SICB_IWR1(val)            bfin_write32(SICB_IWR1,val)
+/* Watchdog Timer registers for Core A (0xFFC0 0200-0xFFC0 02FF) */
+#define bfin_read_WDOGA_CTL()                bfin_read16(WDOGA_CTL)
+#define bfin_write_WDOGA_CTL(val)            bfin_write16(WDOGA_CTL,val)
+#define bfin_read_WDOGA_CNT()                bfin_read32(WDOGA_CNT)
+#define bfin_write_WDOGA_CNT(val)            bfin_write32(WDOGA_CNT,val)
+#define bfin_read_WDOGA_STAT()               bfin_read32(WDOGA_STAT)
+#define bfin_write_WDOGA_STAT(val)           bfin_write32(WDOGA_STAT,val)
+
+/* Watchdog Timer registers for Core B (0xFFC0 1200-0xFFC0 12FF) */
+#define bfin_read_WDOGB_CTL()                bfin_read16(WDOGB_CTL)
+#define bfin_write_WDOGB_CTL(val)            bfin_write16(WDOGB_CTL,val)
+#define bfin_read_WDOGB_CNT()                bfin_read32(WDOGB_CNT)
+#define bfin_write_WDOGB_CNT(val)            bfin_write32(WDOGB_CNT,val)
+#define bfin_read_WDOGB_STAT()               bfin_read32(WDOGB_STAT)
+#define bfin_write_WDOGB_STAT(val)           bfin_write32(WDOGB_STAT,val)
+
+/* UART Controller (0xFFC00400 - 0xFFC004FF) */
+#define bfin_read_UART_THR()                 bfin_read16(UART_THR)
+#define bfin_write_UART_THR(val)             bfin_write16(UART_THR,val)
+#define bfin_read_UART_RBR()                 bfin_read16(UART_RBR)
+#define bfin_write_UART_RBR(val)             bfin_write16(UART_RBR,val)
+#define bfin_read_UART_DLL()                 bfin_read16(UART_DLL)
+#define bfin_write_UART_DLL(val)             bfin_write16(UART_DLL,val)
+#define bfin_read_UART_IER()                 bfin_read16(UART_IER)
+#define bfin_write_UART_IER(val)             bfin_write16(UART_IER,val)
+#define bfin_read_UART_DLH()                 bfin_read16(UART_DLH)
+#define bfin_write_UART_DLH(val)             bfin_write16(UART_DLH,val)
+#define bfin_read_UART_IIR()                 bfin_read16(UART_IIR)
+#define bfin_write_UART_IIR(val)             bfin_write16(UART_IIR,val)
+#define bfin_read_UART_LCR()                 bfin_read16(UART_LCR)
+#define bfin_write_UART_LCR(val)             bfin_write16(UART_LCR,val)
+#define bfin_read_UART_MCR()                 bfin_read16(UART_MCR)
+#define bfin_write_UART_MCR(val)             bfin_write16(UART_MCR,val)
+#define bfin_read_UART_LSR()                 bfin_read16(UART_LSR)
+#define bfin_write_UART_LSR(val)             bfin_write16(UART_LSR,val)
+#define bfin_read_UART_MSR()                 bfin_read16(UART_MSR)
+#define bfin_write_UART_MSR(val)             bfin_write16(UART_MSR,val)
+#define bfin_read_UART_SCR()                 bfin_read16(UART_SCR)
+#define bfin_write_UART_SCR(val)             bfin_write16(UART_SCR,val)
+#define bfin_read_UART_GCTL()                bfin_read16(UART_GCTL)
+#define bfin_write_UART_GCTL(val)            bfin_write16(UART_GCTL,val)
+
+/* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+#define bfin_read_SPI_CTL()                  bfin_read16(SPI_CTL)
+#define bfin_write_SPI_CTL(val)              bfin_write16(SPI_CTL,val)
+#define bfin_read_SPI_FLG()                  bfin_read16(SPI_FLG)
+#define bfin_write_SPI_FLG(val)              bfin_write16(SPI_FLG,val)
+#define bfin_read_SPI_STAT()                 bfin_read16(SPI_STAT)
+#define bfin_write_SPI_STAT(val)             bfin_write16(SPI_STAT,val)
+#define bfin_read_SPI_TDBR()                 bfin_read16(SPI_TDBR)
+#define bfin_write_SPI_TDBR(val)             bfin_write16(SPI_TDBR,val)
+#define bfin_read_SPI_RDBR()                 bfin_read16(SPI_RDBR)
+#define bfin_write_SPI_RDBR(val)             bfin_write16(SPI_RDBR,val)
+#define bfin_read_SPI_BAUD()                 bfin_read16(SPI_BAUD)
+#define bfin_write_SPI_BAUD(val)             bfin_write16(SPI_BAUD,val)
+#define bfin_read_SPI_SHADOW()               bfin_read16(SPI_SHADOW)
+#define bfin_write_SPI_SHADOW(val)           bfin_write16(SPI_SHADOW,val)
+
+/* Timer 0-7 registers (0xFFC0 0600-0xFFC0 06FF) */
+#define bfin_read_TIMER0_CONFIG()            bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)        bfin_write16(TIMER0_CONFIG,val)
+#define bfin_read_TIMER0_COUNTER()           bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)       bfin_write32(TIMER0_COUNTER,val)
+#define bfin_read_TIMER0_PERIOD()            bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)        bfin_write32(TIMER0_PERIOD,val)
+#define bfin_read_TIMER0_WIDTH()             bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)         bfin_write32(TIMER0_WIDTH,val)
+#define bfin_read_TIMER1_CONFIG()            bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)        bfin_write16(TIMER1_CONFIG,val)
+#define bfin_read_TIMER1_COUNTER()           bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)       bfin_write32(TIMER1_COUNTER,val)
+#define bfin_read_TIMER1_PERIOD()            bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)        bfin_write32(TIMER1_PERIOD,val)
+#define bfin_read_TIMER1_WIDTH()             bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)         bfin_write32(TIMER1_WIDTH,val)
+#define bfin_read_TIMER2_CONFIG()            bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)        bfin_write16(TIMER2_CONFIG,val)
+#define bfin_read_TIMER2_COUNTER()           bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)       bfin_write32(TIMER2_COUNTER,val)
+#define bfin_read_TIMER2_PERIOD()            bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)        bfin_write32(TIMER2_PERIOD,val)
+#define bfin_read_TIMER2_WIDTH()             bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)         bfin_write32(TIMER2_WIDTH,val)
+#define bfin_read_TIMER3_CONFIG()            bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val)        bfin_write16(TIMER3_CONFIG,val)
+#define bfin_read_TIMER3_COUNTER()           bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val)       bfin_write32(TIMER3_COUNTER,val)
+#define bfin_read_TIMER3_PERIOD()            bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val)        bfin_write32(TIMER3_PERIOD,val)
+#define bfin_read_TIMER3_WIDTH()             bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val)         bfin_write32(TIMER3_WIDTH,val)
+#define bfin_read_TIMER4_CONFIG()            bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val)        bfin_write16(TIMER4_CONFIG,val)
+#define bfin_read_TIMER4_COUNTER()           bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val)       bfin_write32(TIMER4_COUNTER,val)
+#define bfin_read_TIMER4_PERIOD()            bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val)        bfin_write32(TIMER4_PERIOD,val)
+#define bfin_read_TIMER4_WIDTH()             bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val)         bfin_write32(TIMER4_WIDTH,val)
+#define bfin_read_TIMER5_CONFIG()            bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val)        bfin_write16(TIMER5_CONFIG,val)
+#define bfin_read_TIMER5_COUNTER()           bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val)       bfin_write32(TIMER5_COUNTER,val)
+#define bfin_read_TIMER5_PERIOD()            bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val)        bfin_write32(TIMER5_PERIOD,val)
+#define bfin_read_TIMER5_WIDTH()             bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val)         bfin_write32(TIMER5_WIDTH,val)
+#define bfin_read_TIMER6_CONFIG()            bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val)        bfin_write16(TIMER6_CONFIG,val)
+#define bfin_read_TIMER6_COUNTER()           bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val)       bfin_write32(TIMER6_COUNTER,val)
+#define bfin_read_TIMER6_PERIOD()            bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val)        bfin_write32(TIMER6_PERIOD,val)
+#define bfin_read_TIMER6_WIDTH()             bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val)         bfin_write32(TIMER6_WIDTH,val)
+#define bfin_read_TIMER7_CONFIG()            bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val)        bfin_write16(TIMER7_CONFIG,val)
+#define bfin_read_TIMER7_COUNTER()           bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val)       bfin_write32(TIMER7_COUNTER,val)
+#define bfin_read_TIMER7_PERIOD()            bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val)        bfin_write32(TIMER7_PERIOD,val)
+#define bfin_read_TIMER7_WIDTH()             bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val)         bfin_write32(TIMER7_WIDTH,val)
+
+/* Timer registers 8-11 (0xFFC0 1600-0xFFC0 16FF) */
+#define bfin_read_TMRS8_ENABLE()             bfin_read16(TMRS8_ENABLE)
+#define bfin_write_TMRS8_ENABLE(val)         bfin_write16(TMRS8_ENABLE,val)
+#define bfin_read_TMRS8_DISABLE()            bfin_read16(TMRS8_DISABLE)
+#define bfin_write_TMRS8_DISABLE(val)        bfin_write16(TMRS8_DISABLE,val)
+#define bfin_read_TMRS8_STATUS()             bfin_read32(TMRS8_STATUS)
+#define bfin_write_TMRS8_STATUS(val)         bfin_write32(TMRS8_STATUS,val)
+#define bfin_read_TIMER8_CONFIG()            bfin_read16(TIMER8_CONFIG)
+#define bfin_write_TIMER8_CONFIG(val)        bfin_write16(TIMER8_CONFIG,val)
+#define bfin_read_TIMER8_COUNTER()           bfin_read32(TIMER8_COUNTER)
+#define bfin_write_TIMER8_COUNTER(val)       bfin_write32(TIMER8_COUNTER,val)
+#define bfin_read_TIMER8_PERIOD()            bfin_read32(TIMER8_PERIOD)
+#define bfin_write_TIMER8_PERIOD(val)        bfin_write32(TIMER8_PERIOD,val)
+#define bfin_read_TIMER8_WIDTH()             bfin_read32(TIMER8_WIDTH)
+#define bfin_write_TIMER8_WIDTH(val)         bfin_write32(TIMER8_WIDTH,val)
+#define bfin_read_TIMER9_CONFIG()            bfin_read16(TIMER9_CONFIG)
+#define bfin_write_TIMER9_CONFIG(val)        bfin_write16(TIMER9_CONFIG,val)
+#define bfin_read_TIMER9_COUNTER()           bfin_read32(TIMER9_COUNTER)
+#define bfin_write_TIMER9_COUNTER(val)       bfin_write32(TIMER9_COUNTER,val)
+#define bfin_read_TIMER9_PERIOD()            bfin_read32(TIMER9_PERIOD)
+#define bfin_write_TIMER9_PERIOD(val)        bfin_write32(TIMER9_PERIOD,val)
+#define bfin_read_TIMER9_WIDTH()             bfin_read32(TIMER9_WIDTH)
+#define bfin_write_TIMER9_WIDTH(val)         bfin_write32(TIMER9_WIDTH,val)
+#define bfin_read_TIMER10_CONFIG()           bfin_read16(TIMER10_CONFIG)
+#define bfin_write_TIMER10_CONFIG(val)       bfin_write16(TIMER10_CONFIG,val)
+#define bfin_read_TIMER10_COUNTER()          bfin_read32(TIMER10_COUNTER)
+#define bfin_write_TIMER10_COUNTER(val)      bfin_write32(TIMER10_COUNTER,val)
+#define bfin_read_TIMER10_PERIOD()           bfin_read32(TIMER10_PERIOD)
+#define bfin_write_TIMER10_PERIOD(val)       bfin_write32(TIMER10_PERIOD,val)
+#define bfin_read_TIMER10_WIDTH()            bfin_read32(TIMER10_WIDTH)
+#define bfin_write_TIMER10_WIDTH(val)        bfin_write32(TIMER10_WIDTH,val)
+#define bfin_read_TIMER11_CONFIG()           bfin_read16(TIMER11_CONFIG)
+#define bfin_write_TIMER11_CONFIG(val)       bfin_write16(TIMER11_CONFIG,val)
+#define bfin_read_TIMER11_COUNTER()          bfin_read32(TIMER11_COUNTER)
+#define bfin_write_TIMER11_COUNTER(val)      bfin_write32(TIMER11_COUNTER,val)
+#define bfin_read_TIMER11_PERIOD()           bfin_read32(TIMER11_PERIOD)
+#define bfin_write_TIMER11_PERIOD(val)       bfin_write32(TIMER11_PERIOD,val)
+#define bfin_read_TIMER11_WIDTH()            bfin_read32(TIMER11_WIDTH)
+#define bfin_write_TIMER11_WIDTH(val)        bfin_write32(TIMER11_WIDTH,val)
+#define bfin_read_TMRS4_ENABLE()             bfin_read16(TMRS4_ENABLE)
+#define bfin_write_TMRS4_ENABLE(val)         bfin_write16(TMRS4_ENABLE,val)
+#define bfin_read_TMRS4_DISABLE()            bfin_read16(TMRS4_DISABLE)
+#define bfin_write_TMRS4_DISABLE(val)        bfin_write16(TMRS4_DISABLE,val)
+#define bfin_read_TMRS4_STATUS()             bfin_read32(TMRS4_STATUS)
+#define bfin_write_TMRS4_STATUS(val)         bfin_write32(TMRS4_STATUS,val)
+
+/* Programmable Flag 0 registers (0xFFC0 0700-0xFFC0 07FF) */
+#define bfin_read_FIO0_FLAG_D()              bfin_read16(FIO0_FLAG_D)
+#define bfin_write_FIO0_FLAG_D(val)          bfin_write16(FIO0_FLAG_D,val)
+#define bfin_read_FIO0_FLAG_C()              bfin_read16(FIO0_FLAG_C)
+#define bfin_write_FIO0_FLAG_C(val)          bfin_write16(FIO0_FLAG_C,val)
+#define bfin_read_FIO0_FLAG_S()              bfin_read16(FIO0_FLAG_S)
+#define bfin_write_FIO0_FLAG_S(val)          bfin_write16(FIO0_FLAG_S,val)
+#define bfin_read_FIO0_FLAG_T()              bfin_read16(FIO0_FLAG_T)
+#define bfin_write_FIO0_FLAG_T(val)          bfin_write16(FIO0_FLAG_T,val)
+#define bfin_read_FIO0_MASKA_D()             bfin_read16(FIO0_MASKA_D)
+#define bfin_write_FIO0_MASKA_D(val)         bfin_write16(FIO0_MASKA_D,val)
+#define bfin_read_FIO0_MASKA_C()             bfin_read16(FIO0_MASKA_C)
+#define bfin_write_FIO0_MASKA_C(val)         bfin_write16(FIO0_MASKA_C,val)
+#define bfin_read_FIO0_MASKA_S()             bfin_read16(FIO0_MASKA_S)
+#define bfin_write_FIO0_MASKA_S(val)         bfin_write16(FIO0_MASKA_S,val)
+#define bfin_read_FIO0_MASKA_T()             bfin_read16(FIO0_MASKA_T)
+#define bfin_write_FIO0_MASKA_T(val)         bfin_write16(FIO0_MASKA_T,val)
+#define bfin_read_FIO0_MASKB_D()             bfin_read16(FIO0_MASKB_D)
+#define bfin_write_FIO0_MASKB_D(val)         bfin_write16(FIO0_MASKB_D,val)
+#define bfin_read_FIO0_MASKB_C()             bfin_read16(FIO0_MASKB_C)
+#define bfin_write_FIO0_MASKB_C(val)         bfin_write16(FIO0_MASKB_C,val)
+#define bfin_read_FIO0_MASKB_S()             bfin_read16(FIO0_MASKB_S)
+#define bfin_write_FIO0_MASKB_S(val)         bfin_write16(FIO0_MASKB_S,val)
+#define bfin_read_FIO0_MASKB_T()             bfin_read16(FIO0_MASKB_T)
+#define bfin_write_FIO0_MASKB_T(val)         bfin_write16(FIO0_MASKB_T,val)
+#define bfin_read_FIO0_DIR()                 bfin_read16(FIO0_DIR)
+#define bfin_write_FIO0_DIR(val)             bfin_write16(FIO0_DIR,val)
+#define bfin_read_FIO0_POLAR()               bfin_read16(FIO0_POLAR)
+#define bfin_write_FIO0_POLAR(val)           bfin_write16(FIO0_POLAR,val)
+#define bfin_read_FIO0_EDGE()                bfin_read16(FIO0_EDGE)
+#define bfin_write_FIO0_EDGE(val)            bfin_write16(FIO0_EDGE,val)
+#define bfin_read_FIO0_BOTH()                bfin_read16(FIO0_BOTH)
+#define bfin_write_FIO0_BOTH(val)            bfin_write16(FIO0_BOTH,val)
+#define bfin_read_FIO0_INEN()                bfin_read16(FIO0_INEN)
+#define bfin_write_FIO0_INEN(val)            bfin_write16(FIO0_INEN,val)
+/* Programmable Flag 1 registers (0xFFC0 1500-0xFFC0 15FF) */
+#define bfin_read_FIO1_FLAG_D()              bfin_read16(FIO1_FLAG_D)
+#define bfin_write_FIO1_FLAG_D(val)          bfin_write16(FIO1_FLAG_D,val)
+#define bfin_read_FIO1_FLAG_C()              bfin_read16(FIO1_FLAG_C)
+#define bfin_write_FIO1_FLAG_C(val)          bfin_write16(FIO1_FLAG_C,val)
+#define bfin_read_FIO1_FLAG_S()              bfin_read16(FIO1_FLAG_S)
+#define bfin_write_FIO1_FLAG_S(val)          bfin_write16(FIO1_FLAG_S,val)
+#define bfin_read_FIO1_FLAG_T()              bfin_read16(FIO1_FLAG_T)
+#define bfin_write_FIO1_FLAG_T(val)          bfin_write16(FIO1_FLAG_T,val)
+#define bfin_read_FIO1_MASKA_D()             bfin_read16(FIO1_MASKA_D)
+#define bfin_write_FIO1_MASKA_D(val)         bfin_write16(FIO1_MASKA_D,val)
+#define bfin_read_FIO1_MASKA_C()             bfin_read16(FIO1_MASKA_C)
+#define bfin_write_FIO1_MASKA_C(val)         bfin_write16(FIO1_MASKA_C,val)
+#define bfin_read_FIO1_MASKA_S()             bfin_read16(FIO1_MASKA_S)
+#define bfin_write_FIO1_MASKA_S(val)         bfin_write16(FIO1_MASKA_S,val)
+#define bfin_read_FIO1_MASKA_T()             bfin_read16(FIO1_MASKA_T)
+#define bfin_write_FIO1_MASKA_T(val)         bfin_write16(FIO1_MASKA_T,val)
+#define bfin_read_FIO1_MASKB_D()             bfin_read16(FIO1_MASKB_D)
+#define bfin_write_FIO1_MASKB_D(val)         bfin_write16(FIO1_MASKB_D,val)
+#define bfin_read_FIO1_MASKB_C()             bfin_read16(FIO1_MASKB_C)
+#define bfin_write_FIO1_MASKB_C(val)         bfin_write16(FIO1_MASKB_C,val)
+#define bfin_read_FIO1_MASKB_S()             bfin_read16(FIO1_MASKB_S)
+#define bfin_write_FIO1_MASKB_S(val)         bfin_write16(FIO1_MASKB_S,val)
+#define bfin_read_FIO1_MASKB_T()             bfin_read16(FIO1_MASKB_T)
+#define bfin_write_FIO1_MASKB_T(val)         bfin_write16(FIO1_MASKB_T,val)
+#define bfin_read_FIO1_DIR()                 bfin_read16(FIO1_DIR)
+#define bfin_write_FIO1_DIR(val)             bfin_write16(FIO1_DIR,val)
+#define bfin_read_FIO1_POLAR()               bfin_read16(FIO1_POLAR)
+#define bfin_write_FIO1_POLAR(val)           bfin_write16(FIO1_POLAR,val)
+#define bfin_read_FIO1_EDGE()                bfin_read16(FIO1_EDGE)
+#define bfin_write_FIO1_EDGE(val)            bfin_write16(FIO1_EDGE,val)
+#define bfin_read_FIO1_BOTH()                bfin_read16(FIO1_BOTH)
+#define bfin_write_FIO1_BOTH(val)            bfin_write16(FIO1_BOTH,val)
+#define bfin_read_FIO1_INEN()                bfin_read16(FIO1_INEN)
+#define bfin_write_FIO1_INEN(val)            bfin_write16(FIO1_INEN,val)
+/* Programmable Flag registers (0xFFC0 1700-0xFFC0 17FF) */
+#define bfin_read_FIO2_FLAG_D()              bfin_read16(FIO2_FLAG_D)
+#define bfin_write_FIO2_FLAG_D(val)          bfin_write16(FIO2_FLAG_D,val)
+#define bfin_read_FIO2_FLAG_C()              bfin_read16(FIO2_FLAG_C)
+#define bfin_write_FIO2_FLAG_C(val)          bfin_write16(FIO2_FLAG_C,val)
+#define bfin_read_FIO2_FLAG_S()              bfin_read16(FIO2_FLAG_S)
+#define bfin_write_FIO2_FLAG_S(val)          bfin_write16(FIO2_FLAG_S,val)
+#define bfin_read_FIO2_FLAG_T()              bfin_read16(FIO2_FLAG_T)
+#define bfin_write_FIO2_FLAG_T(val)          bfin_write16(FIO2_FLAG_T,val)
+#define bfin_read_FIO2_MASKA_D()             bfin_read16(FIO2_MASKA_D)
+#define bfin_write_FIO2_MASKA_D(val)         bfin_write16(FIO2_MASKA_D,val)
+#define bfin_read_FIO2_MASKA_C()             bfin_read16(FIO2_MASKA_C)
+#define bfin_write_FIO2_MASKA_C(val)         bfin_write16(FIO2_MASKA_C,val)
+#define bfin_read_FIO2_MASKA_S()             bfin_read16(FIO2_MASKA_S)
+#define bfin_write_FIO2_MASKA_S(val)         bfin_write16(FIO2_MASKA_S,val)
+#define bfin_read_FIO2_MASKA_T()             bfin_read16(FIO2_MASKA_T)
+#define bfin_write_FIO2_MASKA_T(val)         bfin_write16(FIO2_MASKA_T,val)
+#define bfin_read_FIO2_MASKB_D()             bfin_read16(FIO2_MASKB_D)
+#define bfin_write_FIO2_MASKB_D(val)         bfin_write16(FIO2_MASKB_D,val)
+#define bfin_read_FIO2_MASKB_C()             bfin_read16(FIO2_MASKB_C)
+#define bfin_write_FIO2_MASKB_C(val)         bfin_write16(FIO2_MASKB_C,val)
+#define bfin_read_FIO2_MASKB_S()             bfin_read16(FIO2_MASKB_S)
+#define bfin_write_FIO2_MASKB_S(val)         bfin_write16(FIO2_MASKB_S,val)
+#define bfin_read_FIO2_MASKB_T()             bfin_read16(FIO2_MASKB_T)
+#define bfin_write_FIO2_MASKB_T(val)         bfin_write16(FIO2_MASKB_T,val)
+#define bfin_read_FIO2_DIR()                 bfin_read16(FIO2_DIR)
+#define bfin_write_FIO2_DIR(val)             bfin_write16(FIO2_DIR,val)
+#define bfin_read_FIO2_POLAR()               bfin_read16(FIO2_POLAR)
+#define bfin_write_FIO2_POLAR(val)           bfin_write16(FIO2_POLAR,val)
+#define bfin_read_FIO2_EDGE()                bfin_read16(FIO2_EDGE)
+#define bfin_write_FIO2_EDGE(val)            bfin_write16(FIO2_EDGE,val)
+#define bfin_read_FIO2_BOTH()                bfin_read16(FIO2_BOTH)
+#define bfin_write_FIO2_BOTH(val)            bfin_write16(FIO2_BOTH,val)
+#define bfin_read_FIO2_INEN()                bfin_read16(FIO2_INEN)
+#define bfin_write_FIO2_INEN(val)            bfin_write16(FIO2_INEN,val)
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define bfin_read_SPORT0_TCR1()              bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)          bfin_write16(SPORT0_TCR1,val)
+#define bfin_read_SPORT0_TCR2()              bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)          bfin_write16(SPORT0_TCR2,val)
+#define bfin_read_SPORT0_TCLKDIV()           bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)       bfin_write16(SPORT0_TCLKDIV,val)
+#define bfin_read_SPORT0_TFSDIV()            bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)        bfin_write16(SPORT0_TFSDIV,val)
+#define bfin_read_SPORT0_TX()                bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)            bfin_write32(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX()                bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)            bfin_write32(SPORT0_RX,val)
+#define bfin_read_SPORT0_TX32()              bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)          bfin_write32(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX32()              bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)          bfin_write32(SPORT0_RX,val)
+#define bfin_read_SPORT0_TX16()              bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)          bfin_write16(SPORT0_TX,val)
+#define bfin_read_SPORT0_RX16()              bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)          bfin_write16(SPORT0_RX,val)
+#define bfin_read_SPORT0_RCR1()              bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)          bfin_write16(SPORT0_RCR1,val)
+#define bfin_read_SPORT0_RCR2()              bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)          bfin_write16(SPORT0_RCR2,val)
+#define bfin_read_SPORT0_RCLKDIV()           bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)       bfin_write16(SPORT0_RCLKDIV,val)
+#define bfin_read_SPORT0_RFSDIV()            bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)        bfin_write16(SPORT0_RFSDIV,val)
+#define bfin_read_SPORT0_STAT()              bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)          bfin_write16(SPORT0_STAT,val)
+#define bfin_read_SPORT0_CHNL()              bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)          bfin_write16(SPORT0_CHNL,val)
+#define bfin_read_SPORT0_MCMC1()             bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)         bfin_write16(SPORT0_MCMC1,val)
+#define bfin_read_SPORT0_MCMC2()             bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)         bfin_write16(SPORT0_MCMC2,val)
+#define bfin_read_SPORT0_MTCS0()             bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)         bfin_write32(SPORT0_MTCS0,val)
+#define bfin_read_SPORT0_MTCS1()             bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)         bfin_write32(SPORT0_MTCS1,val)
+#define bfin_read_SPORT0_MTCS2()             bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)         bfin_write32(SPORT0_MTCS2,val)
+#define bfin_read_SPORT0_MTCS3()             bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)         bfin_write32(SPORT0_MTCS3,val)
+#define bfin_read_SPORT0_MRCS0()             bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)         bfin_write32(SPORT0_MRCS0,val)
+#define bfin_read_SPORT0_MRCS1()             bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)         bfin_write32(SPORT0_MRCS1,val)
+#define bfin_read_SPORT0_MRCS2()             bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)         bfin_write32(SPORT0_MRCS2,val)
+#define bfin_read_SPORT0_MRCS3()             bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)         bfin_write32(SPORT0_MRCS3,val)
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define bfin_read_SPORT1_TCR1()              bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)          bfin_write16(SPORT1_TCR1,val)
+#define bfin_read_SPORT1_TCR2()              bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)          bfin_write16(SPORT1_TCR2,val)
+#define bfin_read_SPORT1_TCLKDIV()           bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)       bfin_write16(SPORT1_TCLKDIV,val)
+#define bfin_read_SPORT1_TFSDIV()            bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)        bfin_write16(SPORT1_TFSDIV,val)
+#define bfin_read_SPORT1_TX()                bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)            bfin_write32(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX()                bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)            bfin_write32(SPORT1_RX,val)
+#define bfin_read_SPORT1_TX32()              bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)          bfin_write32(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX32()              bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)          bfin_write32(SPORT1_RX,val)
+#define bfin_read_SPORT1_TX16()              bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)          bfin_write16(SPORT1_TX,val)
+#define bfin_read_SPORT1_RX16()              bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)          bfin_write16(SPORT1_RX,val)
+#define bfin_read_SPORT1_RCR1()              bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)          bfin_write16(SPORT1_RCR1,val)
+#define bfin_read_SPORT1_RCR2()              bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)          bfin_write16(SPORT1_RCR2,val)
+#define bfin_read_SPORT1_RCLKDIV()           bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)       bfin_write16(SPORT1_RCLKDIV,val)
+#define bfin_read_SPORT1_RFSDIV()            bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)        bfin_write16(SPORT1_RFSDIV,val)
+#define bfin_read_SPORT1_STAT()              bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)          bfin_write16(SPORT1_STAT,val)
+#define bfin_read_SPORT1_CHNL()              bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)          bfin_write16(SPORT1_CHNL,val)
+#define bfin_read_SPORT1_MCMC1()             bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)         bfin_write16(SPORT1_MCMC1,val)
+#define bfin_read_SPORT1_MCMC2()             bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)         bfin_write16(SPORT1_MCMC2,val)
+#define bfin_read_SPORT1_MTCS0()             bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)         bfin_write32(SPORT1_MTCS0,val)
+#define bfin_read_SPORT1_MTCS1()             bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)         bfin_write32(SPORT1_MTCS1,val)
+#define bfin_read_SPORT1_MTCS2()             bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)         bfin_write32(SPORT1_MTCS2,val)
+#define bfin_read_SPORT1_MTCS3()             bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)         bfin_write32(SPORT1_MTCS3,val)
+#define bfin_read_SPORT1_MRCS0()             bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)         bfin_write32(SPORT1_MRCS0,val)
+#define bfin_read_SPORT1_MRCS1()             bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)         bfin_write32(SPORT1_MRCS1,val)
+#define bfin_read_SPORT1_MRCS2()             bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)         bfin_write32(SPORT1_MRCS2,val)
+#define bfin_read_SPORT1_MRCS3()             bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)         bfin_write32(SPORT1_MRCS3,val)
+/* Asynchronous Memory Controller - External Bus Interface Unit */
+#define bfin_read_EBIU_AMGCTL()              bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)          bfin_write16(EBIU_AMGCTL,val)
+#define bfin_read_EBIU_AMBCTL0()             bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)         bfin_write32(EBIU_AMBCTL0,val)
+#define bfin_read_EBIU_AMBCTL1()             bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)         bfin_write32(EBIU_AMBCTL1,val)
+/* SDRAM Controller External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+#define bfin_read_EBIU_SDGCTL()              bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val)          bfin_write32(EBIU_SDGCTL,val)
+#define bfin_read_EBIU_SDBCTL()              bfin_read32(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val)          bfin_write32(EBIU_SDBCTL,val)
+#define bfin_read_EBIU_SDRRC()               bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val)           bfin_write16(EBIU_SDRRC,val)
+#define bfin_read_EBIU_SDSTAT()              bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val)          bfin_write16(EBIU_SDSTAT,val)
+/* Parallel Peripheral Interface (PPI) 0 registers (0xFFC0 1000-0xFFC0 10FF) */
+#define bfin_read_PPI0_CONTROL()             bfin_read16(PPI0_CONTROL)
+#define bfin_write_PPI0_CONTROL(val)         bfin_write16(PPI0_CONTROL,val)
+#define bfin_read_PPI0_STATUS()              bfin_read16(PPI0_STATUS)
+#define bfin_write_PPI0_STATUS(val)          bfin_write16(PPI0_STATUS,val)
+#define bfin_read_PPI0_COUNT()               bfin_read16(PPI0_COUNT)
+#define bfin_write_PPI0_COUNT(val)           bfin_write16(PPI0_COUNT,val)
+#define bfin_read_PPI0_DELAY()               bfin_read16(PPI0_DELAY)
+#define bfin_write_PPI0_DELAY(val)           bfin_write16(PPI0_DELAY,val)
+#define bfin_read_PPI0_FRAME()               bfin_read16(PPI0_FRAME)
+#define bfin_write_PPI0_FRAME(val)           bfin_write16(PPI0_FRAME,val)
+/* Parallel Peripheral Interface (PPI) 1 registers (0xFFC0 1300-0xFFC0 13FF) */
+#define bfin_read_PPI1_CONTROL()             bfin_read16(PPI1_CONTROL)
+#define bfin_write_PPI1_CONTROL(val)         bfin_write16(PPI1_CONTROL,val)
+#define bfin_read_PPI1_STATUS()              bfin_read16(PPI1_STATUS)
+#define bfin_write_PPI1_STATUS(val)          bfin_write16(PPI1_STATUS,val)
+#define bfin_read_PPI1_COUNT()               bfin_read16(PPI1_COUNT)
+#define bfin_write_PPI1_COUNT(val)           bfin_write16(PPI1_COUNT,val)
+#define bfin_read_PPI1_DELAY()               bfin_read16(PPI1_DELAY)
+#define bfin_write_PPI1_DELAY(val)           bfin_write16(PPI1_DELAY,val)
+#define bfin_read_PPI1_FRAME()               bfin_read16(PPI1_FRAME)
+#define bfin_write_PPI1_FRAME(val)           bfin_write16(PPI1_FRAME,val)
+/*DMA traffic control registers */
+#define bfin_read_DMA1_TC_PER()              bfin_read16(DMA1_TC_PER)
+#define bfin_write_DMA1_TC_PER(val)          bfin_write16(DMA1_TC_PER,val)
+#define bfin_read_DMA1_TC_CNT()              bfin_read16(DMA1_TC_CNT)
+#define bfin_write_DMA1_TC_CNT(val)          bfin_write16(DMA1_TC_CNT,val)
+#define bfin_read_DMA2_TC_PER()              bfin_read16(DMA2_TC_PER)
+#define bfin_write_DMA2_TC_PER(val)          bfin_write16(DMA2_TC_PER,val)
+#define bfin_read_DMA2_TC_CNT()              bfin_read16(DMA2_TC_CNT)
+#define bfin_write_DMA2_TC_CNT(val)          bfin_write16(DMA2_TC_CNT,val)
+/* DMA1 Controller registers (0xFFC0 1C00-0xFFC0 1FFF) */
+#define bfin_read_DMA1_0_CONFIG()            bfin_read16(DMA1_0_CONFIG)
+#define bfin_write_DMA1_0_CONFIG(val)        bfin_write16(DMA1_0_CONFIG,val)
+#define bfin_read_DMA1_0_NEXT_DESC_PTR()     bfin_read32(DMA1_0_NEXT_DESC_PTR)
+#define bfin_write_DMA1_0_NEXT_DESC_PTR(val) bfin_write32(DMA1_0_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_0_START_ADDR()        bfin_read32(DMA1_0_START_ADDR)
+#define bfin_write_DMA1_0_START_ADDR(val)    bfin_write32(DMA1_0_START_ADDR,val)
+#define bfin_read_DMA1_0_X_COUNT()           bfin_read16(DMA1_0_X_COUNT)
+#define bfin_write_DMA1_0_X_COUNT(val)       bfin_write16(DMA1_0_X_COUNT,val)
+#define bfin_read_DMA1_0_Y_COUNT()           bfin_read16(DMA1_0_Y_COUNT)
+#define bfin_write_DMA1_0_Y_COUNT(val)       bfin_write16(DMA1_0_Y_COUNT,val)
+#define bfin_read_DMA1_0_X_MODIFY()          bfin_read16(DMA1_0_X_MODIFY)
+#define bfin_write_DMA1_0_X_MODIFY(val)      bfin_write16(DMA1_0_X_MODIFY,val)
+#define bfin_read_DMA1_0_Y_MODIFY()          bfin_read16(DMA1_0_Y_MODIFY)
+#define bfin_write_DMA1_0_Y_MODIFY(val)      bfin_write16(DMA1_0_Y_MODIFY,val)
+#define bfin_read_DMA1_0_CURR_DESC_PTR()     bfin_read32(DMA1_0_CURR_DESC_PTR)
+#define bfin_write_DMA1_0_CURR_DESC_PTR(val) bfin_write32(DMA1_0_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_0_CURR_ADDR()         bfin_read32(DMA1_0_CURR_ADDR)
+#define bfin_write_DMA1_0_CURR_ADDR(val)     bfin_write32(DMA1_0_CURR_ADDR,val)
+#define bfin_read_DMA1_0_CURR_X_COUNT()      bfin_read16(DMA1_0_CURR_X_COUNT)
+#define bfin_write_DMA1_0_CURR_X_COUNT(val)  bfin_write16(DMA1_0_CURR_X_COUNT,val)
+#define bfin_read_DMA1_0_CURR_Y_COUNT()      bfin_read16(DMA1_0_CURR_Y_COUNT)
+#define bfin_write_DMA1_0_CURR_Y_COUNT(val)  bfin_write16(DMA1_0_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_0_IRQ_STATUS()        bfin_read16(DMA1_0_IRQ_STATUS)
+#define bfin_write_DMA1_0_IRQ_STATUS(val)    bfin_write16(DMA1_0_IRQ_STATUS,val)
+#define bfin_read_DMA1_0_PERIPHERAL_MAP()    bfin_read16(DMA1_0_PERIPHERAL_MAP)
+#define bfin_write_DMA1_0_PERIPHERAL_MAP(val) bfin_write16(DMA1_0_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_1_CONFIG()            bfin_read16(DMA1_1_CONFIG)
+#define bfin_write_DMA1_1_CONFIG(val)        bfin_write16(DMA1_1_CONFIG,val)
+#define bfin_read_DMA1_1_NEXT_DESC_PTR()     bfin_read32(DMA1_1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_1_NEXT_DESC_PTR(val) bfin_write32(DMA1_1_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_1_START_ADDR()        bfin_read32(DMA1_1_START_ADDR)
+#define bfin_write_DMA1_1_START_ADDR(val)    bfin_write32(DMA1_1_START_ADDR,val)
+#define bfin_read_DMA1_1_X_COUNT()           bfin_read16(DMA1_1_X_COUNT)
+#define bfin_write_DMA1_1_X_COUNT(val)       bfin_write16(DMA1_1_X_COUNT,val)
+#define bfin_read_DMA1_1_Y_COUNT()           bfin_read16(DMA1_1_Y_COUNT)
+#define bfin_write_DMA1_1_Y_COUNT(val)       bfin_write16(DMA1_1_Y_COUNT,val)
+#define bfin_read_DMA1_1_X_MODIFY()          bfin_read16(DMA1_1_X_MODIFY)
+#define bfin_write_DMA1_1_X_MODIFY(val)      bfin_write16(DMA1_1_X_MODIFY,val)
+#define bfin_read_DMA1_1_Y_MODIFY()          bfin_read16(DMA1_1_Y_MODIFY)
+#define bfin_write_DMA1_1_Y_MODIFY(val)      bfin_write16(DMA1_1_Y_MODIFY,val)
+#define bfin_read_DMA1_1_CURR_DESC_PTR()     bfin_read32(DMA1_1_CURR_DESC_PTR)
+#define bfin_write_DMA1_1_CURR_DESC_PTR(val) bfin_write32(DMA1_1_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_1_CURR_ADDR()         bfin_read32(DMA1_1_CURR_ADDR)
+#define bfin_write_DMA1_1_CURR_ADDR(val)     bfin_write32(DMA1_1_CURR_ADDR,val)
+#define bfin_read_DMA1_1_CURR_X_COUNT()      bfin_read16(DMA1_1_CURR_X_COUNT)
+#define bfin_write_DMA1_1_CURR_X_COUNT(val)  bfin_write16(DMA1_1_CURR_X_COUNT,val)
+#define bfin_read_DMA1_1_CURR_Y_COUNT()      bfin_read16(DMA1_1_CURR_Y_COUNT)
+#define bfin_write_DMA1_1_CURR_Y_COUNT(val)  bfin_write16(DMA1_1_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_1_IRQ_STATUS()        bfin_read16(DMA1_1_IRQ_STATUS)
+#define bfin_write_DMA1_1_IRQ_STATUS(val)    bfin_write16(DMA1_1_IRQ_STATUS,val)
+#define bfin_read_DMA1_1_PERIPHERAL_MAP()    bfin_read16(DMA1_1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_1_PERIPHERAL_MAP(val) bfin_write16(DMA1_1_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_2_CONFIG()            bfin_read16(DMA1_2_CONFIG)
+#define bfin_write_DMA1_2_CONFIG(val)        bfin_write16(DMA1_2_CONFIG,val)
+#define bfin_read_DMA1_2_NEXT_DESC_PTR()     bfin_read32(DMA1_2_NEXT_DESC_PTR)
+#define bfin_write_DMA1_2_NEXT_DESC_PTR(val) bfin_write32(DMA1_2_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_2_START_ADDR()        bfin_read32(DMA1_2_START_ADDR)
+#define bfin_write_DMA1_2_START_ADDR(val)    bfin_write32(DMA1_2_START_ADDR,val)
+#define bfin_read_DMA1_2_X_COUNT()           bfin_read16(DMA1_2_X_COUNT)
+#define bfin_write_DMA1_2_X_COUNT(val)       bfin_write16(DMA1_2_X_COUNT,val)
+#define bfin_read_DMA1_2_Y_COUNT()           bfin_read16(DMA1_2_Y_COUNT)
+#define bfin_write_DMA1_2_Y_COUNT(val)       bfin_write16(DMA1_2_Y_COUNT,val)
+#define bfin_read_DMA1_2_X_MODIFY()          bfin_read16(DMA1_2_X_MODIFY)
+#define bfin_write_DMA1_2_X_MODIFY(val)      bfin_write16(DMA1_2_X_MODIFY,val)
+#define bfin_read_DMA1_2_Y_MODIFY()          bfin_read16(DMA1_2_Y_MODIFY)
+#define bfin_write_DMA1_2_Y_MODIFY(val)      bfin_write16(DMA1_2_Y_MODIFY,val)
+#define bfin_read_DMA1_2_CURR_DESC_PTR()     bfin_read32(DMA1_2_CURR_DESC_PTR)
+#define bfin_write_DMA1_2_CURR_DESC_PTR(val) bfin_write32(DMA1_2_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_2_CURR_ADDR()         bfin_read32(DMA1_2_CURR_ADDR)
+#define bfin_write_DMA1_2_CURR_ADDR(val)     bfin_write32(DMA1_2_CURR_ADDR,val)
+#define bfin_read_DMA1_2_CURR_X_COUNT()      bfin_read16(DMA1_2_CURR_X_COUNT)
+#define bfin_write_DMA1_2_CURR_X_COUNT(val)  bfin_write16(DMA1_2_CURR_X_COUNT,val)
+#define bfin_read_DMA1_2_CURR_Y_COUNT()      bfin_read16(DMA1_2_CURR_Y_COUNT)
+#define bfin_write_DMA1_2_CURR_Y_COUNT(val)  bfin_write16(DMA1_2_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_2_IRQ_STATUS()        bfin_read16(DMA1_2_IRQ_STATUS)
+#define bfin_write_DMA1_2_IRQ_STATUS(val)    bfin_write16(DMA1_2_IRQ_STATUS,val)
+#define bfin_read_DMA1_2_PERIPHERAL_MAP()    bfin_read16(DMA1_2_PERIPHERAL_MAP)
+#define bfin_write_DMA1_2_PERIPHERAL_MAP(val) bfin_write16(DMA1_2_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_3_CONFIG()            bfin_read16(DMA1_3_CONFIG)
+#define bfin_write_DMA1_3_CONFIG(val)        bfin_write16(DMA1_3_CONFIG,val)
+#define bfin_read_DMA1_3_NEXT_DESC_PTR()     bfin_read32(DMA1_3_NEXT_DESC_PTR)
+#define bfin_write_DMA1_3_NEXT_DESC_PTR(val) bfin_write32(DMA1_3_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_3_START_ADDR()        bfin_read32(DMA1_3_START_ADDR)
+#define bfin_write_DMA1_3_START_ADDR(val)    bfin_write32(DMA1_3_START_ADDR,val)
+#define bfin_read_DMA1_3_X_COUNT()           bfin_read16(DMA1_3_X_COUNT)
+#define bfin_write_DMA1_3_X_COUNT(val)       bfin_write16(DMA1_3_X_COUNT,val)
+#define bfin_read_DMA1_3_Y_COUNT()           bfin_read16(DMA1_3_Y_COUNT)
+#define bfin_write_DMA1_3_Y_COUNT(val)       bfin_write16(DMA1_3_Y_COUNT,val)
+#define bfin_read_DMA1_3_X_MODIFY()          bfin_read16(DMA1_3_X_MODIFY)
+#define bfin_write_DMA1_3_X_MODIFY(val)      bfin_write16(DMA1_3_X_MODIFY,val)
+#define bfin_read_DMA1_3_Y_MODIFY()          bfin_read16(DMA1_3_Y_MODIFY)
+#define bfin_write_DMA1_3_Y_MODIFY(val)      bfin_write16(DMA1_3_Y_MODIFY,val)
+#define bfin_read_DMA1_3_CURR_DESC_PTR()     bfin_read32(DMA1_3_CURR_DESC_PTR)
+#define bfin_write_DMA1_3_CURR_DESC_PTR(val) bfin_write32(DMA1_3_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_3_CURR_ADDR()         bfin_read32(DMA1_3_CURR_ADDR)
+#define bfin_write_DMA1_3_CURR_ADDR(val)     bfin_write32(DMA1_3_CURR_ADDR,val)
+#define bfin_read_DMA1_3_CURR_X_COUNT()      bfin_read16(DMA1_3_CURR_X_COUNT)
+#define bfin_write_DMA1_3_CURR_X_COUNT(val)  bfin_write16(DMA1_3_CURR_X_COUNT,val)
+#define bfin_read_DMA1_3_CURR_Y_COUNT()      bfin_read16(DMA1_3_CURR_Y_COUNT)
+#define bfin_write_DMA1_3_CURR_Y_COUNT(val)  bfin_write16(DMA1_3_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_3_IRQ_STATUS()        bfin_read16(DMA1_3_IRQ_STATUS)
+#define bfin_write_DMA1_3_IRQ_STATUS(val)    bfin_write16(DMA1_3_IRQ_STATUS,val)
+#define bfin_read_DMA1_3_PERIPHERAL_MAP()    bfin_read16(DMA1_3_PERIPHERAL_MAP)
+#define bfin_write_DMA1_3_PERIPHERAL_MAP(val) bfin_write16(DMA1_3_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_4_CONFIG()            bfin_read16(DMA1_4_CONFIG)
+#define bfin_write_DMA1_4_CONFIG(val)        bfin_write16(DMA1_4_CONFIG,val)
+#define bfin_read_DMA1_4_NEXT_DESC_PTR()     bfin_read32(DMA1_4_NEXT_DESC_PTR)
+#define bfin_write_DMA1_4_NEXT_DESC_PTR(val) bfin_write32(DMA1_4_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_4_START_ADDR()        bfin_read32(DMA1_4_START_ADDR)
+#define bfin_write_DMA1_4_START_ADDR(val)    bfin_write32(DMA1_4_START_ADDR,val)
+#define bfin_read_DMA1_4_X_COUNT()           bfin_read16(DMA1_4_X_COUNT)
+#define bfin_write_DMA1_4_X_COUNT(val)       bfin_write16(DMA1_4_X_COUNT,val)
+#define bfin_read_DMA1_4_Y_COUNT()           bfin_read16(DMA1_4_Y_COUNT)
+#define bfin_write_DMA1_4_Y_COUNT(val)       bfin_write16(DMA1_4_Y_COUNT,val)
+#define bfin_read_DMA1_4_X_MODIFY()          bfin_read16(DMA1_4_X_MODIFY)
+#define bfin_write_DMA1_4_X_MODIFY(val)      bfin_write16(DMA1_4_X_MODIFY,val)
+#define bfin_read_DMA1_4_Y_MODIFY()          bfin_read16(DMA1_4_Y_MODIFY)
+#define bfin_write_DMA1_4_Y_MODIFY(val)      bfin_write16(DMA1_4_Y_MODIFY,val)
+#define bfin_read_DMA1_4_CURR_DESC_PTR()     bfin_read32(DMA1_4_CURR_DESC_PTR)
+#define bfin_write_DMA1_4_CURR_DESC_PTR(val) bfin_write32(DMA1_4_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_4_CURR_ADDR()         bfin_read32(DMA1_4_CURR_ADDR)
+#define bfin_write_DMA1_4_CURR_ADDR(val)     bfin_write32(DMA1_4_CURR_ADDR,val)
+#define bfin_read_DMA1_4_CURR_X_COUNT()      bfin_read16(DMA1_4_CURR_X_COUNT)
+#define bfin_write_DMA1_4_CURR_X_COUNT(val)  bfin_write16(DMA1_4_CURR_X_COUNT,val)
+#define bfin_read_DMA1_4_CURR_Y_COUNT()      bfin_read16(DMA1_4_CURR_Y_COUNT)
+#define bfin_write_DMA1_4_CURR_Y_COUNT(val)  bfin_write16(DMA1_4_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_4_IRQ_STATUS()        bfin_read16(DMA1_4_IRQ_STATUS)
+#define bfin_write_DMA1_4_IRQ_STATUS(val)    bfin_write16(DMA1_4_IRQ_STATUS,val)
+#define bfin_read_DMA1_4_PERIPHERAL_MAP()    bfin_read16(DMA1_4_PERIPHERAL_MAP)
+#define bfin_write_DMA1_4_PERIPHERAL_MAP(val) bfin_write16(DMA1_4_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_5_CONFIG()            bfin_read16(DMA1_5_CONFIG)
+#define bfin_write_DMA1_5_CONFIG(val)        bfin_write16(DMA1_5_CONFIG,val)
+#define bfin_read_DMA1_5_NEXT_DESC_PTR()     bfin_read32(DMA1_5_NEXT_DESC_PTR)
+#define bfin_write_DMA1_5_NEXT_DESC_PTR(val) bfin_write32(DMA1_5_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_5_START_ADDR()        bfin_read32(DMA1_5_START_ADDR)
+#define bfin_write_DMA1_5_START_ADDR(val)    bfin_write32(DMA1_5_START_ADDR,val)
+#define bfin_read_DMA1_5_X_COUNT()           bfin_read16(DMA1_5_X_COUNT)
+#define bfin_write_DMA1_5_X_COUNT(val)       bfin_write16(DMA1_5_X_COUNT,val)
+#define bfin_read_DMA1_5_Y_COUNT()           bfin_read16(DMA1_5_Y_COUNT)
+#define bfin_write_DMA1_5_Y_COUNT(val)       bfin_write16(DMA1_5_Y_COUNT,val)
+#define bfin_read_DMA1_5_X_MODIFY()          bfin_read16(DMA1_5_X_MODIFY)
+#define bfin_write_DMA1_5_X_MODIFY(val)      bfin_write16(DMA1_5_X_MODIFY,val)
+#define bfin_read_DMA1_5_Y_MODIFY()          bfin_read16(DMA1_5_Y_MODIFY)
+#define bfin_write_DMA1_5_Y_MODIFY(val)      bfin_write16(DMA1_5_Y_MODIFY,val)
+#define bfin_read_DMA1_5_CURR_DESC_PTR()     bfin_read32(DMA1_5_CURR_DESC_PTR)
+#define bfin_write_DMA1_5_CURR_DESC_PTR(val) bfin_write32(DMA1_5_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_5_CURR_ADDR()         bfin_read32(DMA1_5_CURR_ADDR)
+#define bfin_write_DMA1_5_CURR_ADDR(val)     bfin_write32(DMA1_5_CURR_ADDR,val)
+#define bfin_read_DMA1_5_CURR_X_COUNT()      bfin_read16(DMA1_5_CURR_X_COUNT)
+#define bfin_write_DMA1_5_CURR_X_COUNT(val)  bfin_write16(DMA1_5_CURR_X_COUNT,val)
+#define bfin_read_DMA1_5_CURR_Y_COUNT()      bfin_read16(DMA1_5_CURR_Y_COUNT)
+#define bfin_write_DMA1_5_CURR_Y_COUNT(val)  bfin_write16(DMA1_5_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_5_IRQ_STATUS()        bfin_read16(DMA1_5_IRQ_STATUS)
+#define bfin_write_DMA1_5_IRQ_STATUS(val)    bfin_write16(DMA1_5_IRQ_STATUS,val)
+#define bfin_read_DMA1_5_PERIPHERAL_MAP()    bfin_read16(DMA1_5_PERIPHERAL_MAP)
+#define bfin_write_DMA1_5_PERIPHERAL_MAP(val) bfin_write16(DMA1_5_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_6_CONFIG()            bfin_read16(DMA1_6_CONFIG)
+#define bfin_write_DMA1_6_CONFIG(val)        bfin_write16(DMA1_6_CONFIG,val)
+#define bfin_read_DMA1_6_NEXT_DESC_PTR()     bfin_read32(DMA1_6_NEXT_DESC_PTR)
+#define bfin_write_DMA1_6_NEXT_DESC_PTR(val) bfin_write32(DMA1_6_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_6_START_ADDR()        bfin_read32(DMA1_6_START_ADDR)
+#define bfin_write_DMA1_6_START_ADDR(val)    bfin_write32(DMA1_6_START_ADDR,val)
+#define bfin_read_DMA1_6_X_COUNT()           bfin_read16(DMA1_6_X_COUNT)
+#define bfin_write_DMA1_6_X_COUNT(val)       bfin_write16(DMA1_6_X_COUNT,val)
+#define bfin_read_DMA1_6_Y_COUNT()           bfin_read16(DMA1_6_Y_COUNT)
+#define bfin_write_DMA1_6_Y_COUNT(val)       bfin_write16(DMA1_6_Y_COUNT,val)
+#define bfin_read_DMA1_6_X_MODIFY()          bfin_read16(DMA1_6_X_MODIFY)
+#define bfin_write_DMA1_6_X_MODIFY(val)      bfin_write16(DMA1_6_X_MODIFY,val)
+#define bfin_read_DMA1_6_Y_MODIFY()          bfin_read16(DMA1_6_Y_MODIFY)
+#define bfin_write_DMA1_6_Y_MODIFY(val)      bfin_write16(DMA1_6_Y_MODIFY,val)
+#define bfin_read_DMA1_6_CURR_DESC_PTR()     bfin_read32(DMA1_6_CURR_DESC_PTR)
+#define bfin_write_DMA1_6_CURR_DESC_PTR(val) bfin_write32(DMA1_6_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_6_CURR_ADDR()         bfin_read32(DMA1_6_CURR_ADDR)
+#define bfin_write_DMA1_6_CURR_ADDR(val)     bfin_write32(DMA1_6_CURR_ADDR,val)
+#define bfin_read_DMA1_6_CURR_X_COUNT()      bfin_read16(DMA1_6_CURR_X_COUNT)
+#define bfin_write_DMA1_6_CURR_X_COUNT(val)  bfin_write16(DMA1_6_CURR_X_COUNT,val)
+#define bfin_read_DMA1_6_CURR_Y_COUNT()      bfin_read16(DMA1_6_CURR_Y_COUNT)
+#define bfin_write_DMA1_6_CURR_Y_COUNT(val)  bfin_write16(DMA1_6_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_6_IRQ_STATUS()        bfin_read16(DMA1_6_IRQ_STATUS)
+#define bfin_write_DMA1_6_IRQ_STATUS(val)    bfin_write16(DMA1_6_IRQ_STATUS,val)
+#define bfin_read_DMA1_6_PERIPHERAL_MAP()    bfin_read16(DMA1_6_PERIPHERAL_MAP)
+#define bfin_write_DMA1_6_PERIPHERAL_MAP(val) bfin_write16(DMA1_6_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_7_CONFIG()            bfin_read16(DMA1_7_CONFIG)
+#define bfin_write_DMA1_7_CONFIG(val)        bfin_write16(DMA1_7_CONFIG,val)
+#define bfin_read_DMA1_7_NEXT_DESC_PTR()     bfin_read32(DMA1_7_NEXT_DESC_PTR)
+#define bfin_write_DMA1_7_NEXT_DESC_PTR(val) bfin_write32(DMA1_7_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_7_START_ADDR()        bfin_read32(DMA1_7_START_ADDR)
+#define bfin_write_DMA1_7_START_ADDR(val)    bfin_write32(DMA1_7_START_ADDR,val)
+#define bfin_read_DMA1_7_X_COUNT()           bfin_read16(DMA1_7_X_COUNT)
+#define bfin_write_DMA1_7_X_COUNT(val)       bfin_write16(DMA1_7_X_COUNT,val)
+#define bfin_read_DMA1_7_Y_COUNT()           bfin_read16(DMA1_7_Y_COUNT)
+#define bfin_write_DMA1_7_Y_COUNT(val)       bfin_write16(DMA1_7_Y_COUNT,val)
+#define bfin_read_DMA1_7_X_MODIFY()          bfin_read16(DMA1_7_X_MODIFY)
+#define bfin_write_DMA1_7_X_MODIFY(val)      bfin_write16(DMA1_7_X_MODIFY,val)
+#define bfin_read_DMA1_7_Y_MODIFY()          bfin_read16(DMA1_7_Y_MODIFY)
+#define bfin_write_DMA1_7_Y_MODIFY(val)      bfin_write16(DMA1_7_Y_MODIFY,val)
+#define bfin_read_DMA1_7_CURR_DESC_PTR()     bfin_read32(DMA1_7_CURR_DESC_PTR)
+#define bfin_write_DMA1_7_CURR_DESC_PTR(val) bfin_write32(DMA1_7_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_7_CURR_ADDR()         bfin_read32(DMA1_7_CURR_ADDR)
+#define bfin_write_DMA1_7_CURR_ADDR(val)     bfin_write32(DMA1_7_CURR_ADDR,val)
+#define bfin_read_DMA1_7_CURR_X_COUNT()      bfin_read16(DMA1_7_CURR_X_COUNT)
+#define bfin_write_DMA1_7_CURR_X_COUNT(val)  bfin_write16(DMA1_7_CURR_X_COUNT,val)
+#define bfin_read_DMA1_7_CURR_Y_COUNT()      bfin_read16(DMA1_7_CURR_Y_COUNT)
+#define bfin_write_DMA1_7_CURR_Y_COUNT(val)  bfin_write16(DMA1_7_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_7_IRQ_STATUS()        bfin_read16(DMA1_7_IRQ_STATUS)
+#define bfin_write_DMA1_7_IRQ_STATUS(val)    bfin_write16(DMA1_7_IRQ_STATUS,val)
+#define bfin_read_DMA1_7_PERIPHERAL_MAP()    bfin_read16(DMA1_7_PERIPHERAL_MAP)
+#define bfin_write_DMA1_7_PERIPHERAL_MAP(val) bfin_write16(DMA1_7_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_8_CONFIG()            bfin_read16(DMA1_8_CONFIG)
+#define bfin_write_DMA1_8_CONFIG(val)        bfin_write16(DMA1_8_CONFIG,val)
+#define bfin_read_DMA1_8_NEXT_DESC_PTR()     bfin_read32(DMA1_8_NEXT_DESC_PTR)
+#define bfin_write_DMA1_8_NEXT_DESC_PTR(val) bfin_write32(DMA1_8_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_8_START_ADDR()        bfin_read32(DMA1_8_START_ADDR)
+#define bfin_write_DMA1_8_START_ADDR(val)    bfin_write32(DMA1_8_START_ADDR,val)
+#define bfin_read_DMA1_8_X_COUNT()           bfin_read16(DMA1_8_X_COUNT)
+#define bfin_write_DMA1_8_X_COUNT(val)       bfin_write16(DMA1_8_X_COUNT,val)
+#define bfin_read_DMA1_8_Y_COUNT()           bfin_read16(DMA1_8_Y_COUNT)
+#define bfin_write_DMA1_8_Y_COUNT(val)       bfin_write16(DMA1_8_Y_COUNT,val)
+#define bfin_read_DMA1_8_X_MODIFY()          bfin_read16(DMA1_8_X_MODIFY)
+#define bfin_write_DMA1_8_X_MODIFY(val)      bfin_write16(DMA1_8_X_MODIFY,val)
+#define bfin_read_DMA1_8_Y_MODIFY()          bfin_read16(DMA1_8_Y_MODIFY)
+#define bfin_write_DMA1_8_Y_MODIFY(val)      bfin_write16(DMA1_8_Y_MODIFY,val)
+#define bfin_read_DMA1_8_CURR_DESC_PTR()     bfin_read32(DMA1_8_CURR_DESC_PTR)
+#define bfin_write_DMA1_8_CURR_DESC_PTR(val) bfin_write32(DMA1_8_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_8_CURR_ADDR()         bfin_read32(DMA1_8_CURR_ADDR)
+#define bfin_write_DMA1_8_CURR_ADDR(val)     bfin_write32(DMA1_8_CURR_ADDR,val)
+#define bfin_read_DMA1_8_CURR_X_COUNT()      bfin_read16(DMA1_8_CURR_X_COUNT)
+#define bfin_write_DMA1_8_CURR_X_COUNT(val)  bfin_write16(DMA1_8_CURR_X_COUNT,val)
+#define bfin_read_DMA1_8_CURR_Y_COUNT()      bfin_read16(DMA1_8_CURR_Y_COUNT)
+#define bfin_write_DMA1_8_CURR_Y_COUNT(val)  bfin_write16(DMA1_8_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_8_IRQ_STATUS()        bfin_read16(DMA1_8_IRQ_STATUS)
+#define bfin_write_DMA1_8_IRQ_STATUS(val)    bfin_write16(DMA1_8_IRQ_STATUS,val)
+#define bfin_read_DMA1_8_PERIPHERAL_MAP()    bfin_read16(DMA1_8_PERIPHERAL_MAP)
+#define bfin_write_DMA1_8_PERIPHERAL_MAP(val) bfin_write16(DMA1_8_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_9_CONFIG()            bfin_read16(DMA1_9_CONFIG)
+#define bfin_write_DMA1_9_CONFIG(val)        bfin_write16(DMA1_9_CONFIG,val)
+#define bfin_read_DMA1_9_NEXT_DESC_PTR()     bfin_read32(DMA1_9_NEXT_DESC_PTR)
+#define bfin_write_DMA1_9_NEXT_DESC_PTR(val) bfin_write32(DMA1_9_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_9_START_ADDR()        bfin_read32(DMA1_9_START_ADDR)
+#define bfin_write_DMA1_9_START_ADDR(val)    bfin_write32(DMA1_9_START_ADDR,val)
+#define bfin_read_DMA1_9_X_COUNT()           bfin_read16(DMA1_9_X_COUNT)
+#define bfin_write_DMA1_9_X_COUNT(val)       bfin_write16(DMA1_9_X_COUNT,val)
+#define bfin_read_DMA1_9_Y_COUNT()           bfin_read16(DMA1_9_Y_COUNT)
+#define bfin_write_DMA1_9_Y_COUNT(val)       bfin_write16(DMA1_9_Y_COUNT,val)
+#define bfin_read_DMA1_9_X_MODIFY()          bfin_read16(DMA1_9_X_MODIFY)
+#define bfin_write_DMA1_9_X_MODIFY(val)      bfin_write16(DMA1_9_X_MODIFY,val)
+#define bfin_read_DMA1_9_Y_MODIFY()          bfin_read16(DMA1_9_Y_MODIFY)
+#define bfin_write_DMA1_9_Y_MODIFY(val)      bfin_write16(DMA1_9_Y_MODIFY,val)
+#define bfin_read_DMA1_9_CURR_DESC_PTR()     bfin_read32(DMA1_9_CURR_DESC_PTR)
+#define bfin_write_DMA1_9_CURR_DESC_PTR(val) bfin_write32(DMA1_9_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_9_CURR_ADDR()         bfin_read32(DMA1_9_CURR_ADDR)
+#define bfin_write_DMA1_9_CURR_ADDR(val)     bfin_write32(DMA1_9_CURR_ADDR,val)
+#define bfin_read_DMA1_9_CURR_X_COUNT()      bfin_read16(DMA1_9_CURR_X_COUNT)
+#define bfin_write_DMA1_9_CURR_X_COUNT(val)  bfin_write16(DMA1_9_CURR_X_COUNT,val)
+#define bfin_read_DMA1_9_CURR_Y_COUNT()      bfin_read16(DMA1_9_CURR_Y_COUNT)
+#define bfin_write_DMA1_9_CURR_Y_COUNT(val)  bfin_write16(DMA1_9_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_9_IRQ_STATUS()        bfin_read16(DMA1_9_IRQ_STATUS)
+#define bfin_write_DMA1_9_IRQ_STATUS(val)    bfin_write16(DMA1_9_IRQ_STATUS,val)
+#define bfin_read_DMA1_9_PERIPHERAL_MAP()    bfin_read16(DMA1_9_PERIPHERAL_MAP)
+#define bfin_write_DMA1_9_PERIPHERAL_MAP(val) bfin_write16(DMA1_9_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_10_CONFIG()           bfin_read16(DMA1_10_CONFIG)
+#define bfin_write_DMA1_10_CONFIG(val)       bfin_write16(DMA1_10_CONFIG,val)
+#define bfin_read_DMA1_10_NEXT_DESC_PTR()    bfin_read32(DMA1_10_NEXT_DESC_PTR)
+#define bfin_write_DMA1_10_NEXT_DESC_PTR(val) bfin_write32(DMA1_10_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_10_START_ADDR()       bfin_read32(DMA1_10_START_ADDR)
+#define bfin_write_DMA1_10_START_ADDR(val)   bfin_write32(DMA1_10_START_ADDR,val)
+#define bfin_read_DMA1_10_X_COUNT()          bfin_read16(DMA1_10_X_COUNT)
+#define bfin_write_DMA1_10_X_COUNT(val)      bfin_write16(DMA1_10_X_COUNT,val)
+#define bfin_read_DMA1_10_Y_COUNT()          bfin_read16(DMA1_10_Y_COUNT)
+#define bfin_write_DMA1_10_Y_COUNT(val)      bfin_write16(DMA1_10_Y_COUNT,val)
+#define bfin_read_DMA1_10_X_MODIFY()         bfin_read16(DMA1_10_X_MODIFY)
+#define bfin_write_DMA1_10_X_MODIFY(val)     bfin_write16(DMA1_10_X_MODIFY,val)
+#define bfin_read_DMA1_10_Y_MODIFY()         bfin_read16(DMA1_10_Y_MODIFY)
+#define bfin_write_DMA1_10_Y_MODIFY(val)     bfin_write16(DMA1_10_Y_MODIFY,val)
+#define bfin_read_DMA1_10_CURR_DESC_PTR()    bfin_read32(DMA1_10_CURR_DESC_PTR)
+#define bfin_write_DMA1_10_CURR_DESC_PTR(val) bfin_write32(DMA1_10_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_10_CURR_ADDR()        bfin_read32(DMA1_10_CURR_ADDR)
+#define bfin_write_DMA1_10_CURR_ADDR(val)    bfin_write32(DMA1_10_CURR_ADDR,val)
+#define bfin_read_DMA1_10_CURR_X_COUNT()     bfin_read16(DMA1_10_CURR_X_COUNT)
+#define bfin_write_DMA1_10_CURR_X_COUNT(val) bfin_write16(DMA1_10_CURR_X_COUNT,val)
+#define bfin_read_DMA1_10_CURR_Y_COUNT()     bfin_read16(DMA1_10_CURR_Y_COUNT)
+#define bfin_write_DMA1_10_CURR_Y_COUNT(val) bfin_write16(DMA1_10_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_10_IRQ_STATUS()       bfin_read16(DMA1_10_IRQ_STATUS)
+#define bfin_write_DMA1_10_IRQ_STATUS(val)   bfin_write16(DMA1_10_IRQ_STATUS,val)
+#define bfin_read_DMA1_10_PERIPHERAL_MAP()   bfin_read16(DMA1_10_PERIPHERAL_MAP)
+#define bfin_write_DMA1_10_PERIPHERAL_MAP(val) bfin_write16(DMA1_10_PERIPHERAL_MAP,val)
+#define bfin_read_DMA1_11_CONFIG()           bfin_read16(DMA1_11_CONFIG)
+#define bfin_write_DMA1_11_CONFIG(val)       bfin_write16(DMA1_11_CONFIG,val)
+#define bfin_read_DMA1_11_NEXT_DESC_PTR()    bfin_read32(DMA1_11_NEXT_DESC_PTR)
+#define bfin_write_DMA1_11_NEXT_DESC_PTR(val) bfin_write32(DMA1_11_NEXT_DESC_PTR,val)
+#define bfin_read_DMA1_11_START_ADDR()       bfin_read32(DMA1_11_START_ADDR)
+#define bfin_write_DMA1_11_START_ADDR(val)   bfin_write32(DMA1_11_START_ADDR,val)
+#define bfin_read_DMA1_11_X_COUNT()          bfin_read16(DMA1_11_X_COUNT)
+#define bfin_write_DMA1_11_X_COUNT(val)      bfin_write16(DMA1_11_X_COUNT,val)
+#define bfin_read_DMA1_11_Y_COUNT()          bfin_read16(DMA1_11_Y_COUNT)
+#define bfin_write_DMA1_11_Y_COUNT(val)      bfin_write16(DMA1_11_Y_COUNT,val)
+#define bfin_read_DMA1_11_X_MODIFY()         bfin_read16(DMA1_11_X_MODIFY)
+#define bfin_write_DMA1_11_X_MODIFY(val)     bfin_write16(DMA1_11_X_MODIFY,val)
+#define bfin_read_DMA1_11_Y_MODIFY()         bfin_read16(DMA1_11_Y_MODIFY)
+#define bfin_write_DMA1_11_Y_MODIFY(val)     bfin_write16(DMA1_11_Y_MODIFY,val)
+#define bfin_read_DMA1_11_CURR_DESC_PTR()    bfin_read32(DMA1_11_CURR_DESC_PTR)
+#define bfin_write_DMA1_11_CURR_DESC_PTR(val) bfin_write32(DMA1_11_CURR_DESC_PTR,val)
+#define bfin_read_DMA1_11_CURR_ADDR()        bfin_read32(DMA1_11_CURR_ADDR)
+#define bfin_write_DMA1_11_CURR_ADDR(val)    bfin_write32(DMA1_11_CURR_ADDR,val)
+#define bfin_read_DMA1_11_CURR_X_COUNT()     bfin_read16(DMA1_11_CURR_X_COUNT)
+#define bfin_write_DMA1_11_CURR_X_COUNT(val) bfin_write16(DMA1_11_CURR_X_COUNT,val)
+#define bfin_read_DMA1_11_CURR_Y_COUNT()     bfin_read16(DMA1_11_CURR_Y_COUNT)
+#define bfin_write_DMA1_11_CURR_Y_COUNT(val) bfin_write16(DMA1_11_CURR_Y_COUNT,val)
+#define bfin_read_DMA1_11_IRQ_STATUS()       bfin_read16(DMA1_11_IRQ_STATUS)
+#define bfin_write_DMA1_11_IRQ_STATUS(val)   bfin_write16(DMA1_11_IRQ_STATUS,val)
+#define bfin_read_DMA1_11_PERIPHERAL_MAP()   bfin_read16(DMA1_11_PERIPHERAL_MAP)
+#define bfin_write_DMA1_11_PERIPHERAL_MAP(val) bfin_write16(DMA1_11_PERIPHERAL_MAP,val)
+/* Memory DMA1 Controller registers (0xFFC0 1E80-0xFFC0 1FFF) */
+#define bfin_read_MDMA1_D0_CONFIG()          bfin_read16(MDMA1_D0_CONFIG)
+#define bfin_write_MDMA1_D0_CONFIG(val)      bfin_write16(MDMA1_D0_CONFIG,val)
+#define bfin_read_MDMA1_D0_NEXT_DESC_PTR()   bfin_read32(MDMA1_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA1_D0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA1_D0_START_ADDR()      bfin_read32(MDMA1_D0_START_ADDR)
+#define bfin_write_MDMA1_D0_START_ADDR(val)  bfin_write32(MDMA1_D0_START_ADDR,val)
+#define bfin_read_MDMA1_D0_X_COUNT()         bfin_read16(MDMA1_D0_X_COUNT)
+#define bfin_write_MDMA1_D0_X_COUNT(val)     bfin_write16(MDMA1_D0_X_COUNT,val)
+#define bfin_read_MDMA1_D0_Y_COUNT()         bfin_read16(MDMA1_D0_Y_COUNT)
+#define bfin_write_MDMA1_D0_Y_COUNT(val)     bfin_write16(MDMA1_D0_Y_COUNT,val)
+#define bfin_read_MDMA1_D0_X_MODIFY()        bfin_read16(MDMA1_D0_X_MODIFY)
+#define bfin_write_MDMA1_D0_X_MODIFY(val)    bfin_write16(MDMA1_D0_X_MODIFY,val)
+#define bfin_read_MDMA1_D0_Y_MODIFY()        bfin_read16(MDMA1_D0_Y_MODIFY)
+#define bfin_write_MDMA1_D0_Y_MODIFY(val)    bfin_write16(MDMA1_D0_Y_MODIFY,val)
+#define bfin_read_MDMA1_D0_CURR_DESC_PTR()   bfin_read32(MDMA1_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA1_D0_CURR_DESC_PTR(val) bfin_write32(MDMA1_D0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA1_D0_CURR_ADDR()       bfin_read32(MDMA1_D0_CURR_ADDR)
+#define bfin_write_MDMA1_D0_CURR_ADDR(val)   bfin_write32(MDMA1_D0_CURR_ADDR,val)
+#define bfin_read_MDMA1_D0_CURR_X_COUNT()    bfin_read16(MDMA1_D0_CURR_X_COUNT)
+#define bfin_write_MDMA1_D0_CURR_X_COUNT(val) bfin_write16(MDMA1_D0_CURR_X_COUNT,val)
+#define bfin_read_MDMA1_D0_CURR_Y_COUNT()    bfin_read16(MDMA1_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA1_D0_CURR_Y_COUNT(val) bfin_write16(MDMA1_D0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA1_D0_IRQ_STATUS()      bfin_read16(MDMA1_D0_IRQ_STATUS)
+#define bfin_write_MDMA1_D0_IRQ_STATUS(val)  bfin_write16(MDMA1_D0_IRQ_STATUS,val)
+#define bfin_read_MDMA1_D0_PERIPHERAL_MAP()  bfin_read16(MDMA1_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D0_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA1_S0_CONFIG()          bfin_read16(MDMA1_S0_CONFIG)
+#define bfin_write_MDMA1_S0_CONFIG(val)      bfin_write16(MDMA1_S0_CONFIG,val)
+#define bfin_read_MDMA1_S0_NEXT_DESC_PTR()   bfin_read32(MDMA1_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA1_S0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA1_S0_START_ADDR()      bfin_read32(MDMA1_S0_START_ADDR)
+#define bfin_write_MDMA1_S0_START_ADDR(val)  bfin_write32(MDMA1_S0_START_ADDR,val)
+#define bfin_read_MDMA1_S0_X_COUNT()         bfin_read16(MDMA1_S0_X_COUNT)
+#define bfin_write_MDMA1_S0_X_COUNT(val)     bfin_write16(MDMA1_S0_X_COUNT,val)
+#define bfin_read_MDMA1_S0_Y_COUNT()         bfin_read16(MDMA1_S0_Y_COUNT)
+#define bfin_write_MDMA1_S0_Y_COUNT(val)     bfin_write16(MDMA1_S0_Y_COUNT,val)
+#define bfin_read_MDMA1_S0_X_MODIFY()        bfin_read16(MDMA1_S0_X_MODIFY)
+#define bfin_write_MDMA1_S0_X_MODIFY(val)    bfin_write16(MDMA1_S0_X_MODIFY,val)
+#define bfin_read_MDMA1_S0_Y_MODIFY()        bfin_read16(MDMA1_S0_Y_MODIFY)
+#define bfin_write_MDMA1_S0_Y_MODIFY(val)    bfin_write16(MDMA1_S0_Y_MODIFY,val)
+#define bfin_read_MDMA1_S0_CURR_DESC_PTR()   bfin_read32(MDMA1_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA1_S0_CURR_DESC_PTR(val) bfin_write32(MDMA1_S0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA1_S0_CURR_ADDR()       bfin_read32(MDMA1_S0_CURR_ADDR)
+#define bfin_write_MDMA1_S0_CURR_ADDR(val)   bfin_write32(MDMA1_S0_CURR_ADDR,val)
+#define bfin_read_MDMA1_S0_CURR_X_COUNT()    bfin_read16(MDMA1_S0_CURR_X_COUNT)
+#define bfin_write_MDMA1_S0_CURR_X_COUNT(val) bfin_write16(MDMA1_S0_CURR_X_COUNT,val)
+#define bfin_read_MDMA1_S0_CURR_Y_COUNT()    bfin_read16(MDMA1_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA1_S0_CURR_Y_COUNT(val) bfin_write16(MDMA1_S0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA1_S0_IRQ_STATUS()      bfin_read16(MDMA1_S0_IRQ_STATUS)
+#define bfin_write_MDMA1_S0_IRQ_STATUS(val)  bfin_write16(MDMA1_S0_IRQ_STATUS,val)
+#define bfin_read_MDMA1_S0_PERIPHERAL_MAP()  bfin_read16(MDMA1_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S0_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA1_D1_CONFIG()          bfin_read16(MDMA1_D1_CONFIG)
+#define bfin_write_MDMA1_D1_CONFIG(val)      bfin_write16(MDMA1_D1_CONFIG,val)
+#define bfin_read_MDMA1_D1_NEXT_DESC_PTR()   bfin_read32(MDMA1_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA1_D1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA1_D1_START_ADDR()      bfin_read32(MDMA1_D1_START_ADDR)
+#define bfin_write_MDMA1_D1_START_ADDR(val)  bfin_write32(MDMA1_D1_START_ADDR,val)
+#define bfin_read_MDMA1_D1_X_COUNT()         bfin_read16(MDMA1_D1_X_COUNT)
+#define bfin_write_MDMA1_D1_X_COUNT(val)     bfin_write16(MDMA1_D1_X_COUNT,val)
+#define bfin_read_MDMA1_D1_Y_COUNT()         bfin_read16(MDMA1_D1_Y_COUNT)
+#define bfin_write_MDMA1_D1_Y_COUNT(val)     bfin_write16(MDMA1_D1_Y_COUNT,val)
+#define bfin_read_MDMA1_D1_X_MODIFY()        bfin_read16(MDMA1_D1_X_MODIFY)
+#define bfin_write_MDMA1_D1_X_MODIFY(val)    bfin_write16(MDMA1_D1_X_MODIFY,val)
+#define bfin_read_MDMA1_D1_Y_MODIFY()        bfin_read16(MDMA1_D1_Y_MODIFY)
+#define bfin_write_MDMA1_D1_Y_MODIFY(val)    bfin_write16(MDMA1_D1_Y_MODIFY,val)
+#define bfin_read_MDMA1_D1_CURR_DESC_PTR()   bfin_read32(MDMA1_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA1_D1_CURR_DESC_PTR(val) bfin_write32(MDMA1_D1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA1_D1_CURR_ADDR()       bfin_read32(MDMA1_D1_CURR_ADDR)
+#define bfin_write_MDMA1_D1_CURR_ADDR(val)   bfin_write32(MDMA1_D1_CURR_ADDR,val)
+#define bfin_read_MDMA1_D1_CURR_X_COUNT()    bfin_read16(MDMA1_D1_CURR_X_COUNT)
+#define bfin_write_MDMA1_D1_CURR_X_COUNT(val) bfin_write16(MDMA1_D1_CURR_X_COUNT,val)
+#define bfin_read_MDMA1_D1_CURR_Y_COUNT()    bfin_read16(MDMA1_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA1_D1_CURR_Y_COUNT(val) bfin_write16(MDMA1_D1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA1_D1_IRQ_STATUS()      bfin_read16(MDMA1_D1_IRQ_STATUS)
+#define bfin_write_MDMA1_D1_IRQ_STATUS(val)  bfin_write16(MDMA1_D1_IRQ_STATUS,val)
+#define bfin_read_MDMA1_D1_PERIPHERAL_MAP()  bfin_read16(MDMA1_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D1_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA1_S1_CONFIG()          bfin_read16(MDMA1_S1_CONFIG)
+#define bfin_write_MDMA1_S1_CONFIG(val)      bfin_write16(MDMA1_S1_CONFIG,val)
+#define bfin_read_MDMA1_S1_NEXT_DESC_PTR()   bfin_read32(MDMA1_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA1_S1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA1_S1_START_ADDR()      bfin_read32(MDMA1_S1_START_ADDR)
+#define bfin_write_MDMA1_S1_START_ADDR(val)  bfin_write32(MDMA1_S1_START_ADDR,val)
+#define bfin_read_MDMA1_S1_X_COUNT()         bfin_read16(MDMA1_S1_X_COUNT)
+#define bfin_write_MDMA1_S1_X_COUNT(val)     bfin_write16(MDMA1_S1_X_COUNT,val)
+#define bfin_read_MDMA1_S1_Y_COUNT()         bfin_read16(MDMA1_S1_Y_COUNT)
+#define bfin_write_MDMA1_S1_Y_COUNT(val)     bfin_write16(MDMA1_S1_Y_COUNT,val)
+#define bfin_read_MDMA1_S1_X_MODIFY()        bfin_read16(MDMA1_S1_X_MODIFY)
+#define bfin_write_MDMA1_S1_X_MODIFY(val)    bfin_write16(MDMA1_S1_X_MODIFY,val)
+#define bfin_read_MDMA1_S1_Y_MODIFY()        bfin_read16(MDMA1_S1_Y_MODIFY)
+#define bfin_write_MDMA1_S1_Y_MODIFY(val)    bfin_write16(MDMA1_S1_Y_MODIFY,val)
+#define bfin_read_MDMA1_S1_CURR_DESC_PTR()   bfin_read32(MDMA1_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA1_S1_CURR_DESC_PTR(val) bfin_write32(MDMA1_S1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA1_S1_CURR_ADDR()       bfin_read32(MDMA1_S1_CURR_ADDR)
+#define bfin_write_MDMA1_S1_CURR_ADDR(val)   bfin_write32(MDMA1_S1_CURR_ADDR,val)
+#define bfin_read_MDMA1_S1_CURR_X_COUNT()    bfin_read16(MDMA1_S1_CURR_X_COUNT)
+#define bfin_write_MDMA1_S1_CURR_X_COUNT(val) bfin_write16(MDMA1_S1_CURR_X_COUNT,val)
+#define bfin_read_MDMA1_S1_CURR_Y_COUNT()    bfin_read16(MDMA1_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA1_S1_CURR_Y_COUNT(val) bfin_write16(MDMA1_S1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA1_S1_IRQ_STATUS()      bfin_read16(MDMA1_S1_IRQ_STATUS)
+#define bfin_write_MDMA1_S1_IRQ_STATUS(val)  bfin_write16(MDMA1_S1_IRQ_STATUS,val)
+#define bfin_read_MDMA1_S1_PERIPHERAL_MAP()  bfin_read16(MDMA1_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S1_PERIPHERAL_MAP,val)
+/* DMA2 Controller registers (0xFFC0 0C00-0xFFC0 0DFF) */
+#define bfin_read_DMA2_0_CONFIG()            bfin_read16(DMA2_0_CONFIG)
+#define bfin_write_DMA2_0_CONFIG(val)        bfin_write16(DMA2_0_CONFIG,val)
+#define bfin_read_DMA2_0_NEXT_DESC_PTR()     bfin_read32(DMA2_0_NEXT_DESC_PTR)
+#define bfin_write_DMA2_0_NEXT_DESC_PTR(val) bfin_write32(DMA2_0_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_0_START_ADDR()        bfin_read32(DMA2_0_START_ADDR)
+#define bfin_write_DMA2_0_START_ADDR(val)    bfin_write32(DMA2_0_START_ADDR,val)
+#define bfin_read_DMA2_0_X_COUNT()           bfin_read16(DMA2_0_X_COUNT)
+#define bfin_write_DMA2_0_X_COUNT(val)       bfin_write16(DMA2_0_X_COUNT,val)
+#define bfin_read_DMA2_0_Y_COUNT()           bfin_read16(DMA2_0_Y_COUNT)
+#define bfin_write_DMA2_0_Y_COUNT(val)       bfin_write16(DMA2_0_Y_COUNT,val)
+#define bfin_read_DMA2_0_X_MODIFY()          bfin_read16(DMA2_0_X_MODIFY)
+#define bfin_write_DMA2_0_X_MODIFY(val)      bfin_write16(DMA2_0_X_MODIFY,val)
+#define bfin_read_DMA2_0_Y_MODIFY()          bfin_read16(DMA2_0_Y_MODIFY)
+#define bfin_write_DMA2_0_Y_MODIFY(val)      bfin_write16(DMA2_0_Y_MODIFY,val)
+#define bfin_read_DMA2_0_CURR_DESC_PTR()     bfin_read32(DMA2_0_CURR_DESC_PTR)
+#define bfin_write_DMA2_0_CURR_DESC_PTR(val) bfin_write32(DMA2_0_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_0_CURR_ADDR()         bfin_read32(DMA2_0_CURR_ADDR)
+#define bfin_write_DMA2_0_CURR_ADDR(val)     bfin_write32(DMA2_0_CURR_ADDR,val)
+#define bfin_read_DMA2_0_CURR_X_COUNT()      bfin_read16(DMA2_0_CURR_X_COUNT)
+#define bfin_write_DMA2_0_CURR_X_COUNT(val)  bfin_write16(DMA2_0_CURR_X_COUNT,val)
+#define bfin_read_DMA2_0_CURR_Y_COUNT()      bfin_read16(DMA2_0_CURR_Y_COUNT)
+#define bfin_write_DMA2_0_CURR_Y_COUNT(val)  bfin_write16(DMA2_0_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_0_IRQ_STATUS()        bfin_read16(DMA2_0_IRQ_STATUS)
+#define bfin_write_DMA2_0_IRQ_STATUS(val)    bfin_write16(DMA2_0_IRQ_STATUS,val)
+#define bfin_read_DMA2_0_PERIPHERAL_MAP()    bfin_read16(DMA2_0_PERIPHERAL_MAP)
+#define bfin_write_DMA2_0_PERIPHERAL_MAP(val) bfin_write16(DMA2_0_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_1_CONFIG()            bfin_read16(DMA2_1_CONFIG)
+#define bfin_write_DMA2_1_CONFIG(val)        bfin_write16(DMA2_1_CONFIG,val)
+#define bfin_read_DMA2_1_NEXT_DESC_PTR()     bfin_read32(DMA2_1_NEXT_DESC_PTR)
+#define bfin_write_DMA2_1_NEXT_DESC_PTR(val) bfin_write32(DMA2_1_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_1_START_ADDR()        bfin_read32(DMA2_1_START_ADDR)
+#define bfin_write_DMA2_1_START_ADDR(val)    bfin_write32(DMA2_1_START_ADDR,val)
+#define bfin_read_DMA2_1_X_COUNT()           bfin_read16(DMA2_1_X_COUNT)
+#define bfin_write_DMA2_1_X_COUNT(val)       bfin_write16(DMA2_1_X_COUNT,val)
+#define bfin_read_DMA2_1_Y_COUNT()           bfin_read16(DMA2_1_Y_COUNT)
+#define bfin_write_DMA2_1_Y_COUNT(val)       bfin_write16(DMA2_1_Y_COUNT,val)
+#define bfin_read_DMA2_1_X_MODIFY()          bfin_read16(DMA2_1_X_MODIFY)
+#define bfin_write_DMA2_1_X_MODIFY(val)      bfin_write16(DMA2_1_X_MODIFY,val)
+#define bfin_read_DMA2_1_Y_MODIFY()          bfin_read16(DMA2_1_Y_MODIFY)
+#define bfin_write_DMA2_1_Y_MODIFY(val)      bfin_write16(DMA2_1_Y_MODIFY,val)
+#define bfin_read_DMA2_1_CURR_DESC_PTR()     bfin_read32(DMA2_1_CURR_DESC_PTR)
+#define bfin_write_DMA2_1_CURR_DESC_PTR(val) bfin_write32(DMA2_1_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_1_CURR_ADDR()         bfin_read32(DMA2_1_CURR_ADDR)
+#define bfin_write_DMA2_1_CURR_ADDR(val)     bfin_write32(DMA2_1_CURR_ADDR,val)
+#define bfin_read_DMA2_1_CURR_X_COUNT()      bfin_read16(DMA2_1_CURR_X_COUNT)
+#define bfin_write_DMA2_1_CURR_X_COUNT(val)  bfin_write16(DMA2_1_CURR_X_COUNT,val)
+#define bfin_read_DMA2_1_CURR_Y_COUNT()      bfin_read16(DMA2_1_CURR_Y_COUNT)
+#define bfin_write_DMA2_1_CURR_Y_COUNT(val)  bfin_write16(DMA2_1_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_1_IRQ_STATUS()        bfin_read16(DMA2_1_IRQ_STATUS)
+#define bfin_write_DMA2_1_IRQ_STATUS(val)    bfin_write16(DMA2_1_IRQ_STATUS,val)
+#define bfin_read_DMA2_1_PERIPHERAL_MAP()    bfin_read16(DMA2_1_PERIPHERAL_MAP)
+#define bfin_write_DMA2_1_PERIPHERAL_MAP(val) bfin_write16(DMA2_1_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_2_CONFIG()            bfin_read16(DMA2_2_CONFIG)
+#define bfin_write_DMA2_2_CONFIG(val)        bfin_write16(DMA2_2_CONFIG,val)
+#define bfin_read_DMA2_2_NEXT_DESC_PTR()     bfin_read32(DMA2_2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_2_NEXT_DESC_PTR(val) bfin_write32(DMA2_2_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_2_START_ADDR()        bfin_read32(DMA2_2_START_ADDR)
+#define bfin_write_DMA2_2_START_ADDR(val)    bfin_write32(DMA2_2_START_ADDR,val)
+#define bfin_read_DMA2_2_X_COUNT()           bfin_read16(DMA2_2_X_COUNT)
+#define bfin_write_DMA2_2_X_COUNT(val)       bfin_write16(DMA2_2_X_COUNT,val)
+#define bfin_read_DMA2_2_Y_COUNT()           bfin_read16(DMA2_2_Y_COUNT)
+#define bfin_write_DMA2_2_Y_COUNT(val)       bfin_write16(DMA2_2_Y_COUNT,val)
+#define bfin_read_DMA2_2_X_MODIFY()          bfin_read16(DMA2_2_X_MODIFY)
+#define bfin_write_DMA2_2_X_MODIFY(val)      bfin_write16(DMA2_2_X_MODIFY,val)
+#define bfin_read_DMA2_2_Y_MODIFY()          bfin_read16(DMA2_2_Y_MODIFY)
+#define bfin_write_DMA2_2_Y_MODIFY(val)      bfin_write16(DMA2_2_Y_MODIFY,val)
+#define bfin_read_DMA2_2_CURR_DESC_PTR()     bfin_read32(DMA2_2_CURR_DESC_PTR)
+#define bfin_write_DMA2_2_CURR_DESC_PTR(val) bfin_write32(DMA2_2_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_2_CURR_ADDR()         bfin_read32(DMA2_2_CURR_ADDR)
+#define bfin_write_DMA2_2_CURR_ADDR(val)     bfin_write32(DMA2_2_CURR_ADDR,val)
+#define bfin_read_DMA2_2_CURR_X_COUNT()      bfin_read16(DMA2_2_CURR_X_COUNT)
+#define bfin_write_DMA2_2_CURR_X_COUNT(val)  bfin_write16(DMA2_2_CURR_X_COUNT,val)
+#define bfin_read_DMA2_2_CURR_Y_COUNT()      bfin_read16(DMA2_2_CURR_Y_COUNT)
+#define bfin_write_DMA2_2_CURR_Y_COUNT(val)  bfin_write16(DMA2_2_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_2_IRQ_STATUS()        bfin_read16(DMA2_2_IRQ_STATUS)
+#define bfin_write_DMA2_2_IRQ_STATUS(val)    bfin_write16(DMA2_2_IRQ_STATUS,val)
+#define bfin_read_DMA2_2_PERIPHERAL_MAP()    bfin_read16(DMA2_2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_2_PERIPHERAL_MAP(val) bfin_write16(DMA2_2_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_3_CONFIG()            bfin_read16(DMA2_3_CONFIG)
+#define bfin_write_DMA2_3_CONFIG(val)        bfin_write16(DMA2_3_CONFIG,val)
+#define bfin_read_DMA2_3_NEXT_DESC_PTR()     bfin_read32(DMA2_3_NEXT_DESC_PTR)
+#define bfin_write_DMA2_3_NEXT_DESC_PTR(val) bfin_write32(DMA2_3_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_3_START_ADDR()        bfin_read32(DMA2_3_START_ADDR)
+#define bfin_write_DMA2_3_START_ADDR(val)    bfin_write32(DMA2_3_START_ADDR,val)
+#define bfin_read_DMA2_3_X_COUNT()           bfin_read16(DMA2_3_X_COUNT)
+#define bfin_write_DMA2_3_X_COUNT(val)       bfin_write16(DMA2_3_X_COUNT,val)
+#define bfin_read_DMA2_3_Y_COUNT()           bfin_read16(DMA2_3_Y_COUNT)
+#define bfin_write_DMA2_3_Y_COUNT(val)       bfin_write16(DMA2_3_Y_COUNT,val)
+#define bfin_read_DMA2_3_X_MODIFY()          bfin_read16(DMA2_3_X_MODIFY)
+#define bfin_write_DMA2_3_X_MODIFY(val)      bfin_write16(DMA2_3_X_MODIFY,val)
+#define bfin_read_DMA2_3_Y_MODIFY()          bfin_read16(DMA2_3_Y_MODIFY)
+#define bfin_write_DMA2_3_Y_MODIFY(val)      bfin_write16(DMA2_3_Y_MODIFY,val)
+#define bfin_read_DMA2_3_CURR_DESC_PTR()     bfin_read32(DMA2_3_CURR_DESC_PTR)
+#define bfin_write_DMA2_3_CURR_DESC_PTR(val) bfin_write32(DMA2_3_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_3_CURR_ADDR()         bfin_read32(DMA2_3_CURR_ADDR)
+#define bfin_write_DMA2_3_CURR_ADDR(val)     bfin_write32(DMA2_3_CURR_ADDR,val)
+#define bfin_read_DMA2_3_CURR_X_COUNT()      bfin_read16(DMA2_3_CURR_X_COUNT)
+#define bfin_write_DMA2_3_CURR_X_COUNT(val)  bfin_write16(DMA2_3_CURR_X_COUNT,val)
+#define bfin_read_DMA2_3_CURR_Y_COUNT()      bfin_read16(DMA2_3_CURR_Y_COUNT)
+#define bfin_write_DMA2_3_CURR_Y_COUNT(val)  bfin_write16(DMA2_3_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_3_IRQ_STATUS()        bfin_read16(DMA2_3_IRQ_STATUS)
+#define bfin_write_DMA2_3_IRQ_STATUS(val)    bfin_write16(DMA2_3_IRQ_STATUS,val)
+#define bfin_read_DMA2_3_PERIPHERAL_MAP()    bfin_read16(DMA2_3_PERIPHERAL_MAP)
+#define bfin_write_DMA2_3_PERIPHERAL_MAP(val) bfin_write16(DMA2_3_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_4_CONFIG()            bfin_read16(DMA2_4_CONFIG)
+#define bfin_write_DMA2_4_CONFIG(val)        bfin_write16(DMA2_4_CONFIG,val)
+#define bfin_read_DMA2_4_NEXT_DESC_PTR()     bfin_read32(DMA2_4_NEXT_DESC_PTR)
+#define bfin_write_DMA2_4_NEXT_DESC_PTR(val) bfin_write32(DMA2_4_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_4_START_ADDR()        bfin_read32(DMA2_4_START_ADDR)
+#define bfin_write_DMA2_4_START_ADDR(val)    bfin_write32(DMA2_4_START_ADDR,val)
+#define bfin_read_DMA2_4_X_COUNT()           bfin_read16(DMA2_4_X_COUNT)
+#define bfin_write_DMA2_4_X_COUNT(val)       bfin_write16(DMA2_4_X_COUNT,val)
+#define bfin_read_DMA2_4_Y_COUNT()           bfin_read16(DMA2_4_Y_COUNT)
+#define bfin_write_DMA2_4_Y_COUNT(val)       bfin_write16(DMA2_4_Y_COUNT,val)
+#define bfin_read_DMA2_4_X_MODIFY()          bfin_read16(DMA2_4_X_MODIFY)
+#define bfin_write_DMA2_4_X_MODIFY(val)      bfin_write16(DMA2_4_X_MODIFY,val)
+#define bfin_read_DMA2_4_Y_MODIFY()          bfin_read16(DMA2_4_Y_MODIFY)
+#define bfin_write_DMA2_4_Y_MODIFY(val)      bfin_write16(DMA2_4_Y_MODIFY,val)
+#define bfin_read_DMA2_4_CURR_DESC_PTR()     bfin_read32(DMA2_4_CURR_DESC_PTR)
+#define bfin_write_DMA2_4_CURR_DESC_PTR(val) bfin_write32(DMA2_4_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_4_CURR_ADDR()         bfin_read32(DMA2_4_CURR_ADDR)
+#define bfin_write_DMA2_4_CURR_ADDR(val)     bfin_write32(DMA2_4_CURR_ADDR,val)
+#define bfin_read_DMA2_4_CURR_X_COUNT()      bfin_read16(DMA2_4_CURR_X_COUNT)
+#define bfin_write_DMA2_4_CURR_X_COUNT(val)  bfin_write16(DMA2_4_CURR_X_COUNT,val)
+#define bfin_read_DMA2_4_CURR_Y_COUNT()      bfin_read16(DMA2_4_CURR_Y_COUNT)
+#define bfin_write_DMA2_4_CURR_Y_COUNT(val)  bfin_write16(DMA2_4_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_4_IRQ_STATUS()        bfin_read16(DMA2_4_IRQ_STATUS)
+#define bfin_write_DMA2_4_IRQ_STATUS(val)    bfin_write16(DMA2_4_IRQ_STATUS,val)
+#define bfin_read_DMA2_4_PERIPHERAL_MAP()    bfin_read16(DMA2_4_PERIPHERAL_MAP)
+#define bfin_write_DMA2_4_PERIPHERAL_MAP(val) bfin_write16(DMA2_4_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_5_CONFIG()            bfin_read16(DMA2_5_CONFIG)
+#define bfin_write_DMA2_5_CONFIG(val)        bfin_write16(DMA2_5_CONFIG,val)
+#define bfin_read_DMA2_5_NEXT_DESC_PTR()     bfin_read32(DMA2_5_NEXT_DESC_PTR)
+#define bfin_write_DMA2_5_NEXT_DESC_PTR(val) bfin_write32(DMA2_5_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_5_START_ADDR()        bfin_read32(DMA2_5_START_ADDR)
+#define bfin_write_DMA2_5_START_ADDR(val)    bfin_write32(DMA2_5_START_ADDR,val)
+#define bfin_read_DMA2_5_X_COUNT()           bfin_read16(DMA2_5_X_COUNT)
+#define bfin_write_DMA2_5_X_COUNT(val)       bfin_write16(DMA2_5_X_COUNT,val)
+#define bfin_read_DMA2_5_Y_COUNT()           bfin_read16(DMA2_5_Y_COUNT)
+#define bfin_write_DMA2_5_Y_COUNT(val)       bfin_write16(DMA2_5_Y_COUNT,val)
+#define bfin_read_DMA2_5_X_MODIFY()          bfin_read16(DMA2_5_X_MODIFY)
+#define bfin_write_DMA2_5_X_MODIFY(val)      bfin_write16(DMA2_5_X_MODIFY,val)
+#define bfin_read_DMA2_5_Y_MODIFY()          bfin_read16(DMA2_5_Y_MODIFY)
+#define bfin_write_DMA2_5_Y_MODIFY(val)      bfin_write16(DMA2_5_Y_MODIFY,val)
+#define bfin_read_DMA2_5_CURR_DESC_PTR()     bfin_read32(DMA2_5_CURR_DESC_PTR)
+#define bfin_write_DMA2_5_CURR_DESC_PTR(val) bfin_write32(DMA2_5_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_5_CURR_ADDR()         bfin_read32(DMA2_5_CURR_ADDR)
+#define bfin_write_DMA2_5_CURR_ADDR(val)     bfin_write32(DMA2_5_CURR_ADDR,val)
+#define bfin_read_DMA2_5_CURR_X_COUNT()      bfin_read16(DMA2_5_CURR_X_COUNT)
+#define bfin_write_DMA2_5_CURR_X_COUNT(val)  bfin_write16(DMA2_5_CURR_X_COUNT,val)
+#define bfin_read_DMA2_5_CURR_Y_COUNT()      bfin_read16(DMA2_5_CURR_Y_COUNT)
+#define bfin_write_DMA2_5_CURR_Y_COUNT(val)  bfin_write16(DMA2_5_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_5_IRQ_STATUS()        bfin_read16(DMA2_5_IRQ_STATUS)
+#define bfin_write_DMA2_5_IRQ_STATUS(val)    bfin_write16(DMA2_5_IRQ_STATUS,val)
+#define bfin_read_DMA2_5_PERIPHERAL_MAP()    bfin_read16(DMA2_5_PERIPHERAL_MAP)
+#define bfin_write_DMA2_5_PERIPHERAL_MAP(val) bfin_write16(DMA2_5_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_6_CONFIG()            bfin_read16(DMA2_6_CONFIG)
+#define bfin_write_DMA2_6_CONFIG(val)        bfin_write16(DMA2_6_CONFIG,val)
+#define bfin_read_DMA2_6_NEXT_DESC_PTR()     bfin_read32(DMA2_6_NEXT_DESC_PTR)
+#define bfin_write_DMA2_6_NEXT_DESC_PTR(val) bfin_write32(DMA2_6_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_6_START_ADDR()        bfin_read32(DMA2_6_START_ADDR)
+#define bfin_write_DMA2_6_START_ADDR(val)    bfin_write32(DMA2_6_START_ADDR,val)
+#define bfin_read_DMA2_6_X_COUNT()           bfin_read16(DMA2_6_X_COUNT)
+#define bfin_write_DMA2_6_X_COUNT(val)       bfin_write16(DMA2_6_X_COUNT,val)
+#define bfin_read_DMA2_6_Y_COUNT()           bfin_read16(DMA2_6_Y_COUNT)
+#define bfin_write_DMA2_6_Y_COUNT(val)       bfin_write16(DMA2_6_Y_COUNT,val)
+#define bfin_read_DMA2_6_X_MODIFY()          bfin_read16(DMA2_6_X_MODIFY)
+#define bfin_write_DMA2_6_X_MODIFY(val)      bfin_write16(DMA2_6_X_MODIFY,val)
+#define bfin_read_DMA2_6_Y_MODIFY()          bfin_read16(DMA2_6_Y_MODIFY)
+#define bfin_write_DMA2_6_Y_MODIFY(val)      bfin_write16(DMA2_6_Y_MODIFY,val)
+#define bfin_read_DMA2_6_CURR_DESC_PTR()     bfin_read32(DMA2_6_CURR_DESC_PTR)
+#define bfin_write_DMA2_6_CURR_DESC_PTR(val) bfin_write32(DMA2_6_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_6_CURR_ADDR()         bfin_read32(DMA2_6_CURR_ADDR)
+#define bfin_write_DMA2_6_CURR_ADDR(val)     bfin_write32(DMA2_6_CURR_ADDR,val)
+#define bfin_read_DMA2_6_CURR_X_COUNT()      bfin_read16(DMA2_6_CURR_X_COUNT)
+#define bfin_write_DMA2_6_CURR_X_COUNT(val)  bfin_write16(DMA2_6_CURR_X_COUNT,val)
+#define bfin_read_DMA2_6_CURR_Y_COUNT()      bfin_read16(DMA2_6_CURR_Y_COUNT)
+#define bfin_write_DMA2_6_CURR_Y_COUNT(val)  bfin_write16(DMA2_6_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_6_IRQ_STATUS()        bfin_read16(DMA2_6_IRQ_STATUS)
+#define bfin_write_DMA2_6_IRQ_STATUS(val)    bfin_write16(DMA2_6_IRQ_STATUS,val)
+#define bfin_read_DMA2_6_PERIPHERAL_MAP()    bfin_read16(DMA2_6_PERIPHERAL_MAP)
+#define bfin_write_DMA2_6_PERIPHERAL_MAP(val) bfin_write16(DMA2_6_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_7_CONFIG()            bfin_read16(DMA2_7_CONFIG)
+#define bfin_write_DMA2_7_CONFIG(val)        bfin_write16(DMA2_7_CONFIG,val)
+#define bfin_read_DMA2_7_NEXT_DESC_PTR()     bfin_read32(DMA2_7_NEXT_DESC_PTR)
+#define bfin_write_DMA2_7_NEXT_DESC_PTR(val) bfin_write32(DMA2_7_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_7_START_ADDR()        bfin_read32(DMA2_7_START_ADDR)
+#define bfin_write_DMA2_7_START_ADDR(val)    bfin_write32(DMA2_7_START_ADDR,val)
+#define bfin_read_DMA2_7_X_COUNT()           bfin_read16(DMA2_7_X_COUNT)
+#define bfin_write_DMA2_7_X_COUNT(val)       bfin_write16(DMA2_7_X_COUNT,val)
+#define bfin_read_DMA2_7_Y_COUNT()           bfin_read16(DMA2_7_Y_COUNT)
+#define bfin_write_DMA2_7_Y_COUNT(val)       bfin_write16(DMA2_7_Y_COUNT,val)
+#define bfin_read_DMA2_7_X_MODIFY()          bfin_read16(DMA2_7_X_MODIFY)
+#define bfin_write_DMA2_7_X_MODIFY(val)      bfin_write16(DMA2_7_X_MODIFY,val)
+#define bfin_read_DMA2_7_Y_MODIFY()          bfin_read16(DMA2_7_Y_MODIFY)
+#define bfin_write_DMA2_7_Y_MODIFY(val)      bfin_write16(DMA2_7_Y_MODIFY,val)
+#define bfin_read_DMA2_7_CURR_DESC_PTR()     bfin_read32(DMA2_7_CURR_DESC_PTR)
+#define bfin_write_DMA2_7_CURR_DESC_PTR(val) bfin_write32(DMA2_7_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_7_CURR_ADDR()         bfin_read32(DMA2_7_CURR_ADDR)
+#define bfin_write_DMA2_7_CURR_ADDR(val)     bfin_write32(DMA2_7_CURR_ADDR,val)
+#define bfin_read_DMA2_7_CURR_X_COUNT()      bfin_read16(DMA2_7_CURR_X_COUNT)
+#define bfin_write_DMA2_7_CURR_X_COUNT(val)  bfin_write16(DMA2_7_CURR_X_COUNT,val)
+#define bfin_read_DMA2_7_CURR_Y_COUNT()      bfin_read16(DMA2_7_CURR_Y_COUNT)
+#define bfin_write_DMA2_7_CURR_Y_COUNT(val)  bfin_write16(DMA2_7_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_7_IRQ_STATUS()        bfin_read16(DMA2_7_IRQ_STATUS)
+#define bfin_write_DMA2_7_IRQ_STATUS(val)    bfin_write16(DMA2_7_IRQ_STATUS,val)
+#define bfin_read_DMA2_7_PERIPHERAL_MAP()    bfin_read16(DMA2_7_PERIPHERAL_MAP)
+#define bfin_write_DMA2_7_PERIPHERAL_MAP(val) bfin_write16(DMA2_7_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_8_CONFIG()            bfin_read16(DMA2_8_CONFIG)
+#define bfin_write_DMA2_8_CONFIG(val)        bfin_write16(DMA2_8_CONFIG,val)
+#define bfin_read_DMA2_8_NEXT_DESC_PTR()     bfin_read32(DMA2_8_NEXT_DESC_PTR)
+#define bfin_write_DMA2_8_NEXT_DESC_PTR(val) bfin_write32(DMA2_8_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_8_START_ADDR()        bfin_read32(DMA2_8_START_ADDR)
+#define bfin_write_DMA2_8_START_ADDR(val)    bfin_write32(DMA2_8_START_ADDR,val)
+#define bfin_read_DMA2_8_X_COUNT()           bfin_read16(DMA2_8_X_COUNT)
+#define bfin_write_DMA2_8_X_COUNT(val)       bfin_write16(DMA2_8_X_COUNT,val)
+#define bfin_read_DMA2_8_Y_COUNT()           bfin_read16(DMA2_8_Y_COUNT)
+#define bfin_write_DMA2_8_Y_COUNT(val)       bfin_write16(DMA2_8_Y_COUNT,val)
+#define bfin_read_DMA2_8_X_MODIFY()          bfin_read16(DMA2_8_X_MODIFY)
+#define bfin_write_DMA2_8_X_MODIFY(val)      bfin_write16(DMA2_8_X_MODIFY,val)
+#define bfin_read_DMA2_8_Y_MODIFY()          bfin_read16(DMA2_8_Y_MODIFY)
+#define bfin_write_DMA2_8_Y_MODIFY(val)      bfin_write16(DMA2_8_Y_MODIFY,val)
+#define bfin_read_DMA2_8_CURR_DESC_PTR()     bfin_read32(DMA2_8_CURR_DESC_PTR)
+#define bfin_write_DMA2_8_CURR_DESC_PTR(val) bfin_write32(DMA2_8_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_8_CURR_ADDR()         bfin_read32(DMA2_8_CURR_ADDR)
+#define bfin_write_DMA2_8_CURR_ADDR(val)     bfin_write32(DMA2_8_CURR_ADDR,val)
+#define bfin_read_DMA2_8_CURR_X_COUNT()      bfin_read16(DMA2_8_CURR_X_COUNT)
+#define bfin_write_DMA2_8_CURR_X_COUNT(val)  bfin_write16(DMA2_8_CURR_X_COUNT,val)
+#define bfin_read_DMA2_8_CURR_Y_COUNT()      bfin_read16(DMA2_8_CURR_Y_COUNT)
+#define bfin_write_DMA2_8_CURR_Y_COUNT(val)  bfin_write16(DMA2_8_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_8_IRQ_STATUS()        bfin_read16(DMA2_8_IRQ_STATUS)
+#define bfin_write_DMA2_8_IRQ_STATUS(val)    bfin_write16(DMA2_8_IRQ_STATUS,val)
+#define bfin_read_DMA2_8_PERIPHERAL_MAP()    bfin_read16(DMA2_8_PERIPHERAL_MAP)
+#define bfin_write_DMA2_8_PERIPHERAL_MAP(val) bfin_write16(DMA2_8_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_9_CONFIG()            bfin_read16(DMA2_9_CONFIG)
+#define bfin_write_DMA2_9_CONFIG(val)        bfin_write16(DMA2_9_CONFIG,val)
+#define bfin_read_DMA2_9_NEXT_DESC_PTR()     bfin_read32(DMA2_9_NEXT_DESC_PTR)
+#define bfin_write_DMA2_9_NEXT_DESC_PTR(val) bfin_write32(DMA2_9_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_9_START_ADDR()        bfin_read32(DMA2_9_START_ADDR)
+#define bfin_write_DMA2_9_START_ADDR(val)    bfin_write32(DMA2_9_START_ADDR,val)
+#define bfin_read_DMA2_9_X_COUNT()           bfin_read16(DMA2_9_X_COUNT)
+#define bfin_write_DMA2_9_X_COUNT(val)       bfin_write16(DMA2_9_X_COUNT,val)
+#define bfin_read_DMA2_9_Y_COUNT()           bfin_read16(DMA2_9_Y_COUNT)
+#define bfin_write_DMA2_9_Y_COUNT(val)       bfin_write16(DMA2_9_Y_COUNT,val)
+#define bfin_read_DMA2_9_X_MODIFY()          bfin_read16(DMA2_9_X_MODIFY)
+#define bfin_write_DMA2_9_X_MODIFY(val)      bfin_write16(DMA2_9_X_MODIFY,val)
+#define bfin_read_DMA2_9_Y_MODIFY()          bfin_read16(DMA2_9_Y_MODIFY)
+#define bfin_write_DMA2_9_Y_MODIFY(val)      bfin_write16(DMA2_9_Y_MODIFY,val)
+#define bfin_read_DMA2_9_CURR_DESC_PTR()     bfin_read32(DMA2_9_CURR_DESC_PTR)
+#define bfin_write_DMA2_9_CURR_DESC_PTR(val) bfin_write32(DMA2_9_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_9_CURR_ADDR()         bfin_read32(DMA2_9_CURR_ADDR)
+#define bfin_write_DMA2_9_CURR_ADDR(val)     bfin_write32(DMA2_9_CURR_ADDR,val)
+#define bfin_read_DMA2_9_CURR_X_COUNT()      bfin_read16(DMA2_9_CURR_X_COUNT)
+#define bfin_write_DMA2_9_CURR_X_COUNT(val)  bfin_write16(DMA2_9_CURR_X_COUNT,val)
+#define bfin_read_DMA2_9_CURR_Y_COUNT()      bfin_read16(DMA2_9_CURR_Y_COUNT)
+#define bfin_write_DMA2_9_CURR_Y_COUNT(val)  bfin_write16(DMA2_9_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_9_IRQ_STATUS()        bfin_read16(DMA2_9_IRQ_STATUS)
+#define bfin_write_DMA2_9_IRQ_STATUS(val)    bfin_write16(DMA2_9_IRQ_STATUS,val)
+#define bfin_read_DMA2_9_PERIPHERAL_MAP()    bfin_read16(DMA2_9_PERIPHERAL_MAP)
+#define bfin_write_DMA2_9_PERIPHERAL_MAP(val) bfin_write16(DMA2_9_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_10_CONFIG()           bfin_read16(DMA2_10_CONFIG)
+#define bfin_write_DMA2_10_CONFIG(val)       bfin_write16(DMA2_10_CONFIG,val)
+#define bfin_read_DMA2_10_NEXT_DESC_PTR()    bfin_read32(DMA2_10_NEXT_DESC_PTR)
+#define bfin_write_DMA2_10_NEXT_DESC_PTR(val) bfin_write32(DMA2_10_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_10_START_ADDR()       bfin_read32(DMA2_10_START_ADDR)
+#define bfin_write_DMA2_10_START_ADDR(val)   bfin_write32(DMA2_10_START_ADDR,val)
+#define bfin_read_DMA2_10_X_COUNT()          bfin_read16(DMA2_10_X_COUNT)
+#define bfin_write_DMA2_10_X_COUNT(val)      bfin_write16(DMA2_10_X_COUNT,val)
+#define bfin_read_DMA2_10_Y_COUNT()          bfin_read16(DMA2_10_Y_COUNT)
+#define bfin_write_DMA2_10_Y_COUNT(val)      bfin_write16(DMA2_10_Y_COUNT,val)
+#define bfin_read_DMA2_10_X_MODIFY()         bfin_read16(DMA2_10_X_MODIFY)
+#define bfin_write_DMA2_10_X_MODIFY(val)     bfin_write16(DMA2_10_X_MODIFY,val)
+#define bfin_read_DMA2_10_Y_MODIFY()         bfin_read16(DMA2_10_Y_MODIFY)
+#define bfin_write_DMA2_10_Y_MODIFY(val)     bfin_write16(DMA2_10_Y_MODIFY,val)
+#define bfin_read_DMA2_10_CURR_DESC_PTR()    bfin_read32(DMA2_10_CURR_DESC_PTR)
+#define bfin_write_DMA2_10_CURR_DESC_PTR(val) bfin_write32(DMA2_10_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_10_CURR_ADDR()        bfin_read32(DMA2_10_CURR_ADDR)
+#define bfin_write_DMA2_10_CURR_ADDR(val)    bfin_write32(DMA2_10_CURR_ADDR,val)
+#define bfin_read_DMA2_10_CURR_X_COUNT()     bfin_read16(DMA2_10_CURR_X_COUNT)
+#define bfin_write_DMA2_10_CURR_X_COUNT(val) bfin_write16(DMA2_10_CURR_X_COUNT,val)
+#define bfin_read_DMA2_10_CURR_Y_COUNT()     bfin_read16(DMA2_10_CURR_Y_COUNT)
+#define bfin_write_DMA2_10_CURR_Y_COUNT(val) bfin_write16(DMA2_10_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_10_IRQ_STATUS()       bfin_read16(DMA2_10_IRQ_STATUS)
+#define bfin_write_DMA2_10_IRQ_STATUS(val)   bfin_write16(DMA2_10_IRQ_STATUS,val)
+#define bfin_read_DMA2_10_PERIPHERAL_MAP()   bfin_read16(DMA2_10_PERIPHERAL_MAP)
+#define bfin_write_DMA2_10_PERIPHERAL_MAP(val) bfin_write16(DMA2_10_PERIPHERAL_MAP,val)
+#define bfin_read_DMA2_11_CONFIG()           bfin_read16(DMA2_11_CONFIG)
+#define bfin_write_DMA2_11_CONFIG(val)       bfin_write16(DMA2_11_CONFIG,val)
+#define bfin_read_DMA2_11_NEXT_DESC_PTR()    bfin_read32(DMA2_11_NEXT_DESC_PTR)
+#define bfin_write_DMA2_11_NEXT_DESC_PTR(val) bfin_write32(DMA2_11_NEXT_DESC_PTR,val)
+#define bfin_read_DMA2_11_START_ADDR()       bfin_read32(DMA2_11_START_ADDR)
+#define bfin_write_DMA2_11_START_ADDR(val)   bfin_write32(DMA2_11_START_ADDR,val)
+#define bfin_read_DMA2_11_X_COUNT()          bfin_read16(DMA2_11_X_COUNT)
+#define bfin_write_DMA2_11_X_COUNT(val)      bfin_write16(DMA2_11_X_COUNT,val)
+#define bfin_read_DMA2_11_Y_COUNT()          bfin_read16(DMA2_11_Y_COUNT)
+#define bfin_write_DMA2_11_Y_COUNT(val)      bfin_write16(DMA2_11_Y_COUNT,val)
+#define bfin_read_DMA2_11_X_MODIFY()         bfin_read16(DMA2_11_X_MODIFY)
+#define bfin_write_DMA2_11_X_MODIFY(val)     bfin_write16(DMA2_11_X_MODIFY,val)
+#define bfin_read_DMA2_11_Y_MODIFY()         bfin_read16(DMA2_11_Y_MODIFY)
+#define bfin_write_DMA2_11_Y_MODIFY(val)     bfin_write16(DMA2_11_Y_MODIFY,val)
+#define bfin_read_DMA2_11_CURR_DESC_PTR()    bfin_read32(DMA2_11_CURR_DESC_PTR)
+#define bfin_write_DMA2_11_CURR_DESC_PTR(val) bfin_write32(DMA2_11_CURR_DESC_PTR,val)
+#define bfin_read_DMA2_11_CURR_ADDR()        bfin_read32(DMA2_11_CURR_ADDR)
+#define bfin_write_DMA2_11_CURR_ADDR(val)    bfin_write32(DMA2_11_CURR_ADDR,val)
+#define bfin_read_DMA2_11_CURR_X_COUNT()     bfin_read16(DMA2_11_CURR_X_COUNT)
+#define bfin_write_DMA2_11_CURR_X_COUNT(val) bfin_write16(DMA2_11_CURR_X_COUNT,val)
+#define bfin_read_DMA2_11_CURR_Y_COUNT()     bfin_read16(DMA2_11_CURR_Y_COUNT)
+#define bfin_write_DMA2_11_CURR_Y_COUNT(val) bfin_write16(DMA2_11_CURR_Y_COUNT,val)
+#define bfin_read_DMA2_11_IRQ_STATUS()       bfin_read16(DMA2_11_IRQ_STATUS)
+#define bfin_write_DMA2_11_IRQ_STATUS(val)   bfin_write16(DMA2_11_IRQ_STATUS,val)
+#define bfin_read_DMA2_11_PERIPHERAL_MAP()   bfin_read16(DMA2_11_PERIPHERAL_MAP)
+#define bfin_write_DMA2_11_PERIPHERAL_MAP(val) bfin_write16(DMA2_11_PERIPHERAL_MAP,val)
+/* Memory DMA2 Controller registers (0xFFC0 0E80-0xFFC0 0FFF) */
+#define bfin_read_MDMA2_D0_CONFIG()          bfin_read16(MDMA2_D0_CONFIG)
+#define bfin_write_MDMA2_D0_CONFIG(val)      bfin_write16(MDMA2_D0_CONFIG,val)
+#define bfin_read_MDMA2_D0_NEXT_DESC_PTR()   bfin_read32(MDMA2_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA2_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA2_D0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA2_D0_START_ADDR()      bfin_read32(MDMA2_D0_START_ADDR)
+#define bfin_write_MDMA2_D0_START_ADDR(val)  bfin_write32(MDMA2_D0_START_ADDR,val)
+#define bfin_read_MDMA2_D0_X_COUNT()         bfin_read16(MDMA2_D0_X_COUNT)
+#define bfin_write_MDMA2_D0_X_COUNT(val)     bfin_write16(MDMA2_D0_X_COUNT,val)
+#define bfin_read_MDMA2_D0_Y_COUNT()         bfin_read16(MDMA2_D0_Y_COUNT)
+#define bfin_write_MDMA2_D0_Y_COUNT(val)     bfin_write16(MDMA2_D0_Y_COUNT,val)
+#define bfin_read_MDMA2_D0_X_MODIFY()        bfin_read16(MDMA2_D0_X_MODIFY)
+#define bfin_write_MDMA2_D0_X_MODIFY(val)    bfin_write16(MDMA2_D0_X_MODIFY,val)
+#define bfin_read_MDMA2_D0_Y_MODIFY()        bfin_read16(MDMA2_D0_Y_MODIFY)
+#define bfin_write_MDMA2_D0_Y_MODIFY(val)    bfin_write16(MDMA2_D0_Y_MODIFY,val)
+#define bfin_read_MDMA2_D0_CURR_DESC_PTR()   bfin_read32(MDMA2_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA2_D0_CURR_DESC_PTR(val) bfin_write32(MDMA2_D0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA2_D0_CURR_ADDR()       bfin_read32(MDMA2_D0_CURR_ADDR)
+#define bfin_write_MDMA2_D0_CURR_ADDR(val)   bfin_write32(MDMA2_D0_CURR_ADDR,val)
+#define bfin_read_MDMA2_D0_CURR_X_COUNT()    bfin_read16(MDMA2_D0_CURR_X_COUNT)
+#define bfin_write_MDMA2_D0_CURR_X_COUNT(val) bfin_write16(MDMA2_D0_CURR_X_COUNT,val)
+#define bfin_read_MDMA2_D0_CURR_Y_COUNT()    bfin_read16(MDMA2_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA2_D0_CURR_Y_COUNT(val) bfin_write16(MDMA2_D0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA2_D0_IRQ_STATUS()      bfin_read16(MDMA2_D0_IRQ_STATUS)
+#define bfin_write_MDMA2_D0_IRQ_STATUS(val)  bfin_write16(MDMA2_D0_IRQ_STATUS,val)
+#define bfin_read_MDMA2_D0_PERIPHERAL_MAP()  bfin_read16(MDMA2_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA2_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA2_D0_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA2_S0_CONFIG()          bfin_read16(MDMA2_S0_CONFIG)
+#define bfin_write_MDMA2_S0_CONFIG(val)      bfin_write16(MDMA2_S0_CONFIG,val)
+#define bfin_read_MDMA2_S0_NEXT_DESC_PTR()   bfin_read32(MDMA2_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA2_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA2_S0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA2_S0_START_ADDR()      bfin_read32(MDMA2_S0_START_ADDR)
+#define bfin_write_MDMA2_S0_START_ADDR(val)  bfin_write32(MDMA2_S0_START_ADDR,val)
+#define bfin_read_MDMA2_S0_X_COUNT()         bfin_read16(MDMA2_S0_X_COUNT)
+#define bfin_write_MDMA2_S0_X_COUNT(val)     bfin_write16(MDMA2_S0_X_COUNT,val)
+#define bfin_read_MDMA2_S0_Y_COUNT()         bfin_read16(MDMA2_S0_Y_COUNT)
+#define bfin_write_MDMA2_S0_Y_COUNT(val)     bfin_write16(MDMA2_S0_Y_COUNT,val)
+#define bfin_read_MDMA2_S0_X_MODIFY()        bfin_read16(MDMA2_S0_X_MODIFY)
+#define bfin_write_MDMA2_S0_X_MODIFY(val)    bfin_write16(MDMA2_S0_X_MODIFY,val)
+#define bfin_read_MDMA2_S0_Y_MODIFY()        bfin_read16(MDMA2_S0_Y_MODIFY)
+#define bfin_write_MDMA2_S0_Y_MODIFY(val)    bfin_write16(MDMA2_S0_Y_MODIFY,val)
+#define bfin_read_MDMA2_S0_CURR_DESC_PTR()   bfin_read32(MDMA2_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA2_S0_CURR_DESC_PTR(val) bfin_write32(MDMA2_S0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA2_S0_CURR_ADDR()       bfin_read32(MDMA2_S0_CURR_ADDR)
+#define bfin_write_MDMA2_S0_CURR_ADDR(val)   bfin_write32(MDMA2_S0_CURR_ADDR,val)
+#define bfin_read_MDMA2_S0_CURR_X_COUNT()    bfin_read16(MDMA2_S0_CURR_X_COUNT)
+#define bfin_write_MDMA2_S0_CURR_X_COUNT(val) bfin_write16(MDMA2_S0_CURR_X_COUNT,val)
+#define bfin_read_MDMA2_S0_CURR_Y_COUNT()    bfin_read16(MDMA2_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA2_S0_CURR_Y_COUNT(val) bfin_write16(MDMA2_S0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA2_S0_IRQ_STATUS()      bfin_read16(MDMA2_S0_IRQ_STATUS)
+#define bfin_write_MDMA2_S0_IRQ_STATUS(val)  bfin_write16(MDMA2_S0_IRQ_STATUS,val)
+#define bfin_read_MDMA2_S0_PERIPHERAL_MAP()  bfin_read16(MDMA2_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA2_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA2_S0_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA2_D1_CONFIG()          bfin_read16(MDMA2_D1_CONFIG)
+#define bfin_write_MDMA2_D1_CONFIG(val)      bfin_write16(MDMA2_D1_CONFIG,val)
+#define bfin_read_MDMA2_D1_NEXT_DESC_PTR()   bfin_read32(MDMA2_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA2_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA2_D1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA2_D1_START_ADDR()      bfin_read32(MDMA2_D1_START_ADDR)
+#define bfin_write_MDMA2_D1_START_ADDR(val)  bfin_write32(MDMA2_D1_START_ADDR,val)
+#define bfin_read_MDMA2_D1_X_COUNT()         bfin_read16(MDMA2_D1_X_COUNT)
+#define bfin_write_MDMA2_D1_X_COUNT(val)     bfin_write16(MDMA2_D1_X_COUNT,val)
+#define bfin_read_MDMA2_D1_Y_COUNT()         bfin_read16(MDMA2_D1_Y_COUNT)
+#define bfin_write_MDMA2_D1_Y_COUNT(val)     bfin_write16(MDMA2_D1_Y_COUNT,val)
+#define bfin_read_MDMA2_D1_X_MODIFY()        bfin_read16(MDMA2_D1_X_MODIFY)
+#define bfin_write_MDMA2_D1_X_MODIFY(val)    bfin_write16(MDMA2_D1_X_MODIFY,val)
+#define bfin_read_MDMA2_D1_Y_MODIFY()        bfin_read16(MDMA2_D1_Y_MODIFY)
+#define bfin_write_MDMA2_D1_Y_MODIFY(val)    bfin_write16(MDMA2_D1_Y_MODIFY,val)
+#define bfin_read_MDMA2_D1_CURR_DESC_PTR()   bfin_read32(MDMA2_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA2_D1_CURR_DESC_PTR(val) bfin_write32(MDMA2_D1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA2_D1_CURR_ADDR()       bfin_read32(MDMA2_D1_CURR_ADDR)
+#define bfin_write_MDMA2_D1_CURR_ADDR(val)   bfin_write32(MDMA2_D1_CURR_ADDR,val)
+#define bfin_read_MDMA2_D1_CURR_X_COUNT()    bfin_read16(MDMA2_D1_CURR_X_COUNT)
+#define bfin_write_MDMA2_D1_CURR_X_COUNT(val) bfin_write16(MDMA2_D1_CURR_X_COUNT,val)
+#define bfin_read_MDMA2_D1_CURR_Y_COUNT()    bfin_read16(MDMA2_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA2_D1_CURR_Y_COUNT(val) bfin_write16(MDMA2_D1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA2_D1_IRQ_STATUS()      bfin_read16(MDMA2_D1_IRQ_STATUS)
+#define bfin_write_MDMA2_D1_IRQ_STATUS(val)  bfin_write16(MDMA2_D1_IRQ_STATUS,val)
+#define bfin_read_MDMA2_D1_PERIPHERAL_MAP()  bfin_read16(MDMA2_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA2_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA2_D1_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA2_S1_CONFIG()          bfin_read16(MDMA2_S1_CONFIG)
+#define bfin_write_MDMA2_S1_CONFIG(val)      bfin_write16(MDMA2_S1_CONFIG,val)
+#define bfin_read_MDMA2_S1_NEXT_DESC_PTR()   bfin_read32(MDMA2_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA2_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA2_S1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA2_S1_START_ADDR()      bfin_read32(MDMA2_S1_START_ADDR)
+#define bfin_write_MDMA2_S1_START_ADDR(val)  bfin_write32(MDMA2_S1_START_ADDR,val)
+#define bfin_read_MDMA2_S1_X_COUNT()         bfin_read16(MDMA2_S1_X_COUNT)
+#define bfin_write_MDMA2_S1_X_COUNT(val)     bfin_write16(MDMA2_S1_X_COUNT,val)
+#define bfin_read_MDMA2_S1_Y_COUNT()         bfin_read16(MDMA2_S1_Y_COUNT)
+#define bfin_write_MDMA2_S1_Y_COUNT(val)     bfin_write16(MDMA2_S1_Y_COUNT,val)
+#define bfin_read_MDMA2_S1_X_MODIFY()        bfin_read16(MDMA2_S1_X_MODIFY)
+#define bfin_write_MDMA2_S1_X_MODIFY(val)    bfin_write16(MDMA2_S1_X_MODIFY,val)
+#define bfin_read_MDMA2_S1_Y_MODIFY()        bfin_read16(MDMA2_S1_Y_MODIFY)
+#define bfin_write_MDMA2_S1_Y_MODIFY(val)    bfin_write16(MDMA2_S1_Y_MODIFY,val)
+#define bfin_read_MDMA2_S1_CURR_DESC_PTR()   bfin_read32(MDMA2_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA2_S1_CURR_DESC_PTR(val) bfin_write32(MDMA2_S1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA2_S1_CURR_ADDR()       bfin_read32(MDMA2_S1_CURR_ADDR)
+#define bfin_write_MDMA2_S1_CURR_ADDR(val)   bfin_write32(MDMA2_S1_CURR_ADDR,val)
+#define bfin_read_MDMA2_S1_CURR_X_COUNT()    bfin_read16(MDMA2_S1_CURR_X_COUNT)
+#define bfin_write_MDMA2_S1_CURR_X_COUNT(val) bfin_write16(MDMA2_S1_CURR_X_COUNT,val)
+#define bfin_read_MDMA2_S1_CURR_Y_COUNT()    bfin_read16(MDMA2_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA2_S1_CURR_Y_COUNT(val) bfin_write16(MDMA2_S1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA2_S1_IRQ_STATUS()      bfin_read16(MDMA2_S1_IRQ_STATUS)
+#define bfin_write_MDMA2_S1_IRQ_STATUS(val)  bfin_write16(MDMA2_S1_IRQ_STATUS,val)
+#define bfin_read_MDMA2_S1_PERIPHERAL_MAP()  bfin_read16(MDMA2_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA2_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA2_S1_PERIPHERAL_MAP,val)
+/* Internal Memory DMA Registers (0xFFC0_1800 - 0xFFC0_19FF) */
+#define bfin_read_IMDMA_D0_CONFIG()          bfin_read16(IMDMA_D0_CONFIG)
+#define bfin_write_IMDMA_D0_CONFIG(val)      bfin_write16(IMDMA_D0_CONFIG,val)
+#define bfin_read_IMDMA_D0_NEXT_DESC_PTR()   bfin_read32(IMDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_IMDMA_D0_NEXT_DESC_PTR(val) bfin_write32(IMDMA_D0_NEXT_DESC_PTR,val)
+#define bfin_read_IMDMA_D0_START_ADDR()      bfin_read32(IMDMA_D0_START_ADDR)
+#define bfin_write_IMDMA_D0_START_ADDR(val)  bfin_write32(IMDMA_D0_START_ADDR,val)
+#define bfin_read_IMDMA_D0_X_COUNT()         bfin_read16(IMDMA_D0_X_COUNT)
+#define bfin_write_IMDMA_D0_X_COUNT(val)     bfin_write16(IMDMA_D0_X_COUNT,val)
+#define bfin_read_IMDMA_D0_Y_COUNT()         bfin_read16(IMDMA_D0_Y_COUNT)
+#define bfin_write_IMDMA_D0_Y_COUNT(val)     bfin_write16(IMDMA_D0_Y_COUNT,val)
+#define bfin_read_IMDMA_D0_X_MODIFY()        bfin_read16(IMDMA_D0_X_MODIFY)
+#define bfin_write_IMDMA_D0_X_MODIFY(val)    bfin_write16(IMDMA_D0_X_MODIFY,val)
+#define bfin_read_IMDMA_D0_Y_MODIFY()        bfin_read16(IMDMA_D0_Y_MODIFY)
+#define bfin_write_IMDMA_D0_Y_MODIFY(val)    bfin_write16(IMDMA_D0_Y_MODIFY,val)
+#define bfin_read_IMDMA_D0_CURR_DESC_PTR()   bfin_read32(IMDMA_D0_CURR_DESC_PTR)
+#define bfin_write_IMDMA_D0_CURR_DESC_PTR(val) bfin_write32(IMDMA_D0_CURR_DESC_PTR,val)
+#define bfin_read_IMDMA_D0_CURR_ADDR()       bfin_read32(IMDMA_D0_CURR_ADDR)
+#define bfin_write_IMDMA_D0_CURR_ADDR(val)   bfin_write32(IMDMA_D0_CURR_ADDR,val)
+#define bfin_read_IMDMA_D0_CURR_X_COUNT()    bfin_read16(IMDMA_D0_CURR_X_COUNT)
+#define bfin_write_IMDMA_D0_CURR_X_COUNT(val) bfin_write16(IMDMA_D0_CURR_X_COUNT,val)
+#define bfin_read_IMDMA_D0_CURR_Y_COUNT()    bfin_read16(IMDMA_D0_CURR_Y_COUNT)
+#define bfin_write_IMDMA_D0_CURR_Y_COUNT(val) bfin_write16(IMDMA_D0_CURR_Y_COUNT,val)
+#define bfin_read_IMDMA_D0_IRQ_STATUS()      bfin_read16(IMDMA_D0_IRQ_STATUS)
+#define bfin_write_IMDMA_D0_IRQ_STATUS(val)  bfin_write16(IMDMA_D0_IRQ_STATUS,val)
+#define bfin_read_IMDMA_S0_CONFIG()          bfin_read16(IMDMA_S0_CONFIG)
+#define bfin_write_IMDMA_S0_CONFIG(val)      bfin_write16(IMDMA_S0_CONFIG,val)
+#define bfin_read_IMDMA_S0_NEXT_DESC_PTR()   bfin_read32(IMDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_IMDMA_S0_NEXT_DESC_PTR(val) bfin_write32(IMDMA_S0_NEXT_DESC_PTR,val)
+#define bfin_read_IMDMA_S0_START_ADDR()      bfin_read32(IMDMA_S0_START_ADDR)
+#define bfin_write_IMDMA_S0_START_ADDR(val)  bfin_write32(IMDMA_S0_START_ADDR,val)
+#define bfin_read_IMDMA_S0_X_COUNT()         bfin_read16(IMDMA_S0_X_COUNT)
+#define bfin_write_IMDMA_S0_X_COUNT(val)     bfin_write16(IMDMA_S0_X_COUNT,val)
+#define bfin_read_IMDMA_S0_Y_COUNT()         bfin_read16(IMDMA_S0_Y_COUNT)
+#define bfin_write_IMDMA_S0_Y_COUNT(val)     bfin_write16(IMDMA_S0_Y_COUNT,val)
+#define bfin_read_IMDMA_S0_X_MODIFY()        bfin_read16(IMDMA_S0_X_MODIFY)
+#define bfin_write_IMDMA_S0_X_MODIFY(val)    bfin_write16(IMDMA_S0_X_MODIFY,val)
+#define bfin_read_IMDMA_S0_Y_MODIFY()        bfin_read16(IMDMA_S0_Y_MODIFY)
+#define bfin_write_IMDMA_S0_Y_MODIFY(val)    bfin_write16(IMDMA_S0_Y_MODIFY,val)
+#define bfin_read_IMDMA_S0_CURR_DESC_PTR()   bfin_read32(IMDMA_S0_CURR_DESC_PTR)
+#define bfin_write_IMDMA_S0_CURR_DESC_PTR(val) bfin_write32(IMDMA_S0_CURR_DESC_PTR,val)
+#define bfin_read_IMDMA_S0_CURR_ADDR()       bfin_read32(IMDMA_S0_CURR_ADDR)
+#define bfin_write_IMDMA_S0_CURR_ADDR(val)   bfin_write32(IMDMA_S0_CURR_ADDR,val)
+#define bfin_read_IMDMA_S0_CURR_X_COUNT()    bfin_read16(IMDMA_S0_CURR_X_COUNT)
+#define bfin_write_IMDMA_S0_CURR_X_COUNT(val) bfin_write16(IMDMA_S0_CURR_X_COUNT,val)
+#define bfin_read_IMDMA_S0_CURR_Y_COUNT()    bfin_read16(IMDMA_S0_CURR_Y_COUNT)
+#define bfin_write_IMDMA_S0_CURR_Y_COUNT(val) bfin_write16(IMDMA_S0_CURR_Y_COUNT,val)
+#define bfin_read_IMDMA_S0_IRQ_STATUS()      bfin_read16(IMDMA_S0_IRQ_STATUS)
+#define bfin_write_IMDMA_S0_IRQ_STATUS(val)  bfin_write16(IMDMA_S0_IRQ_STATUS,val)
+#define bfin_read_IMDMA_D1_CONFIG()          bfin_read16(IMDMA_D1_CONFIG)
+#define bfin_write_IMDMA_D1_CONFIG(val)      bfin_write16(IMDMA_D1_CONFIG,val)
+#define bfin_read_IMDMA_D1_NEXT_DESC_PTR()   bfin_read32(IMDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_IMDMA_D1_NEXT_DESC_PTR(val) bfin_write32(IMDMA_D1_NEXT_DESC_PTR,val)
+#define bfin_read_IMDMA_D1_START_ADDR()      bfin_read32(IMDMA_D1_START_ADDR)
+#define bfin_write_IMDMA_D1_START_ADDR(val)  bfin_write32(IMDMA_D1_START_ADDR,val)
+#define bfin_read_IMDMA_D1_X_COUNT()         bfin_read16(IMDMA_D1_X_COUNT)
+#define bfin_write_IMDMA_D1_X_COUNT(val)     bfin_write16(IMDMA_D1_X_COUNT,val)
+#define bfin_read_IMDMA_D1_Y_COUNT()         bfin_read16(IMDMA_D1_Y_COUNT)
+#define bfin_write_IMDMA_D1_Y_COUNT(val)     bfin_write16(IMDMA_D1_Y_COUNT,val)
+#define bfin_read_IMDMA_D1_X_MODIFY()        bfin_read16(IMDMA_D1_X_MODIFY)
+#define bfin_write_IMDMA_D1_X_MODIFY(val)    bfin_write16(IMDMA_D1_X_MODIFY,val)
+#define bfin_read_IMDMA_D1_Y_MODIFY()        bfin_read16(IMDMA_D1_Y_MODIFY)
+#define bfin_write_IMDMA_D1_Y_MODIFY(val)    bfin_write16(IMDMA_D1_Y_MODIFY,val)
+#define bfin_read_IMDMA_D1_CURR_DESC_PTR()   bfin_read32(IMDMA_D1_CURR_DESC_PTR)
+#define bfin_write_IMDMA_D1_CURR_DESC_PTR(val) bfin_write32(IMDMA_D1_CURR_DESC_PTR,val)
+#define bfin_read_IMDMA_D1_CURR_ADDR()       bfin_read32(IMDMA_D1_CURR_ADDR)
+#define bfin_write_IMDMA_D1_CURR_ADDR(val)   bfin_write32(IMDMA_D1_CURR_ADDR,val)
+#define bfin_read_IMDMA_D1_CURR_X_COUNT()    bfin_read16(IMDMA_D1_CURR_X_COUNT)
+#define bfin_write_IMDMA_D1_CURR_X_COUNT(val) bfin_write16(IMDMA_D1_CURR_X_COUNT,val)
+#define bfin_read_IMDMA_D1_CURR_Y_COUNT()    bfin_read16(IMDMA_D1_CURR_Y_COUNT)
+#define bfin_write_IMDMA_D1_CURR_Y_COUNT(val) bfin_write16(IMDMA_D1_CURR_Y_COUNT,val)
+#define bfin_read_IMDMA_D1_IRQ_STATUS()      bfin_read16(IMDMA_D1_IRQ_STATUS)
+#define bfin_write_IMDMA_D1_IRQ_STATUS(val)  bfin_write16(IMDMA_D1_IRQ_STATUS,val)
+#define bfin_read_IMDMA_S1_CONFIG()          bfin_read16(IMDMA_S1_CONFIG)
+#define bfin_write_IMDMA_S1_CONFIG(val)      bfin_write16(IMDMA_S1_CONFIG,val)
+#define bfin_read_IMDMA_S1_NEXT_DESC_PTR()   bfin_read32(IMDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_IMDMA_S1_NEXT_DESC_PTR(val) bfin_write32(IMDMA_S1_NEXT_DESC_PTR,val)
+#define bfin_read_IMDMA_S1_START_ADDR()      bfin_read32(IMDMA_S1_START_ADDR)
+#define bfin_write_IMDMA_S1_START_ADDR(val)  bfin_write32(IMDMA_S1_START_ADDR,val)
+#define bfin_read_IMDMA_S1_X_COUNT()         bfin_read16(IMDMA_S1_X_COUNT)
+#define bfin_write_IMDMA_S1_X_COUNT(val)     bfin_write16(IMDMA_S1_X_COUNT,val)
+#define bfin_read_IMDMA_S1_Y_COUNT()         bfin_read16(IMDMA_S1_Y_COUNT)
+#define bfin_write_IMDMA_S1_Y_COUNT(val)     bfin_write16(IMDMA_S1_Y_COUNT,val)
+#define bfin_read_IMDMA_S1_X_MODIFY()        bfin_read16(IMDMA_S1_X_MODIFY)
+#define bfin_write_IMDMA_S1_X_MODIFY(val)    bfin_write16(IMDMA_S1_X_MODIFY,val)
+#define bfin_read_IMDMA_S1_Y_MODIFY()        bfin_read16(IMDMA_S1_Y_MODIFY)
+#define bfin_write_IMDMA_S1_Y_MODIFY(val)    bfin_write16(IMDMA_S1_Y_MODIFY,val)
+#define bfin_read_IMDMA_S1_CURR_DESC_PTR()   bfin_read32(IMDMA_S1_CURR_DESC_PTR)
+#define bfin_write_IMDMA_S1_CURR_DESC_PTR(val) bfin_write32(IMDMA_S1_CURR_DESC_PTR,val)
+#define bfin_read_IMDMA_S1_CURR_ADDR()       bfin_read32(IMDMA_S1_CURR_ADDR)
+#define bfin_write_IMDMA_S1_CURR_ADDR(val)   bfin_write32(IMDMA_S1_CURR_ADDR,val)
+#define bfin_read_IMDMA_S1_CURR_X_COUNT()    bfin_read16(IMDMA_S1_CURR_X_COUNT)
+#define bfin_write_IMDMA_S1_CURR_X_COUNT(val) bfin_write16(IMDMA_S1_CURR_X_COUNT,val)
+#define bfin_read_IMDMA_S1_CURR_Y_COUNT()    bfin_read16(IMDMA_S1_CURR_Y_COUNT)
+#define bfin_write_IMDMA_S1_CURR_Y_COUNT(val) bfin_write16(IMDMA_S1_CURR_Y_COUNT,val)
+#define bfin_read_IMDMA_S1_IRQ_STATUS()      bfin_read16(IMDMA_S1_IRQ_STATUS)
+#define bfin_write_IMDMA_S1_IRQ_STATUS(val)  bfin_write16(IMDMA_S1_IRQ_STATUS,val)
+
+#define bfin_read_MDMA_S0_CONFIG()  bfin_read_MDMA1_S0_CONFIG()
+#define bfin_write_MDMA_S0_CONFIG(val) bfin_write_MDMA1_S0_CONFIG(val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()  bfin_read_MDMA1_S0_IRQ_STATUS()
+#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write_MDMA1_S0_IRQ_STATUS(val)
+#define bfin_read_MDMA_S0_X_MODIFY()  bfin_read_MDMA1_S0_X_MODIFY()
+#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write_MDMA1_S0_X_MODIFY(val)
+#define bfin_read_MDMA_S0_Y_MODIFY()  bfin_read_MDMA1_S0_Y_MODIFY()
+#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write_MDMA1_S0_Y_MODIFY(val)
+#define bfin_read_MDMA_S0_X_COUNT()  bfin_read_MDMA1_S0_X_COUNT()
+#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write_MDMA1_S0_X_COUNT(val)
+#define bfin_read_MDMA_S0_Y_COUNT()  bfin_read_MDMA1_S0_Y_COUNT()
+#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write_MDMA1_S0_Y_COUNT(val)
+#define bfin_read_MDMA_S0_START_ADDR()  bfin_read_MDMA1_S0_START_ADDR()
+#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write_MDMA1_S0_START_ADDR(val)
+#define bfin_read_MDMA_D0_CONFIG()  bfin_read_MDMA1_D0_CONFIG()
+#define bfin_write_MDMA_D0_CONFIG(val) bfin_write_MDMA1_D0_CONFIG(val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()  bfin_read_MDMA1_D0_IRQ_STATUS()
+#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write_MDMA1_D0_IRQ_STATUS(val)
+#define bfin_read_MDMA_D0_X_MODIFY()  bfin_read_MDMA1_D0_X_MODIFY()
+#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write_MDMA1_D0_X_MODIFY(val)
+#define bfin_read_MDMA_D0_Y_MODIFY()  bfin_read_MDMA1_D0_Y_MODIFY()
+#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write_MDMA1_D0_Y_MODIFY(val)
+#define bfin_read_MDMA_D0_X_COUNT()  bfin_read_MDMA1_D0_X_COUNT()
+#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write_MDMA1_D0_X_COUNT(val)
+#define bfin_read_MDMA_D0_Y_COUNT()  bfin_read_MDMA1_D0_Y_COUNT()
+#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write_MDMA1_D0_Y_COUNT(val)
+#define bfin_read_MDMA_D0_START_ADDR()  bfin_read_MDMA1_D0_START_ADDR()
+#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write_MDMA1_D0_START_ADDR(val)
+
+#endif                         /* _CDEF_BF561_H */
diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h
new file mode 100644 (file)
index 0000000..a6de4c6
--- /dev/null
@@ -0,0 +1,1717 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf561/defBF561.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ * SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF561_H
+#define _DEF_BF561_H
+/*
+#if !defined(__ADSPBF561__)
+#warning defBF561.h should only be included for BF561 chip.
+#endif
+*/
+/* include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/*********************************************************************************** */
+/* System MMR Register Map */
+/*********************************************************************************** */
+
+/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+
+#define PLL_CTL                0xFFC00000      /* PLL Control register (16-bit) */
+#define PLL_DIV                                0xFFC00004      /* PLL Divide Register (16-bit) */
+#define VR_CTL                         0xFFC00008      /* Voltage Regulator Control Register (16-bit) */
+#define PLL_STAT               0xFFC0000C      /* PLL Status register (16-bit) */
+#define PLL_LOCKCNT            0xFFC00010      /* PLL Lock Count register (16-bit) */
+#define CHIPID                 0xFFC00014       /* Chip ID Register */
+
+/* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
+#define SICA_SWRST              0xFFC00100     /* Software Reset register */
+#define SICA_SYSCR              0xFFC00104     /* System Reset Configuration register */
+#define SICA_RVECT              0xFFC00108     /* SIC Reset Vector Address Register */
+#define SICA_IMASK              0xFFC0010C     /* SIC Interrupt Mask register 0 - hack to fix old tests */
+#define SICA_IMASK0             0xFFC0010C     /* SIC Interrupt Mask register 0 */
+#define SICA_IMASK1             0xFFC00110     /* SIC Interrupt Mask register 1 */
+#define SICA_IAR0               0xFFC00124     /* SIC Interrupt Assignment Register 0 */
+#define SICA_IAR1               0xFFC00128     /* SIC Interrupt Assignment Register 1 */
+#define SICA_IAR2               0xFFC0012C     /* SIC Interrupt Assignment Register 2 */
+#define SICA_IAR3               0xFFC00130     /* SIC Interrupt Assignment Register 3 */
+#define SICA_IAR4               0xFFC00134     /* SIC Interrupt Assignment Register 4 */
+#define SICA_IAR5               0xFFC00138     /* SIC Interrupt Assignment Register 5 */
+#define SICA_IAR6               0xFFC0013C     /* SIC Interrupt Assignment Register 6 */
+#define SICA_IAR7               0xFFC00140     /* SIC Interrupt Assignment Register 7 */
+#define SICA_ISR0               0xFFC00114     /* SIC Interrupt Status register 0 */
+#define SICA_ISR1               0xFFC00118     /* SIC Interrupt Status register 1 */
+#define SICA_IWR0               0xFFC0011C     /* SIC Interrupt Wakeup-Enable register 0 */
+#define SICA_IWR1               0xFFC00120     /* SIC Interrupt Wakeup-Enable register 1 */
+
+/* System Reset and Interrupt Controller registers for Core B (0xFFC0 1100-0xFFC0 11FF) */
+#define SICB_SWRST              0xFFC01100     /* reserved */
+#define SICB_SYSCR              0xFFC01104     /* reserved */
+#define SICB_RVECT              0xFFC01108     /* SIC Reset Vector Address Register */
+#define SICB_IMASK0             0xFFC0110C     /* SIC Interrupt Mask register 0 */
+#define SICB_IMASK1             0xFFC01110     /* SIC Interrupt Mask register 1 */
+#define SICB_IAR0               0xFFC01124     /* SIC Interrupt Assignment Register 0 */
+#define SICB_IAR1               0xFFC01128     /* SIC Interrupt Assignment Register 1 */
+#define SICB_IAR2               0xFFC0112C     /* SIC Interrupt Assignment Register 2 */
+#define SICB_IAR3               0xFFC01130     /* SIC Interrupt Assignment Register 3 */
+#define SICB_IAR4               0xFFC01134     /* SIC Interrupt Assignment Register 4 */
+#define SICB_IAR5               0xFFC01138     /* SIC Interrupt Assignment Register 5 */
+#define SICB_IAR6               0xFFC0113C     /* SIC Interrupt Assignment Register 6 */
+#define SICB_IAR7               0xFFC01140     /* SIC Interrupt Assignment Register 7 */
+#define SICB_ISR0               0xFFC01114     /* SIC Interrupt Status register 0 */
+#define SICB_ISR1               0xFFC01118     /* SIC Interrupt Status register 1 */
+#define SICB_IWR0               0xFFC0111C     /* SIC Interrupt Wakeup-Enable register 0 */
+#define SICB_IWR1               0xFFC01120     /* SIC Interrupt Wakeup-Enable register 1 */
+
+/* Watchdog Timer registers for Core A (0xFFC0 0200-0xFFC0 02FF) */
+#define WDOGA_CTL                              0xFFC00200      /* Watchdog Control register */
+#define WDOGA_CNT                              0xFFC00204      /* Watchdog Count register */
+#define WDOGA_STAT                             0xFFC00208      /* Watchdog Status register */
+
+/* Watchdog Timer registers for Core B (0xFFC0 1200-0xFFC0 12FF) */
+#define WDOGB_CTL                              0xFFC01200      /* Watchdog Control register */
+#define WDOGB_CNT                              0xFFC01204      /* Watchdog Count register */
+#define WDOGB_STAT                             0xFFC01208      /* Watchdog Status register */
+
+/* UART Controller (0xFFC00400 - 0xFFC004FF) */
+#define UART_THR               0xFFC00400      /* Transmit Holding register */
+#define UART_RBR               0xFFC00400      /* Receive Buffer register */
+#define UART_DLL               0xFFC00400      /* Divisor Latch (Low-Byte) */
+#define UART_IER               0xFFC00404      /* Interrupt Enable Register */
+#define UART_DLH               0xFFC00404      /* Divisor Latch (High-Byte) */
+#define UART_IIR               0xFFC00408      /* Interrupt Identification Register */
+#define UART_LCR               0xFFC0040C      /* Line Control Register */
+#define UART_MCR                               0xFFC00410      /* Modem Control Register */
+#define UART_LSR               0xFFC00414      /* Line Status Register */
+#define UART_MSR               0xFFC00418      /* Modem Status Register */
+#define UART_SCR               0xFFC0041C      /* SCR Scratch Register */
+#define UART_GCTL                      0xFFC00424      /* Global Control Register */
+
+/* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+#define SPI_CTL                        0xFFC00500      /* SPI Control Register */
+#define SPI_FLG                        0xFFC00504      /* SPI Flag register */
+#define SPI_STAT                       0xFFC00508      /* SPI Status register */
+#define SPI_TDBR                       0xFFC0050C      /* SPI Transmit Data Buffer Register */
+#define SPI_RDBR                       0xFFC00510      /* SPI Receive Data Buffer Register */
+#define SPI_BAUD                       0xFFC00514      /* SPI Baud rate Register */
+#define SPI_SHADOW                     0xFFC00518      /* SPI_RDBR Shadow Register */
+
+/* Timer 0-7 registers (0xFFC0 0600-0xFFC0 06FF) */
+#define TIMER0_CONFIG                          0xFFC00600      /* Timer0 Configuration register */
+#define TIMER0_COUNTER                                 0xFFC00604      /* Timer0 Counter register */
+#define TIMER0_PERIOD                          0xFFC00608      /* Timer0 Period register */
+#define TIMER0_WIDTH                           0xFFC0060C      /* Timer0 Width register */
+
+#define TIMER1_CONFIG                          0xFFC00610      /* Timer1 Configuration register */
+#define TIMER1_COUNTER                                 0xFFC00614      /* Timer1 Counter register */
+#define TIMER1_PERIOD                          0xFFC00618      /* Timer1 Period register */
+#define TIMER1_WIDTH                           0xFFC0061C      /* Timer1 Width register */
+
+#define TIMER2_CONFIG                          0xFFC00620      /* Timer2 Configuration register */
+#define TIMER2_COUNTER                                 0xFFC00624      /* Timer2 Counter register */
+#define TIMER2_PERIOD                          0xFFC00628      /* Timer2 Period register */
+#define TIMER2_WIDTH                           0xFFC0062C      /* Timer2 Width register */
+
+#define TIMER3_CONFIG                          0xFFC00630      /* Timer3 Configuration register */
+#define TIMER3_COUNTER                                 0xFFC00634      /* Timer3 Counter register */
+#define TIMER3_PERIOD                          0xFFC00638      /* Timer3 Period register */
+#define TIMER3_WIDTH                           0xFFC0063C      /* Timer3 Width register */
+
+#define TIMER4_CONFIG                          0xFFC00640      /* Timer4 Configuration register */
+#define TIMER4_COUNTER                                 0xFFC00644      /* Timer4 Counter register */
+#define TIMER4_PERIOD                          0xFFC00648      /* Timer4 Period register */
+#define TIMER4_WIDTH                           0xFFC0064C      /* Timer4 Width register */
+
+#define TIMER5_CONFIG                          0xFFC00650      /* Timer5 Configuration register */
+#define TIMER5_COUNTER                                 0xFFC00654      /* Timer5 Counter register */
+#define TIMER5_PERIOD                          0xFFC00658      /* Timer5 Period register */
+#define TIMER5_WIDTH                           0xFFC0065C      /* Timer5 Width register */
+
+#define TIMER6_CONFIG                          0xFFC00660      /* Timer6 Configuration register */
+#define TIMER6_COUNTER                                 0xFFC00664      /* Timer6 Counter register */
+#define TIMER6_PERIOD                          0xFFC00668      /* Timer6 Period register */
+#define TIMER6_WIDTH                           0xFFC0066C      /* Timer6 Width register */
+
+#define TIMER7_CONFIG                          0xFFC00670      /* Timer7 Configuration register */
+#define TIMER7_COUNTER                                 0xFFC00674      /* Timer7 Counter register */
+#define TIMER7_PERIOD                          0xFFC00678      /* Timer7 Period register */
+#define TIMER7_WIDTH                           0xFFC0067C      /* Timer7 Width register */
+
+#define TMRS8_ENABLE                           0xFFC00680      /* Timer Enable Register */
+#define TMRS8_DISABLE                          0xFFC00684      /* Timer Disable register */
+#define TMRS8_STATUS                           0xFFC00688      /* Timer Status register */
+
+/* Timer registers 8-11 (0xFFC0 1600-0xFFC0 16FF) */
+#define TIMER8_CONFIG                          0xFFC01600      /* Timer8 Configuration register */
+#define TIMER8_COUNTER                                 0xFFC01604      /* Timer8 Counter register */
+#define TIMER8_PERIOD                          0xFFC01608      /* Timer8 Period register */
+#define TIMER8_WIDTH                           0xFFC0160C      /* Timer8 Width register */
+
+#define TIMER9_CONFIG                          0xFFC01610      /* Timer9 Configuration register */
+#define TIMER9_COUNTER                                 0xFFC01614      /* Timer9 Counter register */
+#define TIMER9_PERIOD                          0xFFC01618      /* Timer9 Period register */
+#define TIMER9_WIDTH                           0xFFC0161C      /* Timer9 Width register */
+
+#define TIMER10_CONFIG                                 0xFFC01620      /* Timer10 Configuration register */
+#define TIMER10_COUNTER                        0xFFC01624      /* Timer10 Counter register */
+#define TIMER10_PERIOD                                 0xFFC01628      /* Timer10 Period register */
+#define TIMER10_WIDTH                          0xFFC0162C      /* Timer10 Width register */
+
+#define TIMER11_CONFIG                                 0xFFC01630      /* Timer11 Configuration register */
+#define TIMER11_COUNTER                        0xFFC01634      /* Timer11 Counter register */
+#define TIMER11_PERIOD                                 0xFFC01638      /* Timer11 Period register */
+#define TIMER11_WIDTH                          0xFFC0163C      /* Timer11 Width register */
+
+#define TMRS4_ENABLE                           0xFFC01640      /* Timer Enable Register */
+#define TMRS4_DISABLE                          0xFFC01644      /* Timer Disable register */
+#define TMRS4_STATUS                           0xFFC01648      /* Timer Status register */
+
+/* Programmable Flag 0 registers (0xFFC0 0700-0xFFC0 07FF) */
+#define FIO0_FLAG_D                            0xFFC00700      /* Flag Data register */
+#define FIO0_FLAG_C                            0xFFC00704      /* Flag Clear register */
+#define FIO0_FLAG_S                            0xFFC00708      /* Flag Set register */
+#define FIO0_FLAG_T                            0xFFC0070C      /* Flag Toggle register */
+#define FIO0_MASKA_D                           0xFFC00710      /* Flag Mask Interrupt A Data register */
+#define FIO0_MASKA_C                           0xFFC00714      /* Flag Mask Interrupt A Clear register */
+#define FIO0_MASKA_S                           0xFFC00718      /* Flag Mask Interrupt A Set register */
+#define FIO0_MASKA_T                           0xFFC0071C      /* Flag Mask Interrupt A Toggle register */
+#define FIO0_MASKB_D                           0xFFC00720      /* Flag Mask Interrupt B Data register */
+#define FIO0_MASKB_C                           0xFFC00724      /* Flag Mask Interrupt B Clear register */
+#define FIO0_MASKB_S                           0xFFC00728      /* Flag Mask Interrupt B Set register */
+#define FIO0_MASKB_T                           0xFFC0072C      /* Flag Mask Interrupt B Toggle register */
+#define FIO0_DIR                                       0xFFC00730      /* Flag Direction register */
+#define FIO0_POLAR                                     0xFFC00734      /* Flag Polarity register */
+#define FIO0_EDGE                                      0xFFC00738      /* Flag Interrupt Sensitivity register */
+#define FIO0_BOTH                                      0xFFC0073C      /* Flag Set on Both Edges register */
+#define FIO0_INEN                                      0xFFC00740      /* Flag Input Enable register */
+
+/* Programmable Flag 1 registers (0xFFC0 1500-0xFFC0 15FF) */
+#define FIO1_FLAG_D                            0xFFC01500      /* Flag Data register (mask used to directly */
+#define FIO1_FLAG_C                            0xFFC01504      /* Flag Clear register */
+#define FIO1_FLAG_S                            0xFFC01508      /* Flag Set register */
+#define FIO1_FLAG_T                            0xFFC0150C      /* Flag Toggle register (mask used to */
+#define FIO1_MASKA_D                           0xFFC01510      /* Flag Mask Interrupt A Data register */
+#define FIO1_MASKA_C                           0xFFC01514      /* Flag Mask Interrupt A Clear register */
+#define FIO1_MASKA_S                           0xFFC01518      /* Flag Mask Interrupt A Set register */
+#define FIO1_MASKA_T                           0xFFC0151C      /* Flag Mask Interrupt A Toggle register */
+#define FIO1_MASKB_D                           0xFFC01520      /* Flag Mask Interrupt B Data register */
+#define FIO1_MASKB_C                           0xFFC01524      /* Flag Mask Interrupt B Clear register */
+#define FIO1_MASKB_S                           0xFFC01528      /* Flag Mask Interrupt B Set register */
+#define FIO1_MASKB_T                           0xFFC0152C      /* Flag Mask Interrupt B Toggle register */
+#define FIO1_DIR                                       0xFFC01530      /* Flag Direction register */
+#define FIO1_POLAR                                     0xFFC01534      /* Flag Polarity register */
+#define FIO1_EDGE                                      0xFFC01538      /* Flag Interrupt Sensitivity register */
+#define FIO1_BOTH                                      0xFFC0153C      /* Flag Set on Both Edges register */
+#define FIO1_INEN                                      0xFFC01540      /* Flag Input Enable register */
+
+/* Programmable Flag registers (0xFFC0 1700-0xFFC0 17FF) */
+#define FIO2_FLAG_D                            0xFFC01700      /* Flag Data register (mask used to directly */
+#define FIO2_FLAG_C                            0xFFC01704      /* Flag Clear register */
+#define FIO2_FLAG_S                            0xFFC01708      /* Flag Set register */
+#define FIO2_FLAG_T                            0xFFC0170C      /* Flag Toggle register (mask used to */
+#define FIO2_MASKA_D                           0xFFC01710      /* Flag Mask Interrupt A Data register */
+#define FIO2_MASKA_C                           0xFFC01714      /* Flag Mask Interrupt A Clear register */
+#define FIO2_MASKA_S                           0xFFC01718      /* Flag Mask Interrupt A Set register */
+#define FIO2_MASKA_T                           0xFFC0171C      /* Flag Mask Interrupt A Toggle register */
+#define FIO2_MASKB_D                           0xFFC01720      /* Flag Mask Interrupt B Data register */
+#define FIO2_MASKB_C                           0xFFC01724      /* Flag Mask Interrupt B Clear register */
+#define FIO2_MASKB_S                           0xFFC01728      /* Flag Mask Interrupt B Set register */
+#define FIO2_MASKB_T                           0xFFC0172C      /* Flag Mask Interrupt B Toggle register */
+#define FIO2_DIR                                       0xFFC01730      /* Flag Direction register */
+#define FIO2_POLAR                                     0xFFC01734      /* Flag Polarity register */
+#define FIO2_EDGE                                      0xFFC01738      /* Flag Interrupt Sensitivity register */
+#define FIO2_BOTH                                      0xFFC0173C      /* Flag Set on Both Edges register */
+#define FIO2_INEN                                      0xFFC01740      /* Flag Input Enable register */
+
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define SPORT0_TCR1                    0xFFC00800      /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_TCR2                    0xFFC00804      /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_TCLKDIV                 0xFFC00808      /* SPORT0 Transmit Clock Divider */
+#define SPORT0_TFSDIV                          0xFFC0080C      /* SPORT0 Transmit Frame Sync Divider */
+#define SPORT0_TX                      0xFFC00810      /* SPORT0 TX Data Register */
+#define SPORT0_RX                      0xFFC00818      /* SPORT0 RX Data Register */
+#define SPORT0_RCR1                            0xFFC00820      /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_RCR2                            0xFFC00824      /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_RCLKDIV                 0xFFC00828      /* SPORT0 Receive Clock Divider */
+#define SPORT0_RFSDIV                          0xFFC0082C      /* SPORT0 Receive Frame Sync Divider */
+#define SPORT0_STAT                            0xFFC00830      /* SPORT0 Status Register */
+#define SPORT0_CHNL                            0xFFC00834      /* SPORT0 Current Channel Register */
+#define SPORT0_MCMC1                           0xFFC00838      /* SPORT0 Multi-Channel Configuration Register 1 */
+#define SPORT0_MCMC2                           0xFFC0083C      /* SPORT0 Multi-Channel Configuration Register 2 */
+#define SPORT0_MTCS0                           0xFFC00840      /* SPORT0 Multi-Channel Transmit Select Register 0 */
+#define SPORT0_MTCS1                           0xFFC00844      /* SPORT0 Multi-Channel Transmit Select Register 1 */
+#define SPORT0_MTCS2                           0xFFC00848      /* SPORT0 Multi-Channel Transmit Select Register 2 */
+#define SPORT0_MTCS3                           0xFFC0084C      /* SPORT0 Multi-Channel Transmit Select Register 3 */
+#define SPORT0_MRCS0                           0xFFC00850      /* SPORT0 Multi-Channel Receive Select Register 0 */
+#define SPORT0_MRCS1                           0xFFC00854      /* SPORT0 Multi-Channel Receive Select Register 1 */
+#define SPORT0_MRCS2                           0xFFC00858      /* SPORT0 Multi-Channel Receive Select Register 2 */
+#define SPORT0_MRCS3                           0xFFC0085C      /* SPORT0 Multi-Channel Receive Select Register 3 */
+
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define SPORT1_TCR1                            0xFFC00900      /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_TCR2                            0xFFC00904      /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_TCLKDIV                 0xFFC00908      /* SPORT1 Transmit Clock Divider */
+#define SPORT1_TFSDIV                          0xFFC0090C      /* SPORT1 Transmit Frame Sync Divider */
+#define SPORT1_TX                      0xFFC00910      /* SPORT1 TX Data Register */
+#define SPORT1_RX                      0xFFC00918      /* SPORT1 RX Data Register */
+#define SPORT1_RCR1                            0xFFC00920      /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_RCR2                            0xFFC00924      /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_RCLKDIV                 0xFFC00928      /* SPORT1 Receive Clock Divider */
+#define SPORT1_RFSDIV                          0xFFC0092C      /* SPORT1 Receive Frame Sync Divider */
+#define SPORT1_STAT                            0xFFC00930      /* SPORT1 Status Register */
+#define SPORT1_CHNL                            0xFFC00934      /* SPORT1 Current Channel Register */
+#define SPORT1_MCMC1                           0xFFC00938      /* SPORT1 Multi-Channel Configuration Register 1 */
+#define SPORT1_MCMC2                           0xFFC0093C      /* SPORT1 Multi-Channel Configuration Register 2 */
+#define SPORT1_MTCS0                           0xFFC00940      /* SPORT1 Multi-Channel Transmit Select Register 0 */
+#define SPORT1_MTCS1                           0xFFC00944      /* SPORT1 Multi-Channel Transmit Select Register 1 */
+#define SPORT1_MTCS2                           0xFFC00948      /* SPORT1 Multi-Channel Transmit Select Register 2 */
+#define SPORT1_MTCS3                           0xFFC0094C      /* SPORT1 Multi-Channel Transmit Select Register 3 */
+#define SPORT1_MRCS0                           0xFFC00950      /* SPORT1 Multi-Channel Receive Select Register 0 */
+#define SPORT1_MRCS1                           0xFFC00954      /* SPORT1 Multi-Channel Receive Select Register 1 */
+#define SPORT1_MRCS2                           0xFFC00958      /* SPORT1 Multi-Channel Receive Select Register 2 */
+#define SPORT1_MRCS3                           0xFFC0095C      /* SPORT1 Multi-Channel Receive Select Register 3 */
+
+/* Asynchronous Memory Controller - External Bus Interface Unit  */
+#define EBIU_AMGCTL                                    0xFFC00A00      /* Asynchronous Memory Global Control Register */
+#define EBIU_AMBCTL0                           0xFFC00A04      /* Asynchronous Memory Bank Control Register 0 */
+#define EBIU_AMBCTL1                           0xFFC00A08      /* Asynchronous Memory Bank Control Register 1 */
+
+/* SDRAM Controller External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+#define EBIU_SDGCTL                                    0xFFC00A10      /* SDRAM Global Control Register */
+#define EBIU_SDBCTL                                    0xFFC00A14      /* SDRAM Bank Control Register */
+#define EBIU_SDRRC                                     0xFFC00A18      /* SDRAM Refresh Rate Control Register */
+#define EBIU_SDSTAT                                    0xFFC00A1C      /* SDRAM Status Register */
+
+/* Parallel Peripheral Interface (PPI) 0 registers (0xFFC0 1000-0xFFC0 10FF) */
+#define PPI0_CONTROL                           0xFFC01000      /* PPI0 Control register */
+#define PPI0_STATUS                            0xFFC01004      /* PPI0 Status register */
+#define PPI0_COUNT                                     0xFFC01008      /* PPI0 Transfer Count register */
+#define PPI0_DELAY                                     0xFFC0100C      /* PPI0 Delay Count register */
+#define PPI0_FRAME                                     0xFFC01010      /* PPI0 Frame Length register */
+
+/*Parallel Peripheral Interface (PPI) 1 registers (0xFFC0 1300-0xFFC0 13FF) */
+#define PPI1_CONTROL                           0xFFC01300      /* PPI1 Control register */
+#define PPI1_STATUS                            0xFFC01304      /* PPI1 Status register */
+#define PPI1_COUNT                                     0xFFC01308      /* PPI1 Transfer Count register */
+#define PPI1_DELAY                                     0xFFC0130C      /* PPI1 Delay Count register */
+#define PPI1_FRAME                                     0xFFC01310      /* PPI1 Frame Length register */
+
+/*DMA traffic control registers */
+#define        DMA1_TC_PER  0xFFC01B0C /* Traffic control periods */
+#define        DMA1_TC_CNT  0xFFC01B10 /* Traffic control current counts */
+#define        DMA2_TC_PER  0xFFC00B0C /* Traffic control periods */
+#define        DMA2_TC_CNT  0xFFC00B10 /* Traffic control current counts        */
+
+/* DMA1 Controller registers (0xFFC0 1C00-0xFFC0 1FFF) */
+#define DMA1_0_CONFIG 0xFFC01C08       /* DMA1 Channel 0 Configuration register */
+#define DMA1_0_NEXT_DESC_PTR 0xFFC01C00        /* DMA1 Channel 0 Next Descripter Ptr Reg */
+#define DMA1_0_START_ADDR 0xFFC01C04   /* DMA1 Channel 0 Start Address */
+#define DMA1_0_X_COUNT 0xFFC01C10      /* DMA1 Channel 0 Inner Loop Count */
+#define DMA1_0_Y_COUNT 0xFFC01C18      /* DMA1 Channel 0 Outer Loop Count */
+#define DMA1_0_X_MODIFY 0xFFC01C14     /* DMA1 Channel 0 Inner Loop Addr Increment */
+#define DMA1_0_Y_MODIFY 0xFFC01C1C     /* DMA1 Channel 0 Outer Loop Addr Increment */
+#define DMA1_0_CURR_DESC_PTR 0xFFC01C20        /* DMA1 Channel 0 Current Descriptor Pointer */
+#define DMA1_0_CURR_ADDR 0xFFC01C24    /* DMA1 Channel 0 Current Address Pointer */
+#define DMA1_0_CURR_X_COUNT 0xFFC01C30 /* DMA1 Channel 0 Current Inner Loop Count */
+#define DMA1_0_CURR_Y_COUNT 0xFFC01C38 /* DMA1 Channel 0 Current Outer Loop Count */
+#define DMA1_0_IRQ_STATUS 0xFFC01C28   /* DMA1 Channel 0 Interrupt/Status Register */
+#define DMA1_0_PERIPHERAL_MAP 0xFFC01C2C       /* DMA1 Channel 0 Peripheral Map Register */
+
+#define DMA1_1_CONFIG 0xFFC01C48       /* DMA1 Channel 1 Configuration register */
+#define DMA1_1_NEXT_DESC_PTR 0xFFC01C40        /* DMA1 Channel 1 Next Descripter Ptr Reg */
+#define DMA1_1_START_ADDR 0xFFC01C44   /* DMA1 Channel 1 Start Address */
+#define DMA1_1_X_COUNT 0xFFC01C50      /* DMA1 Channel 1 Inner Loop Count */
+#define DMA1_1_Y_COUNT 0xFFC01C58      /* DMA1 Channel 1 Outer Loop Count */
+#define DMA1_1_X_MODIFY 0xFFC01C54     /* DMA1 Channel 1 Inner Loop Addr Increment */
+#define DMA1_1_Y_MODIFY 0xFFC01C5C     /* DMA1 Channel 1 Outer Loop Addr Increment */
+#define DMA1_1_CURR_DESC_PTR 0xFFC01C60        /* DMA1 Channel 1 Current Descriptor Pointer */
+#define DMA1_1_CURR_ADDR 0xFFC01C64    /* DMA1 Channel 1 Current Address Pointer */
+#define DMA1_1_CURR_X_COUNT 0xFFC01C70 /* DMA1 Channel 1 Current Inner Loop Count */
+#define DMA1_1_CURR_Y_COUNT 0xFFC01C78 /* DMA1 Channel 1 Current Outer Loop Count */
+#define DMA1_1_IRQ_STATUS 0xFFC01C68   /* DMA1 Channel 1 Interrupt/Status Register */
+#define DMA1_1_PERIPHERAL_MAP 0xFFC01C6C       /* DMA1 Channel 1 Peripheral Map Register */
+
+#define DMA1_2_CONFIG 0xFFC01C88       /* DMA1 Channel 2 Configuration register */
+#define DMA1_2_NEXT_DESC_PTR 0xFFC01C80        /* DMA1 Channel 2 Next Descripter Ptr Reg */
+#define DMA1_2_START_ADDR 0xFFC01C84   /* DMA1 Channel 2 Start Address */
+#define DMA1_2_X_COUNT 0xFFC01C90      /* DMA1 Channel 2 Inner Loop Count */
+#define DMA1_2_Y_COUNT 0xFFC01C98      /* DMA1 Channel 2 Outer Loop Count */
+#define DMA1_2_X_MODIFY 0xFFC01C94     /* DMA1 Channel 2 Inner Loop Addr Increment */
+#define DMA1_2_Y_MODIFY 0xFFC01C9C     /* DMA1 Channel 2 Outer Loop Addr Increment */
+#define DMA1_2_CURR_DESC_PTR 0xFFC01CA0        /* DMA1 Channel 2 Current Descriptor Pointer */
+#define DMA1_2_CURR_ADDR 0xFFC01CA4    /* DMA1 Channel 2 Current Address Pointer */
+#define DMA1_2_CURR_X_COUNT 0xFFC01CB0 /* DMA1 Channel 2 Current Inner Loop Count */
+#define DMA1_2_CURR_Y_COUNT 0xFFC01CB8 /* DMA1 Channel 2 Current Outer Loop Count */
+#define DMA1_2_IRQ_STATUS 0xFFC01CA8   /* DMA1 Channel 2 Interrupt/Status Register */
+#define DMA1_2_PERIPHERAL_MAP 0xFFC01CAC       /* DMA1 Channel 2 Peripheral Map Register */
+
+#define DMA1_3_CONFIG 0xFFC01CC8       /* DMA1 Channel 3 Configuration register */
+#define DMA1_3_NEXT_DESC_PTR 0xFFC01CC0        /* DMA1 Channel 3 Next Descripter Ptr Reg */
+#define DMA1_3_START_ADDR 0xFFC01CC4   /* DMA1 Channel 3 Start Address */
+#define DMA1_3_X_COUNT 0xFFC01CD0      /* DMA1 Channel 3 Inner Loop Count */
+#define DMA1_3_Y_COUNT 0xFFC01CD8      /* DMA1 Channel 3 Outer Loop Count */
+#define DMA1_3_X_MODIFY 0xFFC01CD4     /* DMA1 Channel 3 Inner Loop Addr Increment */
+#define DMA1_3_Y_MODIFY 0xFFC01CDC     /* DMA1 Channel 3 Outer Loop Addr Increment */
+#define DMA1_3_CURR_DESC_PTR 0xFFC01CE0        /* DMA1 Channel 3 Current Descriptor Pointer */
+#define DMA1_3_CURR_ADDR 0xFFC01CE4    /* DMA1 Channel 3 Current Address Pointer */
+#define DMA1_3_CURR_X_COUNT 0xFFC01CF0 /* DMA1 Channel 3 Current Inner Loop Count */
+#define DMA1_3_CURR_Y_COUNT 0xFFC01CF8 /* DMA1 Channel 3 Current Outer Loop Count */
+#define DMA1_3_IRQ_STATUS 0xFFC01CE8   /* DMA1 Channel 3 Interrupt/Status Register */
+#define DMA1_3_PERIPHERAL_MAP 0xFFC01CEC       /* DMA1 Channel 3 Peripheral Map Register */
+
+#define DMA1_4_CONFIG 0xFFC01D08       /* DMA1 Channel 4 Configuration register */
+#define DMA1_4_NEXT_DESC_PTR 0xFFC01D00        /* DMA1 Channel 4 Next Descripter Ptr Reg */
+#define DMA1_4_START_ADDR 0xFFC01D04   /* DMA1 Channel 4 Start Address */
+#define DMA1_4_X_COUNT 0xFFC01D10      /* DMA1 Channel 4 Inner Loop Count */
+#define DMA1_4_Y_COUNT 0xFFC01D18      /* DMA1 Channel 4 Outer Loop Count */
+#define DMA1_4_X_MODIFY 0xFFC01D14     /* DMA1 Channel 4 Inner Loop Addr Increment */
+#define DMA1_4_Y_MODIFY 0xFFC01D1C     /* DMA1 Channel 4 Outer Loop Addr Increment */
+#define DMA1_4_CURR_DESC_PTR 0xFFC01D20        /* DMA1 Channel 4 Current Descriptor Pointer */
+#define DMA1_4_CURR_ADDR 0xFFC01D24    /* DMA1 Channel 4 Current Address Pointer */
+#define DMA1_4_CURR_X_COUNT 0xFFC01D30 /* DMA1 Channel 4 Current Inner Loop Count */
+#define DMA1_4_CURR_Y_COUNT 0xFFC01D38 /* DMA1 Channel 4 Current Outer Loop Count */
+#define DMA1_4_IRQ_STATUS 0xFFC01D28   /* DMA1 Channel 4 Interrupt/Status Register */
+#define DMA1_4_PERIPHERAL_MAP 0xFFC01D2C       /* DMA1 Channel 4 Peripheral Map Register */
+
+#define DMA1_5_CONFIG 0xFFC01D48       /* DMA1 Channel 5 Configuration register */
+#define DMA1_5_NEXT_DESC_PTR 0xFFC01D40        /* DMA1 Channel 5 Next Descripter Ptr Reg */
+#define DMA1_5_START_ADDR 0xFFC01D44   /* DMA1 Channel 5 Start Address */
+#define DMA1_5_X_COUNT 0xFFC01D50      /* DMA1 Channel 5 Inner Loop Count */
+#define DMA1_5_Y_COUNT 0xFFC01D58      /* DMA1 Channel 5 Outer Loop Count */
+#define DMA1_5_X_MODIFY 0xFFC01D54     /* DMA1 Channel 5 Inner Loop Addr Increment */
+#define DMA1_5_Y_MODIFY 0xFFC01D5C     /* DMA1 Channel 5 Outer Loop Addr Increment */
+#define DMA1_5_CURR_DESC_PTR 0xFFC01D60        /* DMA1 Channel 5 Current Descriptor Pointer */
+#define DMA1_5_CURR_ADDR 0xFFC01D64    /* DMA1 Channel 5 Current Address Pointer */
+#define DMA1_5_CURR_X_COUNT 0xFFC01D70 /* DMA1 Channel 5 Current Inner Loop Count */
+#define DMA1_5_CURR_Y_COUNT 0xFFC01D78 /* DMA1 Channel 5 Current Outer Loop Count */
+#define DMA1_5_IRQ_STATUS 0xFFC01D68   /* DMA1 Channel 5 Interrupt/Status Register */
+#define DMA1_5_PERIPHERAL_MAP 0xFFC01D6C       /* DMA1 Channel 5 Peripheral Map Register */
+
+#define DMA1_6_CONFIG 0xFFC01D88       /* DMA1 Channel 6 Configuration register */
+#define DMA1_6_NEXT_DESC_PTR 0xFFC01D80        /* DMA1 Channel 6 Next Descripter Ptr Reg */
+#define DMA1_6_START_ADDR 0xFFC01D84   /* DMA1 Channel 6 Start Address */
+#define DMA1_6_X_COUNT 0xFFC01D90      /* DMA1 Channel 6 Inner Loop Count */
+#define DMA1_6_Y_COUNT 0xFFC01D98      /* DMA1 Channel 6 Outer Loop Count */
+#define DMA1_6_X_MODIFY 0xFFC01D94     /* DMA1 Channel 6 Inner Loop Addr Increment */
+#define DMA1_6_Y_MODIFY 0xFFC01D9C     /* DMA1 Channel 6 Outer Loop Addr Increment */
+#define DMA1_6_CURR_DESC_PTR 0xFFC01DA0        /* DMA1 Channel 6 Current Descriptor Pointer */
+#define DMA1_6_CURR_ADDR 0xFFC01DA4    /* DMA1 Channel 6 Current Address Pointer */
+#define DMA1_6_CURR_X_COUNT 0xFFC01DB0 /* DMA1 Channel 6 Current Inner Loop Count */
+#define DMA1_6_CURR_Y_COUNT 0xFFC01DB8 /* DMA1 Channel 6 Current Outer Loop Count */
+#define DMA1_6_IRQ_STATUS 0xFFC01DA8   /* DMA1 Channel 6 Interrupt/Status Register */
+#define DMA1_6_PERIPHERAL_MAP 0xFFC01DAC       /* DMA1 Channel 6 Peripheral Map Register */
+
+#define DMA1_7_CONFIG 0xFFC01DC8       /* DMA1 Channel 7 Configuration register */
+#define DMA1_7_NEXT_DESC_PTR 0xFFC01DC0        /* DMA1 Channel 7 Next Descripter Ptr Reg */
+#define DMA1_7_START_ADDR 0xFFC01DC4   /* DMA1 Channel 7 Start Address */
+#define DMA1_7_X_COUNT 0xFFC01DD0      /* DMA1 Channel 7 Inner Loop Count */
+#define DMA1_7_Y_COUNT 0xFFC01DD8      /* DMA1 Channel 7 Outer Loop Count */
+#define DMA1_7_X_MODIFY 0xFFC01DD4     /* DMA1 Channel 7 Inner Loop Addr Increment */
+#define DMA1_7_Y_MODIFY 0xFFC01DDC     /* DMA1 Channel 7 Outer Loop Addr Increment */
+#define DMA1_7_CURR_DESC_PTR 0xFFC01DE0        /* DMA1 Channel 7 Current Descriptor Pointer */
+#define DMA1_7_CURR_ADDR 0xFFC01DE4    /* DMA1 Channel 7 Current Address Pointer */
+#define DMA1_7_CURR_X_COUNT 0xFFC01DF0 /* DMA1 Channel 7 Current Inner Loop Count */
+#define DMA1_7_CURR_Y_COUNT 0xFFC01DF8 /* DMA1 Channel 7 Current Outer Loop Count */
+#define DMA1_7_IRQ_STATUS 0xFFC01DE8   /* DMA1 Channel 7 Interrupt/Status Register */
+#define DMA1_7_PERIPHERAL_MAP 0xFFC01DEC       /* DMA1 Channel 7 Peripheral Map Register */
+
+#define DMA1_8_CONFIG 0xFFC01E08       /* DMA1 Channel 8 Configuration register */
+#define DMA1_8_NEXT_DESC_PTR 0xFFC01E00        /* DMA1 Channel 8 Next Descripter Ptr Reg */
+#define DMA1_8_START_ADDR 0xFFC01E04   /* DMA1 Channel 8 Start Address */
+#define DMA1_8_X_COUNT 0xFFC01E10      /* DMA1 Channel 8 Inner Loop Count */
+#define DMA1_8_Y_COUNT 0xFFC01E18      /* DMA1 Channel 8 Outer Loop Count */
+#define DMA1_8_X_MODIFY 0xFFC01E14     /* DMA1 Channel 8 Inner Loop Addr Increment */
+#define DMA1_8_Y_MODIFY 0xFFC01E1C     /* DMA1 Channel 8 Outer Loop Addr Increment */
+#define DMA1_8_CURR_DESC_PTR 0xFFC01E20        /* DMA1 Channel 8 Current Descriptor Pointer */
+#define DMA1_8_CURR_ADDR 0xFFC01E24    /* DMA1 Channel 8 Current Address Pointer */
+#define DMA1_8_CURR_X_COUNT 0xFFC01E30 /* DMA1 Channel 8 Current Inner Loop Count */
+#define DMA1_8_CURR_Y_COUNT 0xFFC01E38 /* DMA1 Channel 8 Current Outer Loop Count */
+#define DMA1_8_IRQ_STATUS 0xFFC01E28   /* DMA1 Channel 8 Interrupt/Status Register */
+#define DMA1_8_PERIPHERAL_MAP 0xFFC01E2C       /* DMA1 Channel 8 Peripheral Map Register */
+
+#define DMA1_9_CONFIG 0xFFC01E48       /* DMA1 Channel 9 Configuration register */
+#define DMA1_9_NEXT_DESC_PTR 0xFFC01E40        /* DMA1 Channel 9 Next Descripter Ptr Reg */
+#define DMA1_9_START_ADDR 0xFFC01E44   /* DMA1 Channel 9 Start Address */
+#define DMA1_9_X_COUNT 0xFFC01E50      /* DMA1 Channel 9 Inner Loop Count */
+#define DMA1_9_Y_COUNT 0xFFC01E58      /* DMA1 Channel 9 Outer Loop Count */
+#define DMA1_9_X_MODIFY 0xFFC01E54     /* DMA1 Channel 9 Inner Loop Addr Increment */
+#define DMA1_9_Y_MODIFY 0xFFC01E5C     /* DMA1 Channel 9 Outer Loop Addr Increment */
+#define DMA1_9_CURR_DESC_PTR 0xFFC01E60        /* DMA1 Channel 9 Current Descriptor Pointer */
+#define DMA1_9_CURR_ADDR 0xFFC01E64    /* DMA1 Channel 9 Current Address Pointer */
+#define DMA1_9_CURR_X_COUNT 0xFFC01E70 /* DMA1 Channel 9 Current Inner Loop Count */
+#define DMA1_9_CURR_Y_COUNT 0xFFC01E78 /* DMA1 Channel 9 Current Outer Loop Count */
+#define DMA1_9_IRQ_STATUS 0xFFC01E68   /* DMA1 Channel 9 Interrupt/Status Register */
+#define DMA1_9_PERIPHERAL_MAP 0xFFC01E6C       /* DMA1 Channel 9 Peripheral Map Register */
+
+#define DMA1_10_CONFIG 0xFFC01E88      /* DMA1 Channel 10 Configuration register */
+#define DMA1_10_NEXT_DESC_PTR 0xFFC01E80       /* DMA1 Channel 10 Next Descripter Ptr Reg */
+#define DMA1_10_START_ADDR 0xFFC01E84  /* DMA1 Channel 10 Start Address */
+#define DMA1_10_X_COUNT 0xFFC01E90     /* DMA1 Channel 10 Inner Loop Count */
+#define DMA1_10_Y_COUNT 0xFFC01E98     /* DMA1 Channel 10 Outer Loop Count */
+#define DMA1_10_X_MODIFY 0xFFC01E94    /* DMA1 Channel 10 Inner Loop Addr Increment */
+#define DMA1_10_Y_MODIFY 0xFFC01E9C    /* DMA1 Channel 10 Outer Loop Addr Increment */
+#define DMA1_10_CURR_DESC_PTR 0xFFC01EA0       /* DMA1 Channel 10 Current Descriptor Pointer */
+#define DMA1_10_CURR_ADDR 0xFFC01EA4   /* DMA1 Channel 10 Current Address Pointer */
+#define DMA1_10_CURR_X_COUNT 0xFFC01EB0        /* DMA1 Channel 10 Current Inner Loop Count */
+#define DMA1_10_CURR_Y_COUNT 0xFFC01EB8        /* DMA1 Channel 10 Current Outer Loop Count */
+#define DMA1_10_IRQ_STATUS 0xFFC01EA8  /* DMA1 Channel 10 Interrupt/Status Register */
+#define DMA1_10_PERIPHERAL_MAP 0xFFC01EAC      /* DMA1 Channel 10 Peripheral Map Register */
+
+#define DMA1_11_CONFIG 0xFFC01EC8      /* DMA1 Channel 11 Configuration register */
+#define DMA1_11_NEXT_DESC_PTR 0xFFC01EC0       /* DMA1 Channel 11 Next Descripter Ptr Reg */
+#define DMA1_11_START_ADDR 0xFFC01EC4  /* DMA1 Channel 11 Start Address */
+#define DMA1_11_X_COUNT 0xFFC01ED0     /* DMA1 Channel 11 Inner Loop Count */
+#define DMA1_11_Y_COUNT 0xFFC01ED8     /* DMA1 Channel 11 Outer Loop Count */
+#define DMA1_11_X_MODIFY 0xFFC01ED4    /* DMA1 Channel 11 Inner Loop Addr Increment */
+#define DMA1_11_Y_MODIFY 0xFFC01EDC    /* DMA1 Channel 11 Outer Loop Addr Increment */
+#define DMA1_11_CURR_DESC_PTR 0xFFC01EE0       /* DMA1 Channel 11 Current Descriptor Pointer */
+#define DMA1_11_CURR_ADDR 0xFFC01EE4   /* DMA1 Channel 11 Current Address Pointer */
+#define DMA1_11_CURR_X_COUNT 0xFFC01EF0        /* DMA1 Channel 11 Current Inner Loop Count */
+#define DMA1_11_CURR_Y_COUNT 0xFFC01EF8        /* DMA1 Channel 11 Current Outer Loop Count */
+#define DMA1_11_IRQ_STATUS 0xFFC01EE8  /* DMA1 Channel 11 Interrupt/Status Register */
+#define DMA1_11_PERIPHERAL_MAP 0xFFC01EEC      /* DMA1 Channel 11 Peripheral Map Register */
+
+/* Memory DMA1 Controller registers (0xFFC0 1E80-0xFFC0 1FFF) */
+#define MDMA1_D0_CONFIG 0xFFC01F08     /*MemDMA1 Stream 0 Destination Configuration */
+#define MDMA1_D0_NEXT_DESC_PTR 0xFFC01F00      /*MemDMA1 Stream 0 Destination Next Descriptor Ptr Reg */
+#define MDMA1_D0_START_ADDR 0xFFC01F04 /*MemDMA1 Stream 0 Destination Start Address */
+#define MDMA1_D0_X_COUNT 0xFFC01F10    /*MemDMA1 Stream 0 Destination Inner-Loop Count */
+#define MDMA1_D0_Y_COUNT 0xFFC01F18    /*MemDMA1 Stream 0 Destination Outer-Loop Count */
+#define MDMA1_D0_X_MODIFY 0xFFC01F14   /*MemDMA1 Stream 0 Dest Inner-Loop Address-Increment */
+#define MDMA1_D0_Y_MODIFY 0xFFC01F1C   /*MemDMA1 Stream 0 Dest Outer-Loop Address-Increment */
+#define MDMA1_D0_CURR_DESC_PTR 0xFFC01F20      /*MemDMA1 Stream 0 Dest Current Descriptor Ptr reg */
+#define MDMA1_D0_CURR_ADDR 0xFFC01F24  /*MemDMA1 Stream 0 Destination Current Address */
+#define MDMA1_D0_CURR_X_COUNT 0xFFC01F30       /*MemDMA1 Stream 0 Dest Current Inner-Loop Count */
+#define MDMA1_D0_CURR_Y_COUNT 0xFFC01F38       /*MemDMA1 Stream 0 Dest Current Outer-Loop Count */
+#define MDMA1_D0_IRQ_STATUS 0xFFC01F28 /*MemDMA1 Stream 0 Destination Interrupt/Status */
+#define MDMA1_D0_PERIPHERAL_MAP 0xFFC01F2C     /*MemDMA1 Stream 0 Destination Peripheral Map */
+
+#define MDMA1_S0_CONFIG 0xFFC01F48     /*MemDMA1 Stream 0 Source Configuration */
+#define MDMA1_S0_NEXT_DESC_PTR 0xFFC01F40      /*MemDMA1 Stream 0 Source Next Descriptor Ptr Reg */
+#define MDMA1_S0_START_ADDR 0xFFC01F44 /*MemDMA1 Stream 0 Source Start Address */
+#define MDMA1_S0_X_COUNT 0xFFC01F50    /*MemDMA1 Stream 0 Source Inner-Loop Count */
+#define MDMA1_S0_Y_COUNT 0xFFC01F58    /*MemDMA1 Stream 0 Source Outer-Loop Count */
+#define MDMA1_S0_X_MODIFY 0xFFC01F54   /*MemDMA1 Stream 0 Source Inner-Loop Address-Increment */
+#define MDMA1_S0_Y_MODIFY 0xFFC01F5C   /*MemDMA1 Stream 0 Source Outer-Loop Address-Increment */
+#define MDMA1_S0_CURR_DESC_PTR 0xFFC01F60      /*MemDMA1 Stream 0 Source Current Descriptor Ptr reg */
+#define MDMA1_S0_CURR_ADDR 0xFFC01F64  /*MemDMA1 Stream 0 Source Current Address */
+#define MDMA1_S0_CURR_X_COUNT 0xFFC01F70       /*MemDMA1 Stream 0 Source Current Inner-Loop Count */
+#define MDMA1_S0_CURR_Y_COUNT 0xFFC01F78       /*MemDMA1 Stream 0 Source Current Outer-Loop Count */
+#define MDMA1_S0_IRQ_STATUS 0xFFC01F68 /*MemDMA1 Stream 0 Source Interrupt/Status */
+#define MDMA1_S0_PERIPHERAL_MAP 0xFFC01F6C     /*MemDMA1 Stream 0 Source Peripheral Map */
+
+#define MDMA1_D1_CONFIG 0xFFC01F88     /*MemDMA1 Stream 1 Destination Configuration */
+#define MDMA1_D1_NEXT_DESC_PTR 0xFFC01F80      /*MemDMA1 Stream 1 Destination Next Descriptor Ptr Reg */
+#define MDMA1_D1_START_ADDR 0xFFC01F84 /*MemDMA1 Stream 1 Destination Start Address */
+#define MDMA1_D1_X_COUNT 0xFFC01F90    /*MemDMA1 Stream 1 Destination Inner-Loop Count */
+#define MDMA1_D1_Y_COUNT 0xFFC01F98    /*MemDMA1 Stream 1 Destination Outer-Loop Count */
+#define MDMA1_D1_X_MODIFY 0xFFC01F94   /*MemDMA1 Stream 1 Dest Inner-Loop Address-Increment */
+#define MDMA1_D1_Y_MODIFY 0xFFC01F9C   /*MemDMA1 Stream 1 Dest Outer-Loop Address-Increment */
+#define MDMA1_D1_CURR_DESC_PTR 0xFFC01FA0      /*MemDMA1 Stream 1 Dest Current Descriptor Ptr reg */
+#define MDMA1_D1_CURR_ADDR 0xFFC01FA4  /*MemDMA1 Stream 1 Dest Current Address */
+#define MDMA1_D1_CURR_X_COUNT 0xFFC01FB0       /*MemDMA1 Stream 1 Dest Current Inner-Loop Count */
+#define MDMA1_D1_CURR_Y_COUNT 0xFFC01FB8       /*MemDMA1 Stream 1 Dest Current Outer-Loop Count */
+#define MDMA1_D1_IRQ_STATUS 0xFFC01FA8 /*MemDMA1 Stream 1 Dest Interrupt/Status */
+#define MDMA1_D1_PERIPHERAL_MAP 0xFFC01FAC     /*MemDMA1 Stream 1 Dest Peripheral Map */
+
+#define MDMA1_S1_CONFIG 0xFFC01FC8     /*MemDMA1 Stream 1 Source Configuration */
+#define MDMA1_S1_NEXT_DESC_PTR 0xFFC01FC0      /*MemDMA1 Stream 1 Source Next Descriptor Ptr Reg */
+#define MDMA1_S1_START_ADDR 0xFFC01FC4 /*MemDMA1 Stream 1 Source Start Address */
+#define MDMA1_S1_X_COUNT 0xFFC01FD0    /*MemDMA1 Stream 1 Source Inner-Loop Count */
+#define MDMA1_S1_Y_COUNT 0xFFC01FD8    /*MemDMA1 Stream 1 Source Outer-Loop Count */
+#define MDMA1_S1_X_MODIFY 0xFFC01FD4   /*MemDMA1 Stream 1 Source Inner-Loop Address-Increment */
+#define MDMA1_S1_Y_MODIFY 0xFFC01FDC   /*MemDMA1 Stream 1 Source Outer-Loop Address-Increment */
+#define MDMA1_S1_CURR_DESC_PTR 0xFFC01FE0      /*MemDMA1 Stream 1 Source Current Descriptor Ptr reg */
+#define MDMA1_S1_CURR_ADDR 0xFFC01FE4  /*MemDMA1 Stream 1 Source Current Address */
+#define MDMA1_S1_CURR_X_COUNT 0xFFC01FF0       /*MemDMA1 Stream 1 Source Current Inner-Loop Count */
+#define MDMA1_S1_CURR_Y_COUNT 0xFFC01FF8       /*MemDMA1 Stream 1 Source Current Outer-Loop Count */
+#define MDMA1_S1_IRQ_STATUS 0xFFC01FE8 /*MemDMA1 Stream 1 Source Interrupt/Status */
+#define MDMA1_S1_PERIPHERAL_MAP 0xFFC01FEC     /*MemDMA1 Stream 1 Source Peripheral Map */
+
+/* DMA2 Controller registers (0xFFC0 0C00-0xFFC0 0DFF) */
+#define DMA2_0_CONFIG 0xFFC00C08       /* DMA2 Channel 0 Configuration register */
+#define DMA2_0_NEXT_DESC_PTR 0xFFC00C00        /* DMA2 Channel 0 Next Descripter Ptr Reg */
+#define DMA2_0_START_ADDR 0xFFC00C04   /* DMA2 Channel 0 Start Address */
+#define DMA2_0_X_COUNT 0xFFC00C10      /* DMA2 Channel 0 Inner Loop Count */
+#define DMA2_0_Y_COUNT 0xFFC00C18      /* DMA2 Channel 0 Outer Loop Count */
+#define DMA2_0_X_MODIFY 0xFFC00C14     /* DMA2 Channel 0 Inner Loop Addr Increment */
+#define DMA2_0_Y_MODIFY 0xFFC00C1C     /* DMA2 Channel 0 Outer Loop Addr Increment */
+#define DMA2_0_CURR_DESC_PTR 0xFFC00C20        /* DMA2 Channel 0 Current Descriptor Pointer */
+#define DMA2_0_CURR_ADDR 0xFFC00C24    /* DMA2 Channel 0 Current Address Pointer */
+#define DMA2_0_CURR_X_COUNT 0xFFC00C30 /* DMA2 Channel 0 Current Inner Loop Count */
+#define DMA2_0_CURR_Y_COUNT 0xFFC00C38 /* DMA2 Channel 0 Current Outer Loop Count */
+#define DMA2_0_IRQ_STATUS 0xFFC00C28   /* DMA2 Channel 0 Interrupt/Status Register */
+#define DMA2_0_PERIPHERAL_MAP 0xFFC00C2C       /* DMA2 Channel 0 Peripheral Map Register */
+
+#define DMA2_1_CONFIG 0xFFC00C48       /* DMA2 Channel 1 Configuration register */
+#define DMA2_1_NEXT_DESC_PTR 0xFFC00C40        /* DMA2 Channel 1 Next Descripter Ptr Reg */
+#define DMA2_1_START_ADDR 0xFFC00C44   /* DMA2 Channel 1 Start Address */
+#define DMA2_1_X_COUNT 0xFFC00C50      /* DMA2 Channel 1 Inner Loop Count */
+#define DMA2_1_Y_COUNT 0xFFC00C58      /* DMA2 Channel 1 Outer Loop Count */
+#define DMA2_1_X_MODIFY 0xFFC00C54     /* DMA2 Channel 1 Inner Loop Addr Increment */
+#define DMA2_1_Y_MODIFY 0xFFC00C5C     /* DMA2 Channel 1 Outer Loop Addr Increment */
+#define DMA2_1_CURR_DESC_PTR 0xFFC00C60        /* DMA2 Channel 1 Current Descriptor Pointer */
+#define DMA2_1_CURR_ADDR 0xFFC00C64    /* DMA2 Channel 1 Current Address Pointer */
+#define DMA2_1_CURR_X_COUNT 0xFFC00C70 /* DMA2 Channel 1 Current Inner Loop Count */
+#define DMA2_1_CURR_Y_COUNT 0xFFC00C78 /* DMA2 Channel 1 Current Outer Loop Count */
+#define DMA2_1_IRQ_STATUS 0xFFC00C68   /* DMA2 Channel 1 Interrupt/Status Register */
+#define DMA2_1_PERIPHERAL_MAP 0xFFC00C6C       /* DMA2 Channel 1 Peripheral Map Register */
+
+#define DMA2_2_CONFIG 0xFFC00C88       /* DMA2 Channel 2 Configuration register */
+#define DMA2_2_NEXT_DESC_PTR 0xFFC00C80        /* DMA2 Channel 2 Next Descripter Ptr Reg */
+#define DMA2_2_START_ADDR 0xFFC00C84   /* DMA2 Channel 2 Start Address */
+#define DMA2_2_X_COUNT 0xFFC00C90      /* DMA2 Channel 2 Inner Loop Count */
+#define DMA2_2_Y_COUNT 0xFFC00C98      /* DMA2 Channel 2 Outer Loop Count */
+#define DMA2_2_X_MODIFY 0xFFC00C94     /* DMA2 Channel 2 Inner Loop Addr Increment */
+#define DMA2_2_Y_MODIFY 0xFFC00C9C     /* DMA2 Channel 2 Outer Loop Addr Increment */
+#define DMA2_2_CURR_DESC_PTR 0xFFC00CA0        /* DMA2 Channel 2 Current Descriptor Pointer */
+#define DMA2_2_CURR_ADDR 0xFFC00CA4    /* DMA2 Channel 2 Current Address Pointer */
+#define DMA2_2_CURR_X_COUNT 0xFFC00CB0 /* DMA2 Channel 2 Current Inner Loop Count */
+#define DMA2_2_CURR_Y_COUNT 0xFFC00CB8 /* DMA2 Channel 2 Current Outer Loop Count */
+#define DMA2_2_IRQ_STATUS 0xFFC00CA8   /* DMA2 Channel 2 Interrupt/Status Register */
+#define DMA2_2_PERIPHERAL_MAP 0xFFC00CAC       /* DMA2 Channel 2 Peripheral Map Register */
+
+#define DMA2_3_CONFIG 0xFFC00CC8       /* DMA2 Channel 3 Configuration register */
+#define DMA2_3_NEXT_DESC_PTR 0xFFC00CC0        /* DMA2 Channel 3 Next Descripter Ptr Reg */
+#define DMA2_3_START_ADDR 0xFFC00CC4   /* DMA2 Channel 3 Start Address */
+#define DMA2_3_X_COUNT 0xFFC00CD0      /* DMA2 Channel 3 Inner Loop Count */
+#define DMA2_3_Y_COUNT 0xFFC00CD8      /* DMA2 Channel 3 Outer Loop Count */
+#define DMA2_3_X_MODIFY 0xFFC00CD4     /* DMA2 Channel 3 Inner Loop Addr Increment */
+#define DMA2_3_Y_MODIFY 0xFFC00CDC     /* DMA2 Channel 3 Outer Loop Addr Increment */
+#define DMA2_3_CURR_DESC_PTR 0xFFC00CE0        /* DMA2 Channel 3 Current Descriptor Pointer */
+#define DMA2_3_CURR_ADDR 0xFFC00CE4    /* DMA2 Channel 3 Current Address Pointer */
+#define DMA2_3_CURR_X_COUNT 0xFFC00CF0 /* DMA2 Channel 3 Current Inner Loop Count */
+#define DMA2_3_CURR_Y_COUNT 0xFFC00CF8 /* DMA2 Channel 3 Current Outer Loop Count */
+#define DMA2_3_IRQ_STATUS 0xFFC00CE8   /* DMA2 Channel 3 Interrupt/Status Register */
+#define DMA2_3_PERIPHERAL_MAP 0xFFC00CEC       /* DMA2 Channel 3 Peripheral Map Register */
+
+#define DMA2_4_CONFIG 0xFFC00D08       /* DMA2 Channel 4 Configuration register */
+#define DMA2_4_NEXT_DESC_PTR 0xFFC00D00        /* DMA2 Channel 4 Next Descripter Ptr Reg */
+#define DMA2_4_START_ADDR 0xFFC00D04   /* DMA2 Channel 4 Start Address */
+#define DMA2_4_X_COUNT 0xFFC00D10      /* DMA2 Channel 4 Inner Loop Count */
+#define DMA2_4_Y_COUNT 0xFFC00D18      /* DMA2 Channel 4 Outer Loop Count */
+#define DMA2_4_X_MODIFY 0xFFC00D14     /* DMA2 Channel 4 Inner Loop Addr Increment */
+#define DMA2_4_Y_MODIFY 0xFFC00D1C     /* DMA2 Channel 4 Outer Loop Addr Increment */
+#define DMA2_4_CURR_DESC_PTR 0xFFC00D20        /* DMA2 Channel 4 Current Descriptor Pointer */
+#define DMA2_4_CURR_ADDR 0xFFC00D24    /* DMA2 Channel 4 Current Address Pointer */
+#define DMA2_4_CURR_X_COUNT 0xFFC00D30 /* DMA2 Channel 4 Current Inner Loop Count */
+#define DMA2_4_CURR_Y_COUNT 0xFFC00D38 /* DMA2 Channel 4 Current Outer Loop Count */
+#define DMA2_4_IRQ_STATUS 0xFFC00D28   /* DMA2 Channel 4 Interrupt/Status Register */
+#define DMA2_4_PERIPHERAL_MAP 0xFFC00D2C       /* DMA2 Channel 4 Peripheral Map Register */
+
+#define DMA2_5_CONFIG 0xFFC00D48       /* DMA2 Channel 5 Configuration register */
+#define DMA2_5_NEXT_DESC_PTR 0xFFC00D40        /* DMA2 Channel 5 Next Descripter Ptr Reg */
+#define DMA2_5_START_ADDR 0xFFC00D44   /* DMA2 Channel 5 Start Address */
+#define DMA2_5_X_COUNT 0xFFC00D50      /* DMA2 Channel 5 Inner Loop Count */
+#define DMA2_5_Y_COUNT 0xFFC00D58      /* DMA2 Channel 5 Outer Loop Count */
+#define DMA2_5_X_MODIFY 0xFFC00D54     /* DMA2 Channel 5 Inner Loop Addr Increment */
+#define DMA2_5_Y_MODIFY 0xFFC00D5C     /* DMA2 Channel 5 Outer Loop Addr Increment */
+#define DMA2_5_CURR_DESC_PTR 0xFFC00D60        /* DMA2 Channel 5 Current Descriptor Pointer */
+#define DMA2_5_CURR_ADDR 0xFFC00D64    /* DMA2 Channel 5 Current Address Pointer */
+#define DMA2_5_CURR_X_COUNT 0xFFC00D70 /* DMA2 Channel 5 Current Inner Loop Count */
+#define DMA2_5_CURR_Y_COUNT 0xFFC00D78 /* DMA2 Channel 5 Current Outer Loop Count */
+#define DMA2_5_IRQ_STATUS 0xFFC00D68   /* DMA2 Channel 5 Interrupt/Status Register */
+#define DMA2_5_PERIPHERAL_MAP 0xFFC00D6C       /* DMA2 Channel 5 Peripheral Map Register */
+
+#define DMA2_6_CONFIG 0xFFC00D88       /* DMA2 Channel 6 Configuration register */
+#define DMA2_6_NEXT_DESC_PTR 0xFFC00D80        /* DMA2 Channel 6 Next Descripter Ptr Reg */
+#define DMA2_6_START_ADDR 0xFFC00D84   /* DMA2 Channel 6 Start Address */
+#define DMA2_6_X_COUNT 0xFFC00D90      /* DMA2 Channel 6 Inner Loop Count */
+#define DMA2_6_Y_COUNT 0xFFC00D98      /* DMA2 Channel 6 Outer Loop Count */
+#define DMA2_6_X_MODIFY 0xFFC00D94     /* DMA2 Channel 6 Inner Loop Addr Increment */
+#define DMA2_6_Y_MODIFY 0xFFC00D9C     /* DMA2 Channel 6 Outer Loop Addr Increment */
+#define DMA2_6_CURR_DESC_PTR 0xFFC00DA0        /* DMA2 Channel 6 Current Descriptor Pointer */
+#define DMA2_6_CURR_ADDR 0xFFC00DA4    /* DMA2 Channel 6 Current Address Pointer */
+#define DMA2_6_CURR_X_COUNT 0xFFC00DB0 /* DMA2 Channel 6 Current Inner Loop Count */
+#define DMA2_6_CURR_Y_COUNT 0xFFC00DB8 /* DMA2 Channel 6 Current Outer Loop Count */
+#define DMA2_6_IRQ_STATUS 0xFFC00DA8   /* DMA2 Channel 6 Interrupt/Status Register */
+#define DMA2_6_PERIPHERAL_MAP 0xFFC00DAC       /* DMA2 Channel 6 Peripheral Map Register */
+
+#define DMA2_7_CONFIG 0xFFC00DC8       /* DMA2 Channel 7 Configuration register */
+#define DMA2_7_NEXT_DESC_PTR 0xFFC00DC0        /* DMA2 Channel 7 Next Descripter Ptr Reg */
+#define DMA2_7_START_ADDR 0xFFC00DC4   /* DMA2 Channel 7 Start Address */
+#define DMA2_7_X_COUNT 0xFFC00DD0      /* DMA2 Channel 7 Inner Loop Count */
+#define DMA2_7_Y_COUNT 0xFFC00DD8      /* DMA2 Channel 7 Outer Loop Count */
+#define DMA2_7_X_MODIFY 0xFFC00DD4     /* DMA2 Channel 7 Inner Loop Addr Increment */
+#define DMA2_7_Y_MODIFY 0xFFC00DDC     /* DMA2 Channel 7 Outer Loop Addr Increment */
+#define DMA2_7_CURR_DESC_PTR 0xFFC00DE0        /* DMA2 Channel 7 Current Descriptor Pointer */
+#define DMA2_7_CURR_ADDR 0xFFC00DE4    /* DMA2 Channel 7 Current Address Pointer */
+#define DMA2_7_CURR_X_COUNT 0xFFC00DF0 /* DMA2 Channel 7 Current Inner Loop Count */
+#define DMA2_7_CURR_Y_COUNT 0xFFC00DF8 /* DMA2 Channel 7 Current Outer Loop Count */
+#define DMA2_7_IRQ_STATUS 0xFFC00DE8   /* DMA2 Channel 7 Interrupt/Status Register */
+#define DMA2_7_PERIPHERAL_MAP 0xFFC00DEC       /* DMA2 Channel 7 Peripheral Map Register */
+
+#define DMA2_8_CONFIG 0xFFC00E08       /* DMA2 Channel 8 Configuration register */
+#define DMA2_8_NEXT_DESC_PTR 0xFFC00E00        /* DMA2 Channel 8 Next Descripter Ptr Reg */
+#define DMA2_8_START_ADDR 0xFFC00E04   /* DMA2 Channel 8 Start Address */
+#define DMA2_8_X_COUNT 0xFFC00E10      /* DMA2 Channel 8 Inner Loop Count */
+#define DMA2_8_Y_COUNT 0xFFC00E18      /* DMA2 Channel 8 Outer Loop Count */
+#define DMA2_8_X_MODIFY 0xFFC00E14     /* DMA2 Channel 8 Inner Loop Addr Increment */
+#define DMA2_8_Y_MODIFY 0xFFC00E1C     /* DMA2 Channel 8 Outer Loop Addr Increment */
+#define DMA2_8_CURR_DESC_PTR 0xFFC00E20        /* DMA2 Channel 8 Current Descriptor Pointer */
+#define DMA2_8_CURR_ADDR 0xFFC00E24    /* DMA2 Channel 8 Current Address Pointer */
+#define DMA2_8_CURR_X_COUNT 0xFFC00E30 /* DMA2 Channel 8 Current Inner Loop Count */
+#define DMA2_8_CURR_Y_COUNT 0xFFC00E38 /* DMA2 Channel 8 Current Outer Loop Count */
+#define DMA2_8_IRQ_STATUS 0xFFC00E28   /* DMA2 Channel 8 Interrupt/Status Register */
+#define DMA2_8_PERIPHERAL_MAP 0xFFC00E2C       /* DMA2 Channel 8 Peripheral Map Register */
+
+#define DMA2_9_CONFIG 0xFFC00E48       /* DMA2 Channel 9 Configuration register */
+#define DMA2_9_NEXT_DESC_PTR 0xFFC00E40        /* DMA2 Channel 9 Next Descripter Ptr Reg */
+#define DMA2_9_START_ADDR 0xFFC00E44   /* DMA2 Channel 9 Start Address */
+#define DMA2_9_X_COUNT 0xFFC00E50      /* DMA2 Channel 9 Inner Loop Count */
+#define DMA2_9_Y_COUNT 0xFFC00E58      /* DMA2 Channel 9 Outer Loop Count */
+#define DMA2_9_X_MODIFY 0xFFC00E54     /* DMA2 Channel 9 Inner Loop Addr Increment */
+#define DMA2_9_Y_MODIFY 0xFFC00E5C     /* DMA2 Channel 9 Outer Loop Addr Increment */
+#define DMA2_9_CURR_DESC_PTR 0xFFC00E60        /* DMA2 Channel 9 Current Descriptor Pointer */
+#define DMA2_9_CURR_ADDR 0xFFC00E64    /* DMA2 Channel 9 Current Address Pointer */
+#define DMA2_9_CURR_X_COUNT 0xFFC00E70 /* DMA2 Channel 9 Current Inner Loop Count */
+#define DMA2_9_CURR_Y_COUNT 0xFFC00E78 /* DMA2 Channel 9 Current Outer Loop Count */
+#define DMA2_9_IRQ_STATUS 0xFFC00E68   /* DMA2 Channel 9 Interrupt/Status Register */
+#define DMA2_9_PERIPHERAL_MAP 0xFFC00E6C       /* DMA2 Channel 9 Peripheral Map Register */
+
+#define DMA2_10_CONFIG 0xFFC00E88      /* DMA2 Channel 10 Configuration register */
+#define DMA2_10_NEXT_DESC_PTR 0xFFC00E80       /* DMA2 Channel 10 Next Descripter Ptr Reg */
+#define DMA2_10_START_ADDR 0xFFC00E84  /* DMA2 Channel 10 Start Address */
+#define DMA2_10_X_COUNT 0xFFC00E90     /* DMA2 Channel 10 Inner Loop Count */
+#define DMA2_10_Y_COUNT 0xFFC00E98     /* DMA2 Channel 10 Outer Loop Count */
+#define DMA2_10_X_MODIFY 0xFFC00E94    /* DMA2 Channel 10 Inner Loop Addr Increment */
+#define DMA2_10_Y_MODIFY 0xFFC00E9C    /* DMA2 Channel 10 Outer Loop Addr Increment */
+#define DMA2_10_CURR_DESC_PTR 0xFFC00EA0       /* DMA2 Channel 10 Current Descriptor Pointer */
+#define DMA2_10_CURR_ADDR 0xFFC00EA4   /* DMA2 Channel 10 Current Address Pointer */
+#define DMA2_10_CURR_X_COUNT 0xFFC00EB0        /* DMA2 Channel 10 Current Inner Loop Count */
+#define DMA2_10_CURR_Y_COUNT 0xFFC00EB8        /* DMA2 Channel 10 Current Outer Loop Count */
+#define DMA2_10_IRQ_STATUS 0xFFC00EA8  /* DMA2 Channel 10 Interrupt/Status Register */
+#define DMA2_10_PERIPHERAL_MAP 0xFFC00EAC      /* DMA2 Channel 10 Peripheral Map Register */
+
+#define DMA2_11_CONFIG 0xFFC00EC8      /* DMA2 Channel 11 Configuration register */
+#define DMA2_11_NEXT_DESC_PTR 0xFFC00EC0       /* DMA2 Channel 11 Next Descripter Ptr Reg */
+#define DMA2_11_START_ADDR 0xFFC00EC4  /* DMA2 Channel 11 Start Address */
+#define DMA2_11_X_COUNT 0xFFC00ED0     /* DMA2 Channel 11 Inner Loop Count */
+#define DMA2_11_Y_COUNT 0xFFC00ED8     /* DMA2 Channel 11 Outer Loop Count */
+#define DMA2_11_X_MODIFY 0xFFC00ED4    /* DMA2 Channel 11 Inner Loop Addr Increment */
+#define DMA2_11_Y_MODIFY 0xFFC00EDC    /* DMA2 Channel 11 Outer Loop Addr Increment */
+#define DMA2_11_CURR_DESC_PTR 0xFFC00EE0       /* DMA2 Channel 11 Current Descriptor Pointer */
+#define DMA2_11_CURR_ADDR 0xFFC00EE4   /* DMA2 Channel 11 Current Address Pointer */
+#define DMA2_11_CURR_X_COUNT 0xFFC00EF0        /* DMA2 Channel 11 Current Inner Loop Count */
+#define DMA2_11_CURR_Y_COUNT 0xFFC00EF8        /* DMA2 Channel 11 Current Outer Loop Count */
+#define DMA2_11_IRQ_STATUS 0xFFC00EE8  /* DMA2 Channel 11 Interrupt/Status Register */
+#define DMA2_11_PERIPHERAL_MAP 0xFFC00EEC      /* DMA2 Channel 11 Peripheral Map Register */
+
+/* Memory DMA2 Controller registers (0xFFC0 0E80-0xFFC0 0FFF) */
+#define MDMA2_D0_CONFIG 0xFFC00F08     /*MemDMA2 Stream 0 Destination Configuration register */
+#define MDMA2_D0_NEXT_DESC_PTR 0xFFC00F00      /*MemDMA2 Stream 0 Destination Next Descriptor Ptr Reg */
+#define MDMA2_D0_START_ADDR 0xFFC00F04 /*MemDMA2 Stream 0 Destination Start Address */
+#define MDMA2_D0_X_COUNT 0xFFC00F10    /*MemDMA2 Stream 0 Dest Inner-Loop Count register */
+#define MDMA2_D0_Y_COUNT 0xFFC00F18    /*MemDMA2 Stream 0 Dest Outer-Loop Count register */
+#define MDMA2_D0_X_MODIFY 0xFFC00F14   /*MemDMA2 Stream 0 Dest Inner-Loop Address-Increment */
+#define MDMA2_D0_Y_MODIFY 0xFFC00F1C   /*MemDMA2 Stream 0 Dest Outer-Loop Address-Increment */
+#define MDMA2_D0_CURR_DESC_PTR 0xFFC00F20      /*MemDMA2 Stream 0 Dest Current Descriptor Ptr reg */
+#define MDMA2_D0_CURR_ADDR 0xFFC00F24  /*MemDMA2 Stream 0 Destination Current Address */
+#define MDMA2_D0_CURR_X_COUNT 0xFFC00F30       /*MemDMA2 Stream 0 Dest Current Inner-Loop Count reg */
+#define MDMA2_D0_CURR_Y_COUNT 0xFFC00F38       /*MemDMA2 Stream 0 Dest Current Outer-Loop Count reg */
+#define MDMA2_D0_IRQ_STATUS 0xFFC00F28 /*MemDMA2 Stream 0 Dest Interrupt/Status Register */
+#define MDMA2_D0_PERIPHERAL_MAP 0xFFC00F2C     /*MemDMA2 Stream 0 Destination Peripheral Map register */
+
+#define MDMA2_S0_CONFIG 0xFFC00F48     /*MemDMA2 Stream 0 Source Configuration register */
+#define MDMA2_S0_NEXT_DESC_PTR 0xFFC00F40      /*MemDMA2 Stream 0 Source Next Descriptor Ptr Reg */
+#define MDMA2_S0_START_ADDR 0xFFC00F44 /*MemDMA2 Stream 0 Source Start Address */
+#define MDMA2_S0_X_COUNT 0xFFC00F50    /*MemDMA2 Stream 0 Source Inner-Loop Count register */
+#define MDMA2_S0_Y_COUNT 0xFFC00F58    /*MemDMA2 Stream 0 Source Outer-Loop Count register */
+#define MDMA2_S0_X_MODIFY 0xFFC00F54   /*MemDMA2 Stream 0 Src Inner-Loop Addr-Increment reg */
+#define MDMA2_S0_Y_MODIFY 0xFFC00F5C   /*MemDMA2 Stream 0 Src Outer-Loop Addr-Increment reg */
+#define MDMA2_S0_CURR_DESC_PTR 0xFFC00F60      /*MemDMA2 Stream 0 Source Current Descriptor Ptr reg */
+#define MDMA2_S0_CURR_ADDR 0xFFC00F64  /*MemDMA2 Stream 0 Source Current Address */
+#define MDMA2_S0_CURR_X_COUNT 0xFFC00F70       /*MemDMA2 Stream 0 Src Current Inner-Loop Count reg */
+#define MDMA2_S0_CURR_Y_COUNT 0xFFC00F78       /*MemDMA2 Stream 0 Src Current Outer-Loop Count reg */
+#define MDMA2_S0_IRQ_STATUS 0xFFC00F68 /*MemDMA2 Stream 0 Source Interrupt/Status Register */
+#define MDMA2_S0_PERIPHERAL_MAP 0xFFC00F6C     /*MemDMA2 Stream 0 Source Peripheral Map register */
+
+#define MDMA2_D1_CONFIG 0xFFC00F88     /*MemDMA2 Stream 1 Destination Configuration register */
+#define MDMA2_D1_NEXT_DESC_PTR 0xFFC00F80      /*MemDMA2 Stream 1 Destination Next Descriptor Ptr Reg */
+#define MDMA2_D1_START_ADDR 0xFFC00F84 /*MemDMA2 Stream 1 Destination Start Address */
+#define MDMA2_D1_X_COUNT 0xFFC00F90    /*MemDMA2 Stream 1 Dest Inner-Loop Count register */
+#define MDMA2_D1_Y_COUNT 0xFFC00F98    /*MemDMA2 Stream 1 Dest Outer-Loop Count register */
+#define MDMA2_D1_X_MODIFY 0xFFC00F94   /*MemDMA2 Stream 1 Dest Inner-Loop Address-Increment */
+#define MDMA2_D1_Y_MODIFY 0xFFC00F9C   /*MemDMA2 Stream 1 Dest Outer-Loop Address-Increment */
+#define MDMA2_D1_CURR_DESC_PTR 0xFFC00FA0      /*MemDMA2 Stream 1 Destination Current Descriptor Ptr */
+#define MDMA2_D1_CURR_ADDR 0xFFC00FA4  /*MemDMA2 Stream 1 Destination Current Address reg */
+#define MDMA2_D1_CURR_X_COUNT 0xFFC00FB0       /*MemDMA2 Stream 1 Dest Current Inner-Loop Count reg */
+#define MDMA2_D1_CURR_Y_COUNT 0xFFC00FB8       /*MemDMA2 Stream 1 Dest Current Outer-Loop Count reg */
+#define MDMA2_D1_IRQ_STATUS 0xFFC00FA8 /*MemDMA2 Stream 1 Destination Interrupt/Status Reg */
+#define MDMA2_D1_PERIPHERAL_MAP 0xFFC00FAC     /*MemDMA2 Stream 1 Destination Peripheral Map register */
+
+#define MDMA2_S1_CONFIG 0xFFC00FC8     /*MemDMA2 Stream 1 Source Configuration register */
+#define MDMA2_S1_NEXT_DESC_PTR 0xFFC00FC0      /*MemDMA2 Stream 1 Source Next Descriptor Ptr Reg */
+#define MDMA2_S1_START_ADDR 0xFFC00FC4 /*MemDMA2 Stream 1 Source Start Address */
+#define MDMA2_S1_X_COUNT 0xFFC00FD0    /*MemDMA2 Stream 1 Source Inner-Loop Count register */
+#define MDMA2_S1_Y_COUNT 0xFFC00FD8    /*MemDMA2 Stream 1 Source Outer-Loop Count register */
+#define MDMA2_S1_X_MODIFY 0xFFC00FD4   /*MemDMA2 Stream 1 Src Inner-Loop Address-Increment */
+#define MDMA2_S1_Y_MODIFY 0xFFC00FDC   /*MemDMA2 Stream 1 Source Outer-Loop Address-Increment */
+#define MDMA2_S1_CURR_DESC_PTR 0xFFC00FE0      /*MemDMA2 Stream 1 Source Current Descriptor Ptr reg */
+#define MDMA2_S1_CURR_ADDR 0xFFC00FE4  /*MemDMA2 Stream 1 Source Current Address */
+#define MDMA2_S1_CURR_X_COUNT 0xFFC00FF0       /*MemDMA2 Stream 1 Source Current Inner-Loop Count */
+#define MDMA2_S1_CURR_Y_COUNT 0xFFC00FF8       /*MemDMA2 Stream 1 Source Current Outer-Loop Count */
+#define MDMA2_S1_IRQ_STATUS 0xFFC00FE8 /*MemDMA2 Stream 1 Source Interrupt/Status Register */
+#define MDMA2_S1_PERIPHERAL_MAP 0xFFC00FEC     /*MemDMA2 Stream 1 Source Peripheral Map register */
+
+/* Internal Memory DMA Registers (0xFFC0_1800 - 0xFFC0_19FF) */
+#define IMDMA_D0_CONFIG 0xFFC01808     /*IMDMA Stream 0 Destination Configuration */
+#define IMDMA_D0_NEXT_DESC_PTR 0xFFC01800      /*IMDMA Stream 0 Destination Next Descriptor Ptr Reg */
+#define IMDMA_D0_START_ADDR 0xFFC01804 /*IMDMA Stream 0 Destination Start Address */
+#define IMDMA_D0_X_COUNT 0xFFC01810    /*IMDMA Stream 0 Destination Inner-Loop Count */
+#define IMDMA_D0_Y_COUNT 0xFFC01818    /*IMDMA Stream 0 Destination Outer-Loop Count */
+#define IMDMA_D0_X_MODIFY 0xFFC01814   /*IMDMA Stream 0 Dest Inner-Loop Address-Increment */
+#define IMDMA_D0_Y_MODIFY 0xFFC0181C   /*IMDMA Stream 0 Dest Outer-Loop Address-Increment */
+#define IMDMA_D0_CURR_DESC_PTR 0xFFC01820      /*IMDMA Stream 0 Destination Current Descriptor Ptr */
+#define IMDMA_D0_CURR_ADDR 0xFFC01824  /*IMDMA Stream 0 Destination Current Address */
+#define IMDMA_D0_CURR_X_COUNT 0xFFC01830       /*IMDMA Stream 0 Destination Current Inner-Loop Count */
+#define IMDMA_D0_CURR_Y_COUNT 0xFFC01838       /*IMDMA Stream 0 Destination Current Outer-Loop Count */
+#define IMDMA_D0_IRQ_STATUS 0xFFC01828 /*IMDMA Stream 0 Destination Interrupt/Status */
+
+#define IMDMA_S0_CONFIG 0xFFC01848     /*IMDMA Stream 0 Source Configuration */
+#define IMDMA_S0_NEXT_DESC_PTR 0xFFC01840      /*IMDMA Stream 0 Source Next Descriptor Ptr Reg */
+#define IMDMA_S0_START_ADDR 0xFFC01844 /*IMDMA Stream 0 Source Start Address */
+#define IMDMA_S0_X_COUNT 0xFFC01850    /*IMDMA Stream 0 Source Inner-Loop Count */
+#define IMDMA_S0_Y_COUNT 0xFFC01858    /*IMDMA Stream 0 Source Outer-Loop Count */
+#define IMDMA_S0_X_MODIFY 0xFFC01854   /*IMDMA Stream 0 Source Inner-Loop Address-Increment */
+#define IMDMA_S0_Y_MODIFY 0xFFC0185C   /*IMDMA Stream 0 Source Outer-Loop Address-Increment */
+#define IMDMA_S0_CURR_DESC_PTR 0xFFC01860      /*IMDMA Stream 0 Source Current Descriptor Ptr reg */
+#define IMDMA_S0_CURR_ADDR 0xFFC01864  /*IMDMA Stream 0 Source Current Address */
+#define IMDMA_S0_CURR_X_COUNT 0xFFC01870       /*IMDMA Stream 0 Source Current Inner-Loop Count */
+#define IMDMA_S0_CURR_Y_COUNT 0xFFC01878       /*IMDMA Stream 0 Source Current Outer-Loop Count */
+#define IMDMA_S0_IRQ_STATUS 0xFFC01868 /*IMDMA Stream 0 Source Interrupt/Status */
+
+#define IMDMA_D1_CONFIG 0xFFC01888     /*IMDMA Stream 1 Destination Configuration */
+#define IMDMA_D1_NEXT_DESC_PTR 0xFFC01880      /*IMDMA Stream 1 Destination Next Descriptor Ptr Reg */
+#define IMDMA_D1_START_ADDR 0xFFC01884 /*IMDMA Stream 1 Destination Start Address */
+#define IMDMA_D1_X_COUNT 0xFFC01890    /*IMDMA Stream 1 Destination Inner-Loop Count */
+#define IMDMA_D1_Y_COUNT 0xFFC01898    /*IMDMA Stream 1 Destination Outer-Loop Count */
+#define IMDMA_D1_X_MODIFY 0xFFC01894   /*IMDMA Stream 1 Dest Inner-Loop Address-Increment */
+#define IMDMA_D1_Y_MODIFY 0xFFC0189C   /*IMDMA Stream 1 Dest Outer-Loop Address-Increment */
+#define IMDMA_D1_CURR_DESC_PTR 0xFFC018A0      /*IMDMA Stream 1 Destination Current Descriptor Ptr */
+#define IMDMA_D1_CURR_ADDR 0xFFC018A4  /*IMDMA Stream 1 Destination Current Address */
+#define IMDMA_D1_CURR_X_COUNT 0xFFC018B0       /*IMDMA Stream 1 Destination Current Inner-Loop Count */
+#define IMDMA_D1_CURR_Y_COUNT 0xFFC018B8       /*IMDMA Stream 1 Destination Current Outer-Loop Count */
+#define IMDMA_D1_IRQ_STATUS 0xFFC018A8 /*IMDMA Stream 1 Destination Interrupt/Status */
+
+#define IMDMA_S1_CONFIG 0xFFC018C8     /*IMDMA Stream 1 Source Configuration */
+#define IMDMA_S1_NEXT_DESC_PTR 0xFFC018C0      /*IMDMA Stream 1 Source Next Descriptor Ptr Reg */
+#define IMDMA_S1_START_ADDR 0xFFC018C4 /*IMDMA Stream 1 Source Start Address */
+#define IMDMA_S1_X_COUNT 0xFFC018D0    /*IMDMA Stream 1 Source Inner-Loop Count */
+#define IMDMA_S1_Y_COUNT 0xFFC018D8    /*IMDMA Stream 1 Source Outer-Loop Count */
+#define IMDMA_S1_X_MODIFY 0xFFC018D4   /*IMDMA Stream 1 Source Inner-Loop Address-Increment */
+#define IMDMA_S1_Y_MODIFY 0xFFC018DC   /*IMDMA Stream 1 Source Outer-Loop Address-Increment */
+#define IMDMA_S1_CURR_DESC_PTR 0xFFC018E0      /*IMDMA Stream 1 Source Current Descriptor Ptr reg */
+#define IMDMA_S1_CURR_ADDR 0xFFC018E4  /*IMDMA Stream 1 Source Current Address */
+#define IMDMA_S1_CURR_X_COUNT 0xFFC018F0       /*IMDMA Stream 1 Source Current Inner-Loop Count */
+#define IMDMA_S1_CURR_Y_COUNT 0xFFC018F8       /*IMDMA Stream 1 Source Current Outer-Loop Count */
+#define IMDMA_S1_IRQ_STATUS 0xFFC018E8 /*IMDMA Stream 1 Source Interrupt/Status */
+
+/*********************************************************************************** */
+/* System MMR Register Bits */
+/******************************************************************************* */
+
+/* ********************* PLL AND RESET MASKS ************************ */
+
+/* PLL_CTL Masks */
+#define PLL_CLKIN              0x00000000      /* Pass CLKIN to PLL */
+#define PLL_CLKIN_DIV2         0x00000001      /* Pass CLKIN/2 to PLL */
+#define PLL_OFF                0x00000002      /* Shut off PLL clocks */
+#define STOPCK_OFF             0x00000008      /* Core clock off */
+#define PDWN                   0x00000020      /* Put the PLL in a Deep Sleep state */
+#define BYPASS                 0x00000100      /* Bypass the PLL */
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* PLL_DIV Masks */
+#define SCLK_DIV(x)  (x)       /* SCLK = VCO / x */
+
+#define CCLK_DIV1              0x00000000      /* CCLK = VCO / 1 */
+#define CCLK_DIV2              0x00000010      /* CCLK = VCO / 2 */
+#define CCLK_DIV4              0x00000020      /* CCLK = VCO / 4 */
+#define CCLK_DIV8              0x00000030      /* CCLK = VCO / 8 */
+
+/* PLL_STAT Masks                                                                                                                                      */
+#define ACTIVE_PLLENABLED      0x0001  /* Processor In Active Mode With PLL Enabled    */
+#define        FULL_ON                         0x0002  /* Processor In Full On Mode                                    */
+#define ACTIVE_PLLDISABLED     0x0004  /* Processor In Active Mode With PLL Disabled   */
+#define        PLL_LOCKED                      0x0020  /* PLL_LOCKCNT Has Been Reached                                 */
+
+/* SWRST Mask */
+#define SYSTEM_RESET           0x00000007      /* Initiates a system software reset */
+#define SWRST_DBL_FAULT_B      0x00000800      /* SWRST Core B Double Fault */
+#define SWRST_DBL_FAULT_A      0x00001000      /* SWRST Core A Double Fault */
+#define SWRST_WDT_B                   0x00002000       /* SWRST Watchdog B */
+#define SWRST_WDT_A                   0x00004000       /* SWRST Watchdog A */
+#define SWRST_OCCURRED         0x00008000      /* SWRST Status */
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS ***************** */
+
+/* SICu_IARv Masks      */
+/* u = A or B */
+/* v = 0 to 7 */
+/* w = 0 or 1 */
+
+/* Per_number = 0 to 63 */
+/* IVG_number = 7 to 15   */
+#define Peripheral_IVG(Per_number, IVG_number)    \
+    ((IVG_number) - 7) << (((Per_number) % 8) * 4)     /* Peripheral #Per_number assigned IVG #IVG_number  */
+    /* Usage: r0.l = lo(Peripheral_IVG(62, 10)); */
+    /*        r0.h = hi(Peripheral_IVG(62, 10)); */
+
+/* SICx_IMASKw Masks */
+/* masks are 32 bit wide, so two writes reguired for "64 bit" wide registers  */
+#define SIC_UNMASK_ALL         0x00000000      /* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL           0xFFFFFFFF      /* Mask all peripheral interrupts */
+#define SIC_MASK(x)           (1 << (x))       /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << (x)))        /* Unmask Peripheral #x interrupt */
+
+/* SIC_IWR Masks */
+#define IWR_DISABLE_ALL        0x00000000      /* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL         0xFFFFFFFF      /* Wakeup Enable all peripherals */
+/* x = pos 0 to 31, for 32-63 use value-32 */
+#define IWR_ENABLE(x)         (1 << (x))       /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))       /* Wakeup Disable Peripheral #x */
+
+/* *********  WATCHDOG TIMER MASKS  ********************8 */
+
+/* Watchdog Timer WDOG_CTL Register */
+#define ICTL(x) ((x<<1) & 0x0006)
+#define ENABLE_RESET     0x00000000    /* Set Watchdog Timer to generate reset */
+#define ENABLE_NMI       0x00000002    /* Set Watchdog Timer to generate non-maskable interrupt */
+#define ENABLE_GPI       0x00000004    /* Set Watchdog Timer to generate general-purpose interrupt */
+#define DISABLE_EVT      0x00000006    /* Disable Watchdog Timer interrupts */
+
+#define TMR_EN         0x0000
+#define TMR_DIS                0x0AD0
+#define TRO            0x8000
+
+#define ICTL_P0                0x01
+#define ICTL_P1                0x02
+#define TRO_P          0x0F
+
+/* ***************************** UART CONTROLLER MASKS ********************** */
+
+/* UART_LCR Register */
+
+#define DLAB   0x80
+#define SB      0x40
+#define STP      0x20
+#define EPS     0x10
+#define PEN    0x08
+#define STB    0x04
+#define WLS(x) ((x-5) & 0x03)
+
+#define DLAB_P 0x07
+#define SB_P   0x06
+#define STP_P  0x05
+#define EPS_P  0x04
+#define PEN_P  0x03
+#define STB_P  0x02
+#define WLS_P1 0x01
+#define WLS_P0 0x00
+
+/* UART_MCR Register */
+#define LOOP_ENA       0x10
+#define LOOP_ENA_P     0x04
+
+/* UART_LSR Register */
+#define TEMT   0x40
+#define THRE   0x20
+#define BI     0x10
+#define FE     0x08
+#define PE     0x04
+#define OE     0x02
+#define DR     0x01
+
+#define TEMP_P 0x06
+#define THRE_P 0x05
+#define BI_P   0x04
+#define FE_P   0x03
+#define PE_P   0x02
+#define OE_P   0x01
+#define DR_P   0x00
+
+/* UART_IER Register */
+#define ELSI   0x04
+#define ETBEI  0x02
+#define ERBFI  0x01
+
+#define ELSI_P 0x02
+#define ETBEI_P        0x01
+#define ERBFI_P        0x00
+
+/* UART_IIR Register */
+#define STATUS(x)      ((x << 1) & 0x06)
+#define NINT           0x01
+#define STATUS_P1      0x02
+#define STATUS_P0      0x01
+#define NINT_P         0x00
+#define IIR_TX_READY    0x02   /* UART_THR empty                               */
+#define IIR_RX_READY    0x04   /* Receive data ready                           */
+#define IIR_LINE_CHANGE 0x06   /* Receive line status                          */
+#define IIR_STATUS     0x06
+
+/* UART_GCTL Register */
+#define FFE    0x20
+#define FPE    0x10
+#define RPOLC  0x08
+#define TPOLC  0x04
+#define IREN   0x02
+#define UCEN   0x01
+
+#define FFE_P  0x05
+#define FPE_P  0x04
+#define RPOLC_P        0x03
+#define TPOLC_P        0x02
+#define IREN_P 0x01
+#define UCEN_P 0x00
+
+/* **********  SERIAL PORT MASKS  ********************** */
+
+/* SPORTx_TCR1 Masks */
+#define TSPEN    0x0001                /* TX enable  */
+#define ITCLK    0x0002                /* Internal TX Clock Select  */
+#define TDTYPE   0x000C                /* TX Data Formatting Select */
+#define TLSBIT   0x0010                /* TX Bit Order */
+#define ITFS     0x0200                /* Internal TX Frame Sync Select  */
+#define TFSR     0x0400                /* TX Frame Sync Required Select  */
+#define DITFS    0x0800                /* Data Independent TX Frame Sync Select  */
+#define LTFS     0x1000                /* Low TX Frame Sync Select  */
+#define LATFS    0x2000                /* Late TX Frame Sync Select  */
+#define TCKFE    0x4000                /* TX Clock Falling Edge Select  */
+
+/* SPORTx_TCR2 Masks */
+#define SLEN       0x001F      /*TX Word Length  */
+#define TXSE        0x0100     /*TX Secondary Enable */
+#define TSFSE       0x0200     /*TX Stereo Frame Sync Enable */
+#define TRFST       0x0400     /*TX Right-First Data Order  */
+
+/* SPORTx_RCR1 Masks */
+#define RSPEN    0x0001                /* RX enable  */
+#define IRCLK    0x0002                /* Internal RX Clock Select  */
+#define RDTYPE   0x000C                /* RX Data Formatting Select */
+#define RULAW    0x0008                /* u-Law enable  */
+#define RALAW    0x000C                /* A-Law enable  */
+#define RLSBIT   0x0010                /* RX Bit Order */
+#define IRFS     0x0200                /* Internal RX Frame Sync Select  */
+#define RFSR     0x0400                /* RX Frame Sync Required Select  */
+#define LRFS     0x1000                /* Low RX Frame Sync Select  */
+#define LARFS    0x2000                /* Late RX Frame Sync Select  */
+#define RCKFE    0x4000                /* RX Clock Falling Edge Select  */
+
+/* SPORTx_RCR2 Masks */
+#define SLEN       0x001F      /*RX Word Length  */
+#define RXSE        0x0100     /*RX Secondary Enable */
+#define RSFSE       0x0200     /*RX Stereo Frame Sync Enable */
+#define RRFST       0x0400     /*Right-First Data Order  */
+
+/*SPORTx_STAT Masks */
+#define RXNE           0x0001  /*RX FIFO Not Empty Status */
+#define RUVF           0x0002  /*RX Underflow Status */
+#define ROVF           0x0004  /*RX Overflow Status */
+#define TXF            0x0008  /*TX FIFO Full Status */
+#define TUVF           0x0010  /*TX Underflow Status */
+#define TOVF           0x0020  /*TX Overflow Status */
+#define TXHRE          0x0040  /*TX Hold Register Empty */
+
+/*SPORTx_MCMC1 Masks */
+#define SP_WSIZE               0x0000F000      /*Multichannel Window Size Field */
+#define SP_WOFF                0x000003FF      /*Multichannel Window Offset Field */
+
+/*SPORTx_MCMC2 Masks */
+#define MCCRM          0x00000003      /*Multichannel Clock Recovery Mode */
+#define MCDTXPE                0x00000004      /*Multichannel DMA Transmit Packing */
+#define MCDRXPE                0x00000008      /*Multichannel DMA Receive Packing */
+#define MCMEN          0x00000010      /*Multichannel Frame Mode Enable */
+#define FSDR           0x00000080      /*Multichannel Frame Sync to Data Relationship */
+#define MFD            0x0000F000      /*Multichannel Frame Delay    */
+
+/*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
+
+/*  PPI_CONTROL Masks         */
+#define PORT_EN              0x00000001        /* PPI Port Enable  */
+#define PORT_DIR             0x00000002        /* PPI Port Direction       */
+#define XFR_TYPE             0x0000000C        /* PPI Transfer Type  */
+#define PORT_CFG             0x00000030        /* PPI Port Configuration */
+#define FLD_SEL              0x00000040        /* PPI Active Field Select */
+#define PACK_EN              0x00000080        /* PPI Packing Mode */
+#define DMA32                0x00000100        /* PPI 32-bit DMA Enable */
+#define SKIP_EN              0x00000200        /* PPI Skip Element Enable */
+#define SKIP_EO              0x00000400        /* PPI Skip Even/Odd Elements */
+#define DLENGTH              0x00003800        /* PPI Data Length  */
+#define DLEN_8              0x0        /* PPI Data Length mask for DLEN=8 */
+#define DLEN(x)        (((x-9) & 0x07) << 11)  /* PPI Data Length (only works for x=10-->x=16) */
+#define POL                  0x0000C000        /* PPI Signal Polarities       */
+
+/* PPI_STATUS Masks */
+#define FLD                 0x00000400 /* Field Indicator   */
+#define FT_ERR              0x00000800 /* Frame Track Error */
+#define OVR                 0x00001000 /* FIFO Overflow Error */
+#define UNDR                0x00002000 /* FIFO Underrun Error */
+#define ERR_DET                     0x00004000 /* Error Detected Indicator */
+#define ERR_NCOR            0x00008000 /* Error Not Corrected Indicator */
+
+/* **********  DMA CONTROLLER MASKS  *********************8 */
+
+/* DMAx_CONFIG, MDMA_yy_CONFIG, IMDMA_yy_CONFIG Masks */
+#define DMAEN          0x00000001      /* Channel Enable */
+#define WNR            0x00000002      /* Channel Direction (W/R*) */
+#define WDSIZE_8       0x00000000      /* Word Size 8 bits */
+#define WDSIZE_16      0x00000004      /* Word Size 16 bits */
+#define WDSIZE_32      0x00000008      /* Word Size 32 bits */
+#define DMA2D          0x00000010      /* 2D/1D* Mode */
+#define RESTART         0x00000020     /* Restart */
+#define DI_SEL         0x00000040      /* Data Interrupt Select */
+#define DI_EN          0x00000080      /* Data Interrupt Enable */
+#define NDSIZE_0               0x0000  /* Next Descriptor Size = 0 (Stop/Autobuffer)   */
+#define NDSIZE_1               0x0100  /* Next Descriptor Size = 1                                             */
+#define NDSIZE_2               0x0200  /* Next Descriptor Size = 2                                             */
+#define NDSIZE_3               0x0300  /* Next Descriptor Size = 3                                             */
+#define NDSIZE_4               0x0400  /* Next Descriptor Size = 4                                             */
+#define NDSIZE_5               0x0500  /* Next Descriptor Size = 5                                             */
+#define NDSIZE_6               0x0600  /* Next Descriptor Size = 6                                             */
+#define NDSIZE_7               0x0700  /* Next Descriptor Size = 7                                             */
+#define NDSIZE_8               0x0800  /* Next Descriptor Size = 8                                             */
+#define NDSIZE_9               0x0900  /* Next Descriptor Size = 9                                             */
+#define NDSIZE         0x00000900      /* Next Descriptor Size */
+#define DMAFLOW                0x00007000      /* Flow Control */
+#define DMAFLOW_STOP           0x0000  /* Stop Mode */
+#define DMAFLOW_AUTO           0x1000  /* Autobuffer Mode */
+#define DMAFLOW_ARRAY          0x4000  /* Descriptor Array Mode */
+#define DMAFLOW_SMALL          0x6000  /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE          0x7000  /* Large Model Descriptor List Mode */
+
+#define DMAEN_P                        0       /* Channel Enable */
+#define WNR_P                  1       /* Channel Direction (W/R*) */
+#define DMA2D_P                        4       /* 2D/1D* Mode */
+#define RESTART_P              5       /* Restart */
+#define DI_SEL_P               6       /* Data Interrupt Select */
+#define DI_EN_P                        7       /* Data Interrupt Enable */
+
+/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS, IMDMA_yy_IRQ_STATUS Masks */
+
+#define DMA_DONE               0x00000001      /* DMA Done Indicator */
+#define DMA_ERR                        0x00000002      /* DMA Error Indicator */
+#define DFETCH                 0x00000004      /* Descriptor Fetch Indicator */
+#define DMA_RUN                        0x00000008      /* DMA Running Indicator */
+
+#define DMA_DONE_P             0       /* DMA Done Indicator */
+#define DMA_ERR_P              1       /* DMA Error Indicator */
+#define DFETCH_P               2       /* Descriptor Fetch Indicator */
+#define DMA_RUN_P              3       /* DMA Running Indicator */
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP, IMDMA_yy_PERIPHERAL_MAP Masks */
+
+#define CTYPE              0x00000040  /* DMA Channel Type Indicator */
+#define CTYPE_P             6  /* DMA Channel Type Indicator BIT POSITION */
+#define PCAP8              0x00000080  /* DMA 8-bit Operation Indicator   */
+#define PCAP16             0x00000100  /* DMA 16-bit Operation Indicator */
+#define PCAP32             0x00000200  /* DMA 32-bit Operation Indicator */
+#define PCAPWR             0x00000400  /* DMA Write Operation Indicator */
+#define PCAPRD             0x00000800  /* DMA Read Operation Indicator */
+#define PMAP               0x00007000  /* DMA Peripheral Map Field */
+
+/*  *************  GENERAL PURPOSE TIMER MASKS  ******************** */
+
+/* PWM Timer bit definitions */
+
+/* TIMER_ENABLE Register */
+#define TIMEN0 0x0001
+#define TIMEN1 0x0002
+#define TIMEN2 0x0004
+#define TIMEN3 0x0008
+#define TIMEN4 0x0010
+#define TIMEN5 0x0020
+#define TIMEN6 0x0040
+#define TIMEN7 0x0080
+#define TIMEN8 0x0001
+#define TIMEN9 0x0002
+#define TIMEN10        0x0004
+#define TIMEN11        0x0008
+
+#define TIMEN0_P       0x00
+#define TIMEN1_P       0x01
+#define TIMEN2_P       0x02
+#define TIMEN3_P       0x03
+#define TIMEN4_P       0x04
+#define TIMEN5_P       0x05
+#define TIMEN6_P       0x06
+#define TIMEN7_P       0x07
+#define TIMEN8_P       0x00
+#define TIMEN9_P       0x01
+#define TIMEN10_P      0x02
+#define TIMEN11_P      0x03
+
+/* TIMER_DISABLE Register */
+#define TIMDIS0                0x0001
+#define TIMDIS1                0x0002
+#define TIMDIS2                0x0004
+#define TIMDIS3                0x0008
+#define TIMDIS4                0x0010
+#define TIMDIS5                0x0020
+#define TIMDIS6                0x0040
+#define TIMDIS7                0x0080
+#define TIMDIS8                0x0001
+#define TIMDIS9                0x0002
+#define TIMDIS10       0x0004
+#define TIMDIS11       0x0008
+
+#define TIMDIS0_P      0x00
+#define TIMDIS1_P      0x01
+#define TIMDIS2_P      0x02
+#define TIMDIS3_P      0x03
+#define TIMDIS4_P      0x04
+#define TIMDIS5_P      0x05
+#define TIMDIS6_P      0x06
+#define TIMDIS7_P      0x07
+#define TIMDIS8_P      0x00
+#define TIMDIS9_P      0x01
+#define TIMDIS10_P     0x02
+#define TIMDIS11_P     0x03
+
+/* TIMER_STATUS Register */
+#define TIMIL0         0x00000001
+#define TIMIL1         0x00000002
+#define TIMIL2         0x00000004
+#define TIMIL3         0x00000008
+#define TIMIL4         0x00010000
+#define TIMIL5         0x00020000
+#define TIMIL6         0x00040000
+#define TIMIL7         0x00080000
+#define TIMIL8         0x0001
+#define TIMIL9         0x0002
+#define TIMIL10                0x0004
+#define TIMIL11                0x0008
+#define TOVL_ERR0      0x00000010
+#define TOVL_ERR1      0x00000020
+#define TOVL_ERR2      0x00000040
+#define TOVL_ERR3      0x00000080
+#define TOVL_ERR4      0x00100000
+#define TOVL_ERR5      0x00200000
+#define TOVL_ERR6      0x00400000
+#define TOVL_ERR7      0x00800000
+#define TOVL_ERR8      0x0010
+#define TOVL_ERR9      0x0020
+#define TOVL_ERR10     0x0040
+#define TOVL_ERR11     0x0080
+#define TRUN0          0x00001000
+#define TRUN1          0x00002000
+#define TRUN2          0x00004000
+#define TRUN3          0x00008000
+#define TRUN4          0x10000000
+#define TRUN5          0x20000000
+#define TRUN6          0x40000000
+#define TRUN7          0x80000000
+#define TRUN8          0x1000
+#define TRUN9          0x2000
+#define TRUN10         0x4000
+#define TRUN11         0x8000
+
+#define TIMIL0_P       0x00
+#define TIMIL1_P       0x01
+#define TIMIL2_P       0x02
+#define TIMIL3_P       0x03
+#define TIMIL4_P       0x10
+#define TIMIL5_P       0x11
+#define TIMIL6_P       0x12
+#define TIMIL7_P       0x13
+#define TIMIL8_P       0x00
+#define TIMIL9_P       0x01
+#define TIMIL10_P      0x02
+#define TIMIL11_P      0x03
+#define TOVL_ERR0_P    0x04
+#define TOVL_ERR1_P    0x05
+#define TOVL_ERR2_P    0x06
+#define TOVL_ERR3_P    0x07
+#define TOVL_ERR4_P    0x14
+#define TOVL_ERR5_P    0x15
+#define TOVL_ERR6_P    0x16
+#define TOVL_ERR7_P    0x17
+#define TOVL_ERR8_P    0x04
+#define TOVL_ERR9_P    0x05
+#define TOVL_ERR10_P   0x06
+#define TOVL_ERR11_P   0x07
+#define TRUN0_P                0x0C
+#define TRUN1_P                0x0D
+#define TRUN2_P                0x0E
+#define TRUN3_P                0x0F
+#define TRUN4_P                0x1C
+#define TRUN5_P                0x1D
+#define TRUN6_P                0x1E
+#define TRUN7_P                0x1F
+#define TRUN8_P                0x0C
+#define TRUN9_P                0x0D
+#define TRUN10_P       0x0E
+#define TRUN11_P       0x0F
+
+/* TIMERx_CONFIG Registers */
+#define PWM_OUT                0x0001
+#define WDTH_CAP       0x0002
+#define EXT_CLK                0x0003
+#define PULSE_HI       0x0004
+#define PERIOD_CNT     0x0008
+#define IRQ_ENA                0x0010
+#define TIN_SEL                0x0020
+#define OUT_DIS                0x0040
+#define CLK_SEL                0x0080
+#define TOGGLE_HI      0x0100
+#define EMU_RUN                0x0200
+#define ERR_TYP(x)     ((x & 0x03) << 14)
+
+#define TMODE_P0               0x00
+#define TMODE_P1               0x01
+#define PULSE_HI_P             0x02
+#define PERIOD_CNT_P           0x03
+#define IRQ_ENA_P              0x04
+#define TIN_SEL_P              0x05
+#define OUT_DIS_P              0x06
+#define CLK_SEL_P              0x07
+#define TOGGLE_HI_P            0x08
+#define EMU_RUN_P              0x09
+#define ERR_TYP_P0             0x0E
+#define ERR_TYP_P1             0x0F
+
+/*/ ******************   PROGRAMMABLE FLAG MASKS  ********************* */
+
+/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks */
+#define PF0         0x0001
+#define PF1         0x0002
+#define PF2         0x0004
+#define PF3         0x0008
+#define PF4         0x0010
+#define PF5         0x0020
+#define PF6         0x0040
+#define PF7         0x0080
+#define PF8         0x0100
+#define PF9         0x0200
+#define PF10        0x0400
+#define PF11        0x0800
+#define PF12        0x1000
+#define PF13        0x2000
+#define PF14        0x4000
+#define PF15        0x8000
+
+/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  BIT POSITIONS */
+#define PF0_P         0
+#define PF1_P         1
+#define PF2_P         2
+#define PF3_P         3
+#define PF4_P         4
+#define PF5_P         5
+#define PF6_P         6
+#define PF7_P         7
+#define PF8_P         8
+#define PF9_P         9
+#define PF10_P        10
+#define PF11_P        11
+#define PF12_P        12
+#define PF13_P        13
+#define PF14_P        14
+#define PF15_P        15
+
+/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  **************** */
+
+/* SPI_CTL Masks */
+#define TIMOD                  0x00000003      /* Transfer initiation mode and interrupt generation */
+#define SZ                     0x00000004      /* Send Zero (=0) or last (=1) word when TDBR empty. */
+#define GM                     0x00000008      /* When RDBR full, get more (=1) data or discard (=0) incoming Data */
+#define PSSE                   0x00000010      /* Enable (=1) Slave-Select input for Master. */
+#define EMISO                  0x00000020      /* Enable (=1) MISO pin as an output. */
+#define SIZE                   0x00000100      /* Word length (0 => 8 bits, 1 => 16 bits) */
+#define LSBF                   0x00000200      /* Data format (0 => MSB sent/received first 1 => LSB sent/received first) */
+#define CPHA                   0x00000400      /* Clock phase (0 => SPICLK starts toggling in middle of xfer, 1 => SPICLK toggles at the beginning of xfer. */
+#define CPOL                   0x00000800      /* Clock polarity (0 => active-high, 1 => active-low) */
+#define MSTR                   0x00001000      /* Configures SPI as master (=1) or slave (=0) */
+#define WOM                    0x00002000      /* Open drain (=1) data output enable (for MOSI and MISO) */
+#define SPE                    0x00004000      /* SPI module enable (=1), disable (=0) */
+
+/* SPI_FLG Masks */
+#define FLS1                   0x00000002      /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLS2                   0x00000004      /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLS3                   0x00000008      /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLS4                   0x00000010      /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLS5                   0x00000020      /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLS6                   0x00000040      /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLS7                   0x00000080      /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
+#define FLG1                   0x00000200      /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
+#define FLG2                   0x00000400      /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLG3                   0x00000800      /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
+#define FLG4                   0x00001000      /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
+#define FLG5                   0x00002000      /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
+#define FLG6                   0x00004000      /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
+#define FLG7                   0x00008000      /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+/* SPI_FLG Bit Positions */
+#define FLS1_P                 0x00000001      /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLS2_P                 0x00000002      /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLS3_P                 0x00000003      /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLS4_P                 0x00000004      /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLS5_P                 0x00000005      /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLS6_P                 0x00000006      /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLS7_P                 0x00000007      /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
+#define FLG1_P                 0x00000009      /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
+#define FLG2_P                 0x0000000A      /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLG3_P                 0x0000000B      /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
+#define FLG4_P                 0x0000000C      /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
+#define FLG5_P                 0x0000000D      /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
+#define FLG6_P                 0x0000000E      /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
+#define FLG7_P                 0x0000000F      /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+/* SPI_STAT Masks */
+#define SPIF                   0x00000001      /* Set (=1) when SPI single-word transfer complete */
+#define MODF                   0x00000002      /* Set (=1) in a master device when some other device tries to become master */
+#define TXE                    0x00000004      /* Set (=1) when transmission occurs with no new data in SPI_TDBR */
+#define TXS                    0x00000008      /* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
+#define RBSY                   0x00000010      /* Set (=1) when data is received with RDBR full */
+#define RXS                    0x00000020      /* SPI_RDBR Data Buffer Status (0=Empty, 1=Full)  */
+#define TXCOL                  0x00000040      /* When set (=1), corrupt data may have been transmitted  */
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
+
+/* AMGCTL Masks */
+#define AMCKEN                 0x0001  /* Enable CLKOUT */
+#define AMBEN_B0               0x0002  /* Enable Asynchronous Memory Bank 0 only */
+#define AMBEN_B0_B1            0x0004  /* Enable Asynchronous Memory Banks 0 & 1 only */
+#define AMBEN_B0_B1_B2 0x0006  /* Enable Asynchronous Memory Banks 0, 1, and 2 */
+#define AMBEN_ALL              0x0008  /* Enable Asynchronous Memory Banks (all) 0, 1, 2, and 3 */
+#define B0_PEN                 0x0010  /* Enable 16-bit packing Bank 0  */
+#define B1_PEN                 0x0020  /* Enable 16-bit packing Bank 1  */
+#define B2_PEN                 0x0040  /* Enable 16-bit packing Bank 2  */
+#define B3_PEN                 0x0080  /* Enable 16-bit packing Bank 3  */
+
+/* AMGCTL Bit Positions */
+#define AMCKEN_P               0x00000000      /* Enable CLKOUT */
+#define AMBEN_P0               0x00000001      /* Asynchronous Memory Enable, 000 - banks 0-3 disabled, 001 - Bank 0 enabled */
+#define AMBEN_P1               0x00000002      /* Asynchronous Memory Enable, 010 - banks 0&1 enabled,  011 - banks 0-3 enabled */
+#define AMBEN_P2               0x00000003      /* Asynchronous Memory Enable, 1xx - All banks (bank 0, 1, 2, and 3) enabled */
+#define B0_PEN_P                       0x004   /* Enable 16-bit packing Bank 0  */
+#define B1_PEN_P                       0x005   /* Enable 16-bit packing Bank 1  */
+#define B2_PEN_P                       0x006   /* Enable 16-bit packing Bank 2  */
+#define B3_PEN_P                       0x007   /* Enable 16-bit packing Bank 3  */
+
+/* AMBCTL0 Masks */
+#define B0RDYEN        0x00000001      /* Bank 0 RDY Enable, 0=disable, 1=enable */
+#define B0RDYPOL 0x00000002    /* Bank 0 RDY Active high, 0=active low, 1=active high */
+#define B0TT_1 0x00000004      /* Bank 0 Transition Time from Read to Write = 1 cycle */
+#define B0TT_2 0x00000008      /* Bank 0 Transition Time from Read to Write = 2 cycles */
+#define B0TT_3 0x0000000C      /* Bank 0 Transition Time from Read to Write = 3 cycles */
+#define B0TT_4 0x00000000      /* Bank 0 Transition Time from Read to Write = 4 cycles */
+#define B0ST_1 0x00000010      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=1 cycle */
+#define B0ST_2 0x00000020      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=2 cycles */
+#define B0ST_3 0x00000030      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=3 cycles */
+#define B0ST_4 0x00000000      /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=4 cycles */
+#define B0HT_1 0x00000040      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 1 cycle */
+#define B0HT_2 0x00000080      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 2 cycles */
+#define B0HT_3 0x000000C0      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 3 cycles */
+#define B0HT_0 0x00000000      /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 0 cycles */
+#define B0RAT_1                        0x00000100      /* Bank 0 Read Access Time = 1 cycle */
+#define B0RAT_2                        0x00000200      /* Bank 0 Read Access Time = 2 cycles */
+#define B0RAT_3                        0x00000300      /* Bank 0 Read Access Time = 3 cycles */
+#define B0RAT_4                        0x00000400      /* Bank 0 Read Access Time = 4 cycles */
+#define B0RAT_5                        0x00000500      /* Bank 0 Read Access Time = 5 cycles */
+#define B0RAT_6                        0x00000600      /* Bank 0 Read Access Time = 6 cycles */
+#define B0RAT_7                        0x00000700      /* Bank 0 Read Access Time = 7 cycles */
+#define B0RAT_8                        0x00000800      /* Bank 0 Read Access Time = 8 cycles */
+#define B0RAT_9                        0x00000900      /* Bank 0 Read Access Time = 9 cycles */
+#define B0RAT_10               0x00000A00      /* Bank 0 Read Access Time = 10 cycles */
+#define B0RAT_11               0x00000B00      /* Bank 0 Read Access Time = 11 cycles */
+#define B0RAT_12               0x00000C00      /* Bank 0 Read Access Time = 12 cycles */
+#define B0RAT_13               0x00000D00      /* Bank 0 Read Access Time = 13 cycles */
+#define B0RAT_14               0x00000E00      /* Bank 0 Read Access Time = 14 cycles */
+#define B0RAT_15               0x00000F00      /* Bank 0 Read Access Time = 15 cycles */
+#define B0WAT_1                        0x00001000      /* Bank 0 Write Access Time = 1 cycle */
+#define B0WAT_2                        0x00002000      /* Bank 0 Write Access Time = 2 cycles */
+#define B0WAT_3                        0x00003000      /* Bank 0 Write Access Time = 3 cycles */
+#define B0WAT_4                        0x00004000      /* Bank 0 Write Access Time = 4 cycles */
+#define B0WAT_5                        0x00005000      /* Bank 0 Write Access Time = 5 cycles */
+#define B0WAT_6                        0x00006000      /* Bank 0 Write Access Time = 6 cycles */
+#define B0WAT_7                        0x00007000      /* Bank 0 Write Access Time = 7 cycles */
+#define B0WAT_8                        0x00008000      /* Bank 0 Write Access Time = 8 cycles */
+#define B0WAT_9                        0x00009000      /* Bank 0 Write Access Time = 9 cycles */
+#define B0WAT_10               0x0000A000      /* Bank 0 Write Access Time = 10 cycles */
+#define B0WAT_11               0x0000B000      /* Bank 0 Write Access Time = 11 cycles */
+#define B0WAT_12               0x0000C000      /* Bank 0 Write Access Time = 12 cycles */
+#define B0WAT_13               0x0000D000      /* Bank 0 Write Access Time = 13 cycles */
+#define B0WAT_14               0x0000E000      /* Bank 0 Write Access Time = 14 cycles */
+#define B0WAT_15               0x0000F000      /* Bank 0 Write Access Time = 15 cycles */
+#define B1RDYEN                        0x00010000      /* Bank 1 RDY enable, 0=disable, 1=enable */
+#define B1RDYPOL               0x00020000      /* Bank 1 RDY Active high, 0=active low, 1=active high */
+#define B1TT_1                 0x00040000      /* Bank 1 Transition Time from Read to Write = 1 cycle */
+#define B1TT_2                 0x00080000      /* Bank 1 Transition Time from Read to Write = 2 cycles */
+#define B1TT_3                 0x000C0000      /* Bank 1 Transition Time from Read to Write = 3 cycles */
+#define B1TT_4                 0x00000000      /* Bank 1 Transition Time from Read to Write = 4 cycles */
+#define B1ST_1                 0x00100000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B1ST_2                 0x00200000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B1ST_3                 0x00300000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B1ST_4                 0x00000000      /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B1HT_1                 0x00400000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B1HT_2                 0x00800000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B1HT_3                 0x00C00000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B1HT_0                 0x00000000      /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B1RAT_1                        0x01000000      /* Bank 1 Read Access Time = 1 cycle */
+#define B1RAT_2                        0x02000000      /* Bank 1 Read Access Time = 2 cycles */
+#define B1RAT_3                        0x03000000      /* Bank 1 Read Access Time = 3 cycles */
+#define B1RAT_4                        0x04000000      /* Bank 1 Read Access Time = 4 cycles */
+#define B1RAT_5                        0x05000000      /* Bank 1 Read Access Time = 5 cycles */
+#define B1RAT_6                        0x06000000      /* Bank 1 Read Access Time = 6 cycles */
+#define B1RAT_7                        0x07000000      /* Bank 1 Read Access Time = 7 cycles */
+#define B1RAT_8                        0x08000000      /* Bank 1 Read Access Time = 8 cycles */
+#define B1RAT_9                        0x09000000      /* Bank 1 Read Access Time = 9 cycles */
+#define B1RAT_10               0x0A000000      /* Bank 1 Read Access Time = 10 cycles */
+#define B1RAT_11               0x0B000000      /* Bank 1 Read Access Time = 11 cycles */
+#define B1RAT_12               0x0C000000      /* Bank 1 Read Access Time = 12 cycles */
+#define B1RAT_13               0x0D000000      /* Bank 1 Read Access Time = 13 cycles */
+#define B1RAT_14               0x0E000000      /* Bank 1 Read Access Time = 14 cycles */
+#define B1RAT_15               0x0F000000      /* Bank 1 Read Access Time = 15 cycles */
+#define B1WAT_1                        0x10000000      /* Bank 1 Write Access Time = 1 cycle */
+#define B1WAT_2                        0x20000000      /* Bank 1 Write Access Time = 2 cycles */
+#define B1WAT_3                        0x30000000      /* Bank 1 Write Access Time = 3 cycles */
+#define B1WAT_4                        0x40000000      /* Bank 1 Write Access Time = 4 cycles */
+#define B1WAT_5                        0x50000000      /* Bank 1 Write Access Time = 5 cycles */
+#define B1WAT_6                        0x60000000      /* Bank 1 Write Access Time = 6 cycles */
+#define B1WAT_7                        0x70000000      /* Bank 1 Write Access Time = 7 cycles */
+#define B1WAT_8                        0x80000000      /* Bank 1 Write Access Time = 8 cycles */
+#define B1WAT_9                        0x90000000      /* Bank 1 Write Access Time = 9 cycles */
+#define B1WAT_10               0xA0000000      /* Bank 1 Write Access Time = 10 cycles */
+#define B1WAT_11               0xB0000000      /* Bank 1 Write Access Time = 11 cycles */
+#define B1WAT_12               0xC0000000      /* Bank 1 Write Access Time = 12 cycles */
+#define B1WAT_13               0xD0000000      /* Bank 1 Write Access Time = 13 cycles */
+#define B1WAT_14               0xE0000000      /* Bank 1 Write Access Time = 14 cycles */
+#define B1WAT_15               0xF0000000      /* Bank 1 Write Access Time = 15 cycles */
+
+/* AMBCTL1 Masks */
+#define B2RDYEN                        0x00000001      /* Bank 2 RDY Enable, 0=disable, 1=enable */
+#define B2RDYPOL               0x00000002      /* Bank 2 RDY Active high, 0=active low, 1=active high */
+#define B2TT_1                 0x00000004      /* Bank 2 Transition Time from Read to Write = 1 cycle */
+#define B2TT_2                 0x00000008      /* Bank 2 Transition Time from Read to Write = 2 cycles */
+#define B2TT_3                 0x0000000C      /* Bank 2 Transition Time from Read to Write = 3 cycles */
+#define B2TT_4                 0x00000000      /* Bank 2 Transition Time from Read to Write = 4 cycles */
+#define B2ST_1                 0x00000010      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B2ST_2                 0x00000020      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B2ST_3                 0x00000030      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B2ST_4                 0x00000000      /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B2HT_1                 0x00000040      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B2HT_2                 0x00000080      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B2HT_3                 0x000000C0      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B2HT_0                 0x00000000      /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B2RAT_1                        0x00000100      /* Bank 2 Read Access Time = 1 cycle */
+#define B2RAT_2                        0x00000200      /* Bank 2 Read Access Time = 2 cycles */
+#define B2RAT_3                        0x00000300      /* Bank 2 Read Access Time = 3 cycles */
+#define B2RAT_4                        0x00000400      /* Bank 2 Read Access Time = 4 cycles */
+#define B2RAT_5                        0x00000500      /* Bank 2 Read Access Time = 5 cycles */
+#define B2RAT_6                        0x00000600      /* Bank 2 Read Access Time = 6 cycles */
+#define B2RAT_7                        0x00000700      /* Bank 2 Read Access Time = 7 cycles */
+#define B2RAT_8                        0x00000800      /* Bank 2 Read Access Time = 8 cycles */
+#define B2RAT_9                        0x00000900      /* Bank 2 Read Access Time = 9 cycles */
+#define B2RAT_10               0x00000A00      /* Bank 2 Read Access Time = 10 cycles */
+#define B2RAT_11               0x00000B00      /* Bank 2 Read Access Time = 11 cycles */
+#define B2RAT_12               0x00000C00      /* Bank 2 Read Access Time = 12 cycles */
+#define B2RAT_13               0x00000D00      /* Bank 2 Read Access Time = 13 cycles */
+#define B2RAT_14               0x00000E00      /* Bank 2 Read Access Time = 14 cycles */
+#define B2RAT_15               0x00000F00      /* Bank 2 Read Access Time = 15 cycles */
+#define B2WAT_1                        0x00001000      /* Bank 2 Write Access Time = 1 cycle */
+#define B2WAT_2                        0x00002000      /* Bank 2 Write Access Time = 2 cycles */
+#define B2WAT_3                        0x00003000      /* Bank 2 Write Access Time = 3 cycles */
+#define B2WAT_4                        0x00004000      /* Bank 2 Write Access Time = 4 cycles */
+#define B2WAT_5                        0x00005000      /* Bank 2 Write Access Time = 5 cycles */
+#define B2WAT_6                        0x00006000      /* Bank 2 Write Access Time = 6 cycles */
+#define B2WAT_7                        0x00007000      /* Bank 2 Write Access Time = 7 cycles */
+#define B2WAT_8                        0x00008000      /* Bank 2 Write Access Time = 8 cycles */
+#define B2WAT_9                        0x00009000      /* Bank 2 Write Access Time = 9 cycles */
+#define B2WAT_10               0x0000A000      /* Bank 2 Write Access Time = 10 cycles */
+#define B2WAT_11               0x0000B000      /* Bank 2 Write Access Time = 11 cycles */
+#define B2WAT_12               0x0000C000      /* Bank 2 Write Access Time = 12 cycles */
+#define B2WAT_13               0x0000D000      /* Bank 2 Write Access Time = 13 cycles */
+#define B2WAT_14               0x0000E000      /* Bank 2 Write Access Time = 14 cycles */
+#define B2WAT_15               0x0000F000      /* Bank 2 Write Access Time = 15 cycles */
+#define B3RDYEN                        0x00010000      /* Bank 3 RDY enable, 0=disable, 1=enable */
+#define B3RDYPOL               0x00020000      /* Bank 3 RDY Active high, 0=active low, 1=active high */
+#define B3TT_1                 0x00040000      /* Bank 3 Transition Time from Read to Write = 1 cycle */
+#define B3TT_2                 0x00080000      /* Bank 3 Transition Time from Read to Write = 2 cycles */
+#define B3TT_3                 0x000C0000      /* Bank 3 Transition Time from Read to Write = 3 cycles */
+#define B3TT_4                 0x00000000      /* Bank 3 Transition Time from Read to Write = 4 cycles */
+#define B3ST_1                 0x00100000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B3ST_2                 0x00200000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B3ST_3                 0x00300000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B3ST_4                 0x00000000      /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B3HT_1                 0x00400000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B3HT_2                 0x00800000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B3HT_3                 0x00C00000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B3HT_0                 0x00000000      /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B3RAT_1                        0x01000000      /* Bank 3 Read Access Time = 1 cycle */
+#define B3RAT_2                        0x02000000      /* Bank 3 Read Access Time = 2 cycles */
+#define B3RAT_3                        0x03000000      /* Bank 3 Read Access Time = 3 cycles */
+#define B3RAT_4                        0x04000000      /* Bank 3 Read Access Time = 4 cycles */
+#define B3RAT_5                        0x05000000      /* Bank 3 Read Access Time = 5 cycles */
+#define B3RAT_6                        0x06000000      /* Bank 3 Read Access Time = 6 cycles */
+#define B3RAT_7                        0x07000000      /* Bank 3 Read Access Time = 7 cycles */
+#define B3RAT_8                        0x08000000      /* Bank 3 Read Access Time = 8 cycles */
+#define B3RAT_9                        0x09000000      /* Bank 3 Read Access Time = 9 cycles */
+#define B3RAT_10               0x0A000000      /* Bank 3 Read Access Time = 10 cycles */
+#define B3RAT_11               0x0B000000      /* Bank 3 Read Access Time = 11 cycles */
+#define B3RAT_12               0x0C000000      /* Bank 3 Read Access Time = 12 cycles */
+#define B3RAT_13               0x0D000000      /* Bank 3 Read Access Time = 13 cycles */
+#define B3RAT_14               0x0E000000      /* Bank 3 Read Access Time = 14 cycles */
+#define B3RAT_15               0x0F000000      /* Bank 3 Read Access Time = 15 cycles */
+#define B3WAT_1                        0x10000000      /* Bank 3 Write Access Time = 1 cycle */
+#define B3WAT_2                        0x20000000      /* Bank 3 Write Access Time = 2 cycles */
+#define B3WAT_3                        0x30000000      /* Bank 3 Write Access Time = 3 cycles */
+#define B3WAT_4                        0x40000000      /* Bank 3 Write Access Time = 4 cycles */
+#define B3WAT_5                        0x50000000      /* Bank 3 Write Access Time = 5 cycles */
+#define B3WAT_6                        0x60000000      /* Bank 3 Write Access Time = 6 cycles */
+#define B3WAT_7                        0x70000000      /* Bank 3 Write Access Time = 7 cycles */
+#define B3WAT_8                        0x80000000      /* Bank 3 Write Access Time = 8 cycles */
+#define B3WAT_9                        0x90000000      /* Bank 3 Write Access Time = 9 cycles */
+#define B3WAT_10               0xA0000000      /* Bank 3 Write Access Time = 10 cycles */
+#define B3WAT_11               0xB0000000      /* Bank 3 Write Access Time = 11 cycles */
+#define B3WAT_12               0xC0000000      /* Bank 3 Write Access Time = 12 cycles */
+#define B3WAT_13               0xD0000000      /* Bank 3 Write Access Time = 13 cycles */
+#define B3WAT_14               0xE0000000      /* Bank 3 Write Access Time = 14 cycles */
+#define B3WAT_15               0xF0000000      /* Bank 3 Write Access Time = 15 cycles */
+
+/* **********************  SDRAM CONTROLLER MASKS  *************************** */
+
+/* EBIU_SDGCTL Masks */
+#define SCTLE                  0x00000001      /* Enable SCLK[0], /SRAS, /SCAS, /SWE, SDQM[3:0] */
+#define CL_2                   0x00000008      /* SDRAM CAS latency = 2 cycles */
+#define CL_3                   0x0000000C      /* SDRAM CAS latency = 3 cycles */
+#define PFE                    0x00000010      /* Enable SDRAM prefetch */
+#define PFP                    0x00000020      /* Prefetch has priority over AMC requests */
+#define TRAS_1                 0x00000040      /* SDRAM tRAS = 1 cycle */
+#define TRAS_2                 0x00000080      /* SDRAM tRAS = 2 cycles */
+#define TRAS_3                 0x000000C0      /* SDRAM tRAS = 3 cycles */
+#define TRAS_4                 0x00000100      /* SDRAM tRAS = 4 cycles */
+#define TRAS_5                 0x00000140      /* SDRAM tRAS = 5 cycles */
+#define TRAS_6                 0x00000180      /* SDRAM tRAS = 6 cycles */
+#define TRAS_7                 0x000001C0      /* SDRAM tRAS = 7 cycles */
+#define TRAS_8                 0x00000200      /* SDRAM tRAS = 8 cycles */
+#define TRAS_9                 0x00000240      /* SDRAM tRAS = 9 cycles */
+#define TRAS_10                        0x00000280      /* SDRAM tRAS = 10 cycles */
+#define TRAS_11                        0x000002C0      /* SDRAM tRAS = 11 cycles */
+#define TRAS_12                        0x00000300      /* SDRAM tRAS = 12 cycles */
+#define TRAS_13                        0x00000340      /* SDRAM tRAS = 13 cycles */
+#define TRAS_14                        0x00000380      /* SDRAM tRAS = 14 cycles */
+#define TRAS_15                        0x000003C0      /* SDRAM tRAS = 15 cycles */
+#define TRP_1                  0x00000800      /* SDRAM tRP = 1 cycle */
+#define TRP_2                  0x00001000      /* SDRAM tRP = 2 cycles */
+#define TRP_3                  0x00001800      /* SDRAM tRP = 3 cycles */
+#define TRP_4                  0x00002000      /* SDRAM tRP = 4 cycles */
+#define TRP_5                  0x00002800      /* SDRAM tRP = 5 cycles */
+#define TRP_6                  0x00003000      /* SDRAM tRP = 6 cycles */
+#define TRP_7                  0x00003800      /* SDRAM tRP = 7 cycles */
+#define TRCD_1                 0x00008000      /* SDRAM tRCD = 1 cycle */
+#define TRCD_2                 0x00010000      /* SDRAM tRCD = 2 cycles */
+#define TRCD_3                 0x00018000      /* SDRAM tRCD = 3 cycles */
+#define TRCD_4                 0x00020000      /* SDRAM tRCD = 4 cycles */
+#define TRCD_5                 0x00028000      /* SDRAM tRCD = 5 cycles */
+#define TRCD_6                 0x00030000      /* SDRAM tRCD = 6 cycles */
+#define TRCD_7                 0x00038000      /* SDRAM tRCD = 7 cycles */
+#define TWR_1                  0x00080000      /* SDRAM tWR = 1 cycle */
+#define TWR_2                  0x00100000      /* SDRAM tWR = 2 cycles */
+#define TWR_3                  0x00180000      /* SDRAM tWR = 3 cycles */
+#define PUPSD                  0x00200000      /*Power-up start delay */
+#define PSM                    0x00400000      /* SDRAM power-up sequence = Precharge, mode register set, 8 CBR refresh cycles */
+#define PSS                            0x00800000      /* enable SDRAM power-up sequence on next SDRAM access */
+#define SRFS                   0x01000000      /* Start SDRAM self-refresh mode */
+#define EBUFE                  0x02000000      /* Enable external buffering timing */
+#define FBBRW                  0x04000000      /* Fast back-to-back read write enable */
+#define EMREN                  0x10000000      /* Extended mode register enable */
+#define TCSR                   0x20000000      /* Temp compensated self refresh value 85 deg C */
+#define CDDBG                  0x40000000      /* Tristate SDRAM controls during bus grant */
+
+/* EBIU_SDBCTL Masks */
+#define EB0_E                          0x00000001      /* Enable SDRAM external bank 0 */
+#define EB0_SZ_16                      0x00000000      /* SDRAM external bank size = 16MB */
+#define EB0_SZ_32                      0x00000002      /* SDRAM external bank size = 32MB */
+#define EB0_SZ_64                      0x00000004      /* SDRAM external bank size = 64MB */
+#define EB0_SZ_128                     0x00000006      /* SDRAM external bank size = 128MB */
+#define EB0_CAW_8                      0x00000000      /* SDRAM external bank column address width = 8 bits */
+#define EB0_CAW_9                      0x00000010      /* SDRAM external bank column address width = 9 bits */
+#define EB0_CAW_10                     0x00000020      /* SDRAM external bank column address width = 9 bits */
+#define EB0_CAW_11                     0x00000030      /* SDRAM external bank column address width = 9 bits */
+
+#define EB1_E                          0x00000100      /* Enable SDRAM external bank 1 */
+#define EB1__SZ_16                     0x00000000      /* SDRAM external bank size = 16MB */
+#define EB1__SZ_32                     0x00000200      /* SDRAM external bank size = 32MB */
+#define EB1__SZ_64                     0x00000400      /* SDRAM external bank size = 64MB */
+#define EB1__SZ_128                    0x00000600      /* SDRAM external bank size = 128MB */
+#define EB1__CAW_8                     0x00000000      /* SDRAM external bank column address width = 8 bits */
+#define EB1__CAW_9                     0x00001000      /* SDRAM external bank column address width = 9 bits */
+#define EB1__CAW_10                    0x00002000      /* SDRAM external bank column address width = 9 bits */
+#define EB1__CAW_11                    0x00003000      /* SDRAM external bank column address width = 9 bits */
+
+#define EB2__E                         0x00010000      /* Enable SDRAM external bank 2 */
+#define EB2__SZ_16                     0x00000000      /* SDRAM external bank size = 16MB */
+#define EB2__SZ_32                     0x00020000      /* SDRAM external bank size = 32MB */
+#define EB2__SZ_64                     0x00040000      /* SDRAM external bank size = 64MB */
+#define EB2__SZ_128                    0x00060000      /* SDRAM external bank size = 128MB */
+#define EB2__CAW_8                     0x00000000      /* SDRAM external bank column address width = 8 bits */
+#define EB2__CAW_9                     0x00100000      /* SDRAM external bank column address width = 9 bits */
+#define EB2__CAW_10                    0x00200000      /* SDRAM external bank column address width = 9 bits */
+#define EB2__CAW_11                    0x00300000      /* SDRAM external bank column address width = 9 bits */
+
+#define EB3__E                         0x01000000      /* Enable SDRAM external bank 3 */
+#define EB3__SZ_16                     0x00000000      /* SDRAM external bank size = 16MB */
+#define EB3__SZ_32                     0x02000000      /* SDRAM external bank size = 32MB */
+#define EB3__SZ_64                     0x04000000      /* SDRAM external bank size = 64MB */
+#define EB3__SZ_128                    0x06000000      /* SDRAM external bank size = 128MB */
+#define EB3__CAW_8                     0x00000000      /* SDRAM external bank column address width = 8 bits */
+#define EB3__CAW_9                     0x10000000      /* SDRAM external bank column address width = 9 bits */
+#define EB3__CAW_10                    0x20000000      /* SDRAM external bank column address width = 9 bits */
+#define EB3__CAW_11                    0x30000000      /* SDRAM external bank column address width = 9 bits */
+
+/* EBIU_SDSTAT Masks */
+#define SDCI                   0x00000001      /* SDRAM controller is idle  */
+#define SDSRA                  0x00000002      /* SDRAM SDRAM self refresh is active */
+#define SDPUA                  0x00000004      /* SDRAM power up active  */
+#define SDRS                   0x00000008      /* SDRAM is in reset state */
+#define SDEASE             0x00000010  /* SDRAM EAB sticky error status - W1C */
+#define BGSTAT                 0x00000020      /* Bus granted */
+
+/*VR_CTL Masks*/
+#define WAKE                    0x100
+#define VLEV_6                  0x60
+#define VLEV_7                  0x70
+#define VLEV_8                  0x80
+#define VLEV_9                  0x90
+#define VLEV_10                 0xA0
+#define VLEV_11                 0xB0
+#define VLEV_12                 0xC0
+#define VLEV_13                 0xD0
+#define VLEV_14                 0xE0
+#define VLEV_15                 0xF0
+#define FREQ_3                  0x03
+
+#endif                         /* _DEF_BF561_H */
diff --git a/include/asm-blackfin/mach-bf561/dma.h b/include/asm-blackfin/mach-bf561/dma.h
new file mode 100644 (file)
index 0000000..21d9820
--- /dev/null
@@ -0,0 +1,35 @@
+/*****************************************************************************
+*
+*        BF-533/2/1 Specific Declarations
+*
+****************************************************************************/
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define MAX_BLACKFIN_DMA_CHANNEL 36
+
+#define CH_PPI0                        0
+#define CH_PPI                 (CH_PPI0)
+#define CH_PPI1                        1
+#define CH_SPORT0_RX           12
+#define CH_SPORT0_TX           13
+#define CH_SPORT1_RX           14
+#define CH_SPORT1_TX           15
+#define CH_SPI                 16
+#define CH_UART_RX             17
+#define CH_UART_TX             18
+#define CH_MEM_STREAM0_DEST     24      /* TX */
+#define CH_MEM_STREAM0_SRC      25      /* RX */
+#define CH_MEM_STREAM1_DEST     26      /* TX */
+#define CH_MEM_STREAM1_SRC      27      /* RX */
+#define CH_MEM_STREAM2_DEST    28
+#define CH_MEM_STREAM2_SRC     29
+#define CH_MEM_STREAM3_SRC     30
+#define CH_MEM_STREAM3_DEST    31
+#define CH_IMEM_STREAM0_DEST   32
+#define CH_IMEM_STREAM0_SRC    33
+#define CH_IMEM_STREAM1_SRC    34
+#define CH_IMEM_STREAM1_DEST   35
+
+#endif
diff --git a/include/asm-blackfin/mach-bf561/irq.h b/include/asm-blackfin/mach-bf561/irq.h
new file mode 100644 (file)
index 0000000..a753ce7
--- /dev/null
@@ -0,0 +1,450 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf561/irq.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BF561_IRQ_H_
+#define _BF561_IRQ_H_
+
+/***********************************************************************
+ * Interrupt source definitions:
+             Event Source              Core Event Name     IRQ No
+                                               (highest priority)
+           Emulation Events                    EMU         0
+            Reset                              RST         1
+            NMI                                        NMI         2
+            Exception                          EVX         3
+            Reserved                           --          4
+            Hardware Error                     IVHW        5
+            Core Timer                         IVTMR       6 *
+
+           PLL Wakeup Interrupt                IVG7        7
+           DMA1 Error (generic)                IVG7        8
+           DMA2 Error (generic)                IVG7        9
+           IMDMA Error (generic)               IVG7        10
+           PPI1 Error Interrupt                IVG7        11
+           PPI2 Error Interrupt                IVG7        12
+           SPORT0 Error Interrupt              IVG7        13
+           SPORT1 Error Interrupt              IVG7        14
+           SPI Error Interrupt                 IVG7        15
+           UART Error Interrupt                IVG7        16
+           Reserved Interrupt                  IVG7        17
+
+           DMA1 0  Interrupt(PPI1)             IVG8        18
+           DMA1 1  Interrupt(PPI2)             IVG8        19
+           DMA1 2  Interrupt                   IVG8        20
+           DMA1 3  Interrupt                   IVG8        21
+           DMA1 4  Interrupt                   IVG8        22
+           DMA1 5  Interrupt                   IVG8        23
+           DMA1 6  Interrupt                   IVG8        24
+           DMA1 7  Interrupt                   IVG8        25
+           DMA1 8  Interrupt                   IVG8        26
+           DMA1 9  Interrupt                   IVG8        27
+           DMA1 10 Interrupt                   IVG8        28
+           DMA1 11 Interrupt                   IVG8        29
+
+           DMA2 0  (SPORT0 RX)                 IVG9        30
+           DMA2 1  (SPORT0 TX)                 IVG9        31
+           DMA2 2  (SPORT1 RX)                 IVG9        32
+           DMA2 3  (SPORT2 TX)                 IVG9        33
+           DMA2 4  (SPI)                       IVG9        34
+           DMA2 5  (UART RX)                   IVG9        35
+           DMA2 6  (UART TX)                   IVG9        36
+           DMA2 7  Interrupt                   IVG9        37
+           DMA2 8  Interrupt                   IVG9        38
+           DMA2 9  Interrupt                   IVG9        39
+           DMA2 10 Interrupt                   IVG9        40
+           DMA2 11 Interrupt                   IVG9        41
+
+           TIMER 0  Interrupt                  IVG10       42
+           TIMER 1  Interrupt                  IVG10       43
+           TIMER 2  Interrupt                  IVG10       44
+           TIMER 3  Interrupt                  IVG10       45
+           TIMER 4  Interrupt                  IVG10       46
+           TIMER 5  Interrupt                  IVG10       47
+           TIMER 6  Interrupt                  IVG10       48
+           TIMER 7  Interrupt                  IVG10       49
+           TIMER 8  Interrupt                  IVG10       50
+           TIMER 9  Interrupt                  IVG10       51
+           TIMER 10 Interrupt                  IVG10       52
+           TIMER 11 Interrupt                  IVG10       53
+
+           Programmable Flags0 A (8)           IVG11       54
+           Programmable Flags0 B (8)           IVG11       55
+           Programmable Flags1 A (8)           IVG11       56
+           Programmable Flags1 B (8)           IVG11       57
+           Programmable Flags2 A (8)           IVG11       58
+           Programmable Flags2 B (8)           IVG11       59
+
+           MDMA1 0 write/read INT              IVG8        60
+           MDMA1 1 write/read INT              IVG8        61
+
+           MDMA2 0 write/read INT              IVG9        62
+           MDMA2 1 write/read INT              IVG9        63
+
+           IMDMA 0 write/read INT              IVG12       64
+           IMDMA 1 write/read INT              IVG12       65
+
+           Watch Dog Timer                     IVG13       66
+
+           Reserved interrupt                  IVG7        67
+           Reserved interrupt                  IVG7        68
+           Supplemental interrupt 0            IVG7        69
+           supplemental interrupt 1            IVG7        70
+
+            Software Interrupt 1               IVG14       71
+            Software Interrupt 2               IVG15       72 *
+                                               (lowest priority)
+ **********************************************************************/
+
+#define SYS_IRQS               72
+#define NR_PERI_INTS           64
+
+/*
+ * The ABSTRACT IRQ definitions
+ *  the first seven of the following are fixed,
+ *  the rest you change if you need to.
+ */
+/* IVG 0-6*/
+#define        IRQ_EMU                 0       /* Emulation                */
+#define        IRQ_RST                 1       /* Reset                    */
+#define        IRQ_NMI                 2       /* Non Maskable Interrupt   */
+#define        IRQ_EVX                 3       /* Exception                */
+#define        IRQ_UNUSED              4       /* Reserved interrupt       */
+#define        IRQ_HWERR               5       /* Hardware Error           */
+#define        IRQ_CORETMR             6       /* Core timer               */
+
+#define IVG_BASE               7
+/* IVG 7  */
+#define        IRQ_PLL_WAKEUP          (IVG_BASE + 0)  /* PLL Wakeup Interrupt     */
+#define        IRQ_DMA1_ERROR          (IVG_BASE + 1)  /* DMA1   Error (general)   */
+#define        IRQ_DMA_ERROR           IRQ_DMA1_ERROR  /* DMA1   Error (general)   */
+#define        IRQ_DMA2_ERROR          (IVG_BASE + 2)  /* DMA2   Error (general)   */
+#define IRQ_IMDMA_ERROR                (IVG_BASE + 3)  /* IMDMA  Error Interrupt   */
+#define        IRQ_PPI1_ERROR          (IVG_BASE + 4)  /* PPI1   Error Interrupt   */
+#define        IRQ_PPI_ERROR           IRQ_PPI1_ERROR  /* PPI1   Error Interrupt   */
+#define        IRQ_PPI2_ERROR          (IVG_BASE + 5)  /* PPI2   Error Interrupt   */
+#define        IRQ_SPORT0_ERROR        (IVG_BASE + 6)  /* SPORT0 Error Interrupt   */
+#define        IRQ_SPORT1_ERROR        (IVG_BASE + 7)  /* SPORT1 Error Interrupt   */
+#define        IRQ_SPI_ERROR           (IVG_BASE + 8)  /* SPI    Error Interrupt   */
+#define        IRQ_UART_ERROR          (IVG_BASE + 9)  /* UART   Error Interrupt   */
+#define IRQ_RESERVED_ERROR     (IVG_BASE + 10) /* Reversed     Interrupt   */
+/* IVG 8  */
+#define        IRQ_DMA1_0              (IVG_BASE + 11) /* DMA1 0  Interrupt(PPI1)  */
+#define        IRQ_PPI                 IRQ_DMA1_0      /* DMA1 0  Interrupt(PPI1)  */
+#define        IRQ_PPI0                IRQ_DMA1_0      /* DMA1 0  Interrupt(PPI1)  */
+#define        IRQ_DMA1_1              (IVG_BASE + 12) /* DMA1 1  Interrupt(PPI2)  */
+#define        IRQ_PPI1                IRQ_DMA1_1      /* DMA1 1  Interrupt(PPI2)  */
+#define        IRQ_DMA1_2              (IVG_BASE + 13) /* DMA1 2  Interrupt        */
+#define        IRQ_DMA1_3              (IVG_BASE + 14) /* DMA1 3  Interrupt        */
+#define        IRQ_DMA1_4              (IVG_BASE + 15) /* DMA1 4  Interrupt        */
+#define        IRQ_DMA1_5              (IVG_BASE + 16) /* DMA1 5  Interrupt        */
+#define        IRQ_DMA1_6              (IVG_BASE + 17) /* DMA1 6  Interrupt        */
+#define        IRQ_DMA1_7              (IVG_BASE + 18) /* DMA1 7  Interrupt        */
+#define        IRQ_DMA1_8              (IVG_BASE + 19) /* DMA1 8  Interrupt        */
+#define        IRQ_DMA1_9              (IVG_BASE + 20) /* DMA1 9  Interrupt        */
+#define        IRQ_DMA1_10             (IVG_BASE + 21) /* DMA1 10 Interrupt        */
+#define        IRQ_DMA1_11             (IVG_BASE + 22) /* DMA1 11 Interrupt        */
+/* IVG 9  */
+#define        IRQ_DMA2_0              (IVG_BASE + 23) /* DMA2 0  (SPORT0 RX)      */
+#define        IRQ_SPORT0_RX           IRQ_DMA2_0      /* DMA2 0  (SPORT0 RX)      */
+#define        IRQ_DMA2_1              (IVG_BASE + 24) /* DMA2 1  (SPORT0 TX)      */
+#define        IRQ_SPORT0_TX           IRQ_DMA2_1      /* DMA2 1  (SPORT0 TX)      */
+#define        IRQ_DMA2_2              (IVG_BASE + 25) /* DMA2 2  (SPORT1 RX)      */
+#define        IRQ_SPORT1_RX           IRQ_DMA2_2      /* DMA2 2  (SPORT1 RX)      */
+#define        IRQ_DMA2_3              (IVG_BASE + 26) /* DMA2 3  (SPORT2 TX)      */
+#define        IRQ_SPORT1_TX           IRQ_DMA2_3      /* DMA2 3  (SPORT2 TX)      */
+#define        IRQ_DMA2_4              (IVG_BASE + 27) /* DMA2 4  (SPI)            */
+#define        IRQ_SPI                 IRQ_DMA2_4      /* DMA2 4  (SPI)            */
+#define        IRQ_DMA2_5              (IVG_BASE + 28) /* DMA2 5  (UART RX)        */
+#define        IRQ_UART_RX             IRQ_DMA2_5      /* DMA2 5  (UART RX)        */
+#define        IRQ_DMA2_6              (IVG_BASE + 29) /* DMA2 6  (UART TX)        */
+#define        IRQ_UART_TX             IRQ_DMA2_6      /* DMA2 6  (UART TX)        */
+#define        IRQ_DMA2_7              (IVG_BASE + 30) /* DMA2 7  Interrupt        */
+#define        IRQ_DMA2_8              (IVG_BASE + 31) /* DMA2 8  Interrupt        */
+#define        IRQ_DMA2_9              (IVG_BASE + 32) /* DMA2 9  Interrupt        */
+#define        IRQ_DMA2_10             (IVG_BASE + 33) /* DMA2 10 Interrupt        */
+#define        IRQ_DMA2_11             (IVG_BASE + 34) /* DMA2 11 Interrupt        */
+/* IVG 10 */
+#define IRQ_TIMER0             (IVG_BASE + 35) /* TIMER 0  Interrupt       */
+#define IRQ_TIMER1             (IVG_BASE + 36) /* TIMER 1  Interrupt       */
+#define IRQ_TIMER2             (IVG_BASE + 37) /* TIMER 2  Interrupt       */
+#define IRQ_TIMER3             (IVG_BASE + 38) /* TIMER 3  Interrupt       */
+#define IRQ_TIMER4             (IVG_BASE + 39) /* TIMER 4  Interrupt       */
+#define IRQ_TIMER5             (IVG_BASE + 40) /* TIMER 5  Interrupt       */
+#define IRQ_TIMER6             (IVG_BASE + 41) /* TIMER 6  Interrupt       */
+#define IRQ_TIMER7             (IVG_BASE + 42) /* TIMER 7  Interrupt       */
+#define IRQ_TIMER8             (IVG_BASE + 43) /* TIMER 8  Interrupt       */
+#define IRQ_TIMER9             (IVG_BASE + 44) /* TIMER 9  Interrupt       */
+#define IRQ_TIMER10            (IVG_BASE + 45) /* TIMER 10 Interrupt       */
+#define IRQ_TIMER11            (IVG_BASE + 46) /* TIMER 11 Interrupt       */
+/* IVG 11 */
+#define        IRQ_PROG0_INTA          (IVG_BASE + 47) /* Programmable Flags0 A (8) */
+#define        IRQ_PROG_INTA           IRQ_PROG0_INTA  /* Programmable Flags0 A (8) */
+#define        IRQ_PROG0_INTB          (IVG_BASE + 48) /* Programmable Flags0 B (8) */
+#define        IRQ_PROG_INTB           IRQ_PROG0_INTB  /* Programmable Flags0 B (8) */
+#define        IRQ_PROG1_INTA          (IVG_BASE + 49) /* Programmable Flags1 A (8) */
+#define        IRQ_PROG1_INTB          (IVG_BASE + 50) /* Programmable Flags1 B (8) */
+#define        IRQ_PROG2_INTA          (IVG_BASE + 51) /* Programmable Flags2 A (8) */
+#define        IRQ_PROG2_INTB          (IVG_BASE + 52) /* Programmable Flags2 B (8) */
+/* IVG 8  */
+#define IRQ_DMA1_WRRD0         (IVG_BASE + 53) /* MDMA1 0 write/read INT   */
+#define IRQ_DMA_WRRD0          IRQ_DMA1_WRRD0  /* MDMA1 0 write/read INT   */
+#define IRQ_MEM_DMA0           IRQ_DMA1_WRRD0
+#define IRQ_DMA1_WRRD1         (IVG_BASE + 54) /* MDMA1 1 write/read INT   */
+#define IRQ_DMA_WRRD1          IRQ_DMA1_WRRD1  /* MDMA1 1 write/read INT   */
+#define IRQ_MEM_DMA1           IRQ_DMA1_WRRD1
+/* IVG 9  */
+#define IRQ_DMA2_WRRD0         (IVG_BASE + 55) /* MDMA2 0 write/read INT   */
+#define IRQ_MEM_DMA2           IRQ_DMA2_WRRD0
+#define IRQ_DMA2_WRRD1         (IVG_BASE + 56) /* MDMA2 1 write/read INT   */
+#define IRQ_MEM_DMA3           IRQ_DMA2_WRRD1
+/* IVG 12 */
+#define IRQ_IMDMA_WRRD0                (IVG_BASE + 57) /* IMDMA 0 write/read INT   */
+#define IRQ_IMEM_DMA0          IRQ_IMDMA_WRRD0
+#define IRQ_IMDMA_WRRD1                (IVG_BASE + 58) /* IMDMA 1 write/read INT   */
+#define IRQ_IMEM_DMA1          IRQ_IMDMA_WRRD1
+/* IVG 13 */
+#define        IRQ_WATCH               (IVG_BASE + 59) /* Watch Dog Timer          */
+/* IVG 7  */
+#define IRQ_RESERVED_1         (IVG_BASE + 60) /* Reserved interrupt       */
+#define IRQ_RESERVED_2         (IVG_BASE + 61) /* Reserved interrupt       */
+#define IRQ_SUPPLE_0           (IVG_BASE + 62) /* Supplemental interrupt 0 */
+#define IRQ_SUPPLE_1           (IVG_BASE + 63) /* supplemental interrupt 1 */
+#define        IRQ_SW_INT1             71      /* Software Interrupt 1     */
+#define        IRQ_SW_INT2             72      /* Software Interrupt 2     */
+                                               /* reserved for SYSCALL */
+#define IRQ_PF0                        73
+#define IRQ_PF1                        74
+#define IRQ_PF2                        75
+#define IRQ_PF3                        76
+#define IRQ_PF4                        77
+#define IRQ_PF5                        78
+#define IRQ_PF6                        79
+#define IRQ_PF7                        80
+#define IRQ_PF8                        81
+#define IRQ_PF9                        82
+#define IRQ_PF10               83
+#define IRQ_PF11               84
+#define IRQ_PF12               85
+#define IRQ_PF13               86
+#define IRQ_PF14               87
+#define IRQ_PF15               88
+#define IRQ_PF16               89
+#define IRQ_PF17               90
+#define IRQ_PF18               91
+#define IRQ_PF19               92
+#define IRQ_PF20               93
+#define IRQ_PF21               94
+#define IRQ_PF22               95
+#define IRQ_PF23               96
+#define IRQ_PF24               97
+#define IRQ_PF25               98
+#define IRQ_PF26               99
+#define IRQ_PF27               100
+#define IRQ_PF28               101
+#define IRQ_PF29               102
+#define IRQ_PF30               103
+#define IRQ_PF31               104
+#define IRQ_PF32               105
+#define IRQ_PF33               106
+#define IRQ_PF34               107
+#define IRQ_PF35               108
+#define IRQ_PF36               109
+#define IRQ_PF37               110
+#define IRQ_PF38               111
+#define IRQ_PF39               112
+#define IRQ_PF40               113
+#define IRQ_PF41               114
+#define IRQ_PF42               115
+#define IRQ_PF43               116
+#define IRQ_PF44               117
+#define IRQ_PF45               118
+#define IRQ_PF46               119
+#define IRQ_PF47               120
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define NR_IRQS                        (IRQ_PF47 + 1)
+#else
+#define NR_IRQS                        SYS_IRQS
+#endif
+
+#define IVG7                   7
+#define IVG8                   8
+#define IVG9                   9
+#define IVG10                  10
+#define IVG11                  11
+#define IVG12                  12
+#define IVG13                  13
+#define IVG14                  14
+#define IVG15                  15
+
+/*
+ * DEFAULT PRIORITIES:
+ */
+
+#define        CONFIG_DEF_PLL_WAKEUP           7
+#define        CONFIG_DEF_DMA1_ERROR           7
+#define        CONFIG_DEF_DMA2_ERROR           7
+#define CONFIG_DEF_IMDMA_ERROR         7
+#define        CONFIG_DEF_PPI1_ERROR           7
+#define        CONFIG_DEF_PPI2_ERROR           7
+#define        CONFIG_DEF_SPORT0_ERROR         7
+#define        CONFIG_DEF_SPORT1_ERROR         7
+#define        CONFIG_DEF_SPI_ERROR            7
+#define        CONFIG_DEF_UART_ERROR           7
+#define CONFIG_DEF_RESERVED_ERROR      7
+#define        CONFIG_DEF_DMA1_0               8
+#define        CONFIG_DEF_DMA1_1               8
+#define        CONFIG_DEF_DMA1_2               8
+#define        CONFIG_DEF_DMA1_3               8
+#define        CONFIG_DEF_DMA1_4               8
+#define        CONFIG_DEF_DMA1_5               8
+#define        CONFIG_DEF_DMA1_6               8
+#define        CONFIG_DEF_DMA1_7               8
+#define        CONFIG_DEF_DMA1_8               8
+#define        CONFIG_DEF_DMA1_9               8
+#define        CONFIG_DEF_DMA1_10              8
+#define        CONFIG_DEF_DMA1_11              8
+#define        CONFIG_DEF_DMA2_0               9
+#define        CONFIG_DEF_DMA2_1               9
+#define        CONFIG_DEF_DMA2_2               9
+#define        CONFIG_DEF_DMA2_3               9
+#define        CONFIG_DEF_DMA2_4               9
+#define        CONFIG_DEF_DMA2_5               9
+#define        CONFIG_DEF_DMA2_6               9
+#define        CONFIG_DEF_DMA2_7               9
+#define        CONFIG_DEF_DMA2_8               9
+#define        CONFIG_DEF_DMA2_9               9
+#define        CONFIG_DEF_DMA2_10              9
+#define        CONFIG_DEF_DMA2_11              9
+#define CONFIG_DEF_TIMER0              10
+#define CONFIG_DEF_TIMER1              10
+#define CONFIG_DEF_TIMER2              10
+#define CONFIG_DEF_TIMER3              10
+#define CONFIG_DEF_TIMER4              10
+#define CONFIG_DEF_TIMER5              10
+#define CONFIG_DEF_TIMER6              10
+#define CONFIG_DEF_TIMER7              10
+#define CONFIG_DEF_TIMER8              10
+#define CONFIG_DEF_TIMER9              10
+#define CONFIG_DEF_TIMER10             10
+#define CONFIG_DEF_TIMER11             10
+#define        CONFIG_DEF_PROG0_INTA           11
+#define        CONFIG_DEF_PROG0_INTB           11
+#define        CONFIG_DEF_PROG1_INTA           11
+#define        CONFIG_DEF_PROG1_INTB           11
+#define        CONFIG_DEF_PROG2_INTA           11
+#define        CONFIG_DEF_PROG2_INTB           11
+#define CONFIG_DEF_DMA1_WRRD0          8
+#define CONFIG_DEF_DMA1_WRRD1          8
+#define CONFIG_DEF_DMA2_WRRD0          9
+#define CONFIG_DEF_DMA2_WRRD1          9
+#define CONFIG_DEF_IMDMA_WRRD0         12
+#define CONFIG_DEF_IMDMA_WRRD1         12
+#define        CONFIG_DEF_WATCH                13
+#define CONFIG_DEF_RESERVED_1          7
+#define CONFIG_DEF_RESERVED_2          7
+#define CONFIG_DEF_SUPPLE_0            7
+#define CONFIG_DEF_SUPPLE_1            7
+
+/* IAR0 BIT FIELDS */
+#define        IRQ_PLL_WAKEUP_POS                      0
+#define        IRQ_DMA1_ERROR_POS                      4
+#define        IRQ_DMA2_ERROR_POS                      8
+#define IRQ_IMDMA_ERROR_POS                    12
+#define        IRQ_PPI0_ERROR_POS                      16
+#define        IRQ_PPI1_ERROR_POS                      20
+#define        IRQ_SPORT0_ERROR_POS            24
+#define        IRQ_SPORT1_ERROR_POS            28
+/* IAR1 BIT FIELDS */
+#define        IRQ_SPI_ERROR_POS                       0
+#define        IRQ_UART_ERROR_POS                      4
+#define IRQ_RESERVED_ERROR_POS         8
+#define        IRQ_DMA1_0_POS                  12
+#define        IRQ_DMA1_1_POS                  16
+#define IRQ_DMA1_2_POS                 20
+#define IRQ_DMA1_3_POS                 24
+#define IRQ_DMA1_4_POS                 28
+/* IAR2 BIT FIELDS */
+#define IRQ_DMA1_5_POS                 0
+#define IRQ_DMA1_6_POS                 4
+#define IRQ_DMA1_7_POS                 8
+#define IRQ_DMA1_8_POS                 12
+#define IRQ_DMA1_9_POS                 16
+#define IRQ_DMA1_10_POS                        20
+#define IRQ_DMA1_11_POS                        24
+#define IRQ_DMA2_0_POS                 28
+/* IAR3 BIT FIELDS */
+#define IRQ_DMA2_1_POS                 0
+#define IRQ_DMA2_2_POS                 4
+#define IRQ_DMA2_3_POS                 8
+#define IRQ_DMA2_4_POS                 12
+#define IRQ_DMA2_5_POS                 16
+#define IRQ_DMA2_6_POS                 20
+#define IRQ_DMA2_7_POS                 24
+#define IRQ_DMA2_8_POS                 28
+/* IAR4 BIT FIELDS */
+#define IRQ_DMA2_9_POS                 0
+#define IRQ_DMA2_10_POS                        4
+#define IRQ_DMA2_11_POS                        8
+#define IRQ_TIMER0_POS                 12
+#define IRQ_TIMER1_POS                 16
+#define IRQ_TIMER2_POS                 20
+#define IRQ_TIMER3_POS                 24
+#define IRQ_TIMER4_POS                 28
+/* IAR5 BIT FIELDS */
+#define IRQ_TIMER5_POS                 0
+#define IRQ_TIMER6_POS                 4
+#define IRQ_TIMER7_POS                 8
+#define IRQ_TIMER8_POS                 12
+#define IRQ_TIMER9_POS                 16
+#define IRQ_TIMER10_POS                        20
+#define IRQ_TIMER11_POS                        24
+#define IRQ_PROG0_INTA_POS                     28
+/* IAR6 BIT FIELDS */
+#define IRQ_PROG0_INTB_POS                     0
+#define IRQ_PROG1_INTA_POS                     4
+#define IRQ_PROG1_INTB_POS                     8
+#define IRQ_PROG2_INTA_POS                     12
+#define IRQ_PROG2_INTB_POS                     16
+#define IRQ_DMA1_WRRD0_POS                     20
+#define IRQ_DMA1_WRRD1_POS                     24
+#define IRQ_DMA2_WRRD0_POS                     28
+/* IAR7 BIT FIELDS */
+#define IRQ_DMA2_WRRD1_POS                     0
+#define IRQ_IMDMA_WRRD0_POS                    4
+#define IRQ_IMDMA_WRRD1_POS                    8
+#define        IRQ_WDTIMER_POS                 12
+#define IRQ_RESERVED_1_POS                     16
+#define IRQ_RESERVED_2_POS                     20
+#define IRQ_SUPPLE_0_POS                       24
+#define IRQ_SUPPLE_1_POS                       28
+
+#endif                         /* _BF561_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf561/mem_init.h b/include/asm-blackfin/mach-bf561/mem_init.h
new file mode 100644 (file)
index 0000000..439a589
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * File:         include/asm-blackfin/mach-bf561/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC8M32B2B5_7)
+#if (CONFIG_SCLK_HZ > 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_7
+#define SDRAM_tRAS_num  7
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_6
+#define SDRAM_tRAS_num  6
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_5
+#define SDRAM_tRAS_num  5
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  4
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_2
+#define SDRAM_tRAS_num  2
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ <= 29850746)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_1
+#define SDRAM_tRAS_num  1
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#endif
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC8M32B2B5_7)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   4096       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_GENERIC_BOARD)
+  /*SDRAM INFORMATION: Modify this for your board */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
+#if (CONFIG_MEM_SIZE == 128)
+#define SDRAM_SIZE      EB0_SZ_128
+#endif
+#if (CONFIG_MEM_SIZE == 64)
+#define SDRAM_SIZE      EB0_SZ_64
+#endif
+#if ( CONFIG_MEM_SIZE == 32)
+#define SDRAM_SIZE      EB0_SZ_32
+#endif
+#if (CONFIG_MEM_SIZE == 16)
+#define SDRAM_SIZE      EB0_SZ_16
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 11)
+#define SDRAM_WIDTH     EB0_CAW_11
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 10)
+#define SDRAM_WIDTH     EB0_CAW_10
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 9)
+#define SDRAM_WIDTH     EB0_CAW_9
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 8)
+#define SDRAM_WIDTH     EB0_CAW_8
+#endif
+
+#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EB0_E)
+
+/* Equation from section 17 (p17-46) of BF533 HRM */
+#define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
+
+/* Enable SCLK Out */
+#define mem_SDGCTL        (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF       1
+#else
+#define CLKIN_HALF       0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS      1
+#else
+#define PLL_BYPASS       0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT  ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT  ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT   ((CONFIG_FLASH_SPEED_BHT  * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST   ((CONFIG_FLASH_SPEED_BST  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT   ((CONFIG_FLASH_SPEED_BTT  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0  \
+       (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+        flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf561/mem_map.h b/include/asm-blackfin/mach-bf561/mem_map.h
new file mode 100644 (file)
index 0000000..ebac9a8
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Memory MAP
+ * Common header file for blackfin BF561 of processors.
+ */
+
+#ifndef _MEM_MAP_561_H_
+#define _MEM_MAP_561_H_
+
+#define COREMMR_BASE           0xFFE00000       /* Core MMRs */
+#define SYSMMR_BASE            0xFFC00000       /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE       0x2C000000       /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE       0x04000000      /* 64M */
+#define ASYNC_BANK2_BASE       0x28000000       /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE       0x04000000      /* 64M */
+#define ASYNC_BANK1_BASE       0x24000000       /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE       0x04000000      /* 64M */
+#define ASYNC_BANK0_BASE       0x20000000       /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE       0x04000000      /* 64M */
+
+/* Level 1 Memory */
+
+#ifdef CONFIG_BLKFIN_CACHE
+#define BLKFIN_ICACHESIZE      (16*1024)
+#else
+#define BLKFIN_ICACHESIZE      (0*1024)
+#endif
+
+/* Memory Map for ADSP-BF561 processors */
+
+#ifdef CONFIG_BF561
+#define L1_CODE_START     0xFFA00000
+#define L1_DATA_A_START     0xFF800000
+#define L1_DATA_B_START     0xFF900000
+
+#define L1_CODE_LENGTH      0x4000
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (16*1024)
+#define BLKFIN_DSUPBANKS       1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE      (32*1024)
+#define BLKFIN_DSUPBANKS       2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x8000
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE      (0*1024)
+#define BLKFIN_DSUPBANKS       0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+#endif
+
+/* Level 2 Memory */
+#define L2_START               0xFEB00000
+#define L2_LENGTH              0x20000
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF561)
+#define L1_SCRATCH_START       0xFFB00000
+#define L1_SCRATCH_LENGTH      0x1000
+#endif
+
+#endif                         /* _MEM_MAP_533_H_ */
diff --git a/include/asm-blackfin/mach-common/cdef_LPBlackfin.h b/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
new file mode 100644 (file)
index 0000000..22aa5e6
--- /dev/null
@@ -0,0 +1,471 @@
+ /*
+  * File:        include/asm-blackfin/mach-common/cdef_LPBlackfin.h
+  * Based on:
+  * Author:      unknown
+  *              COPYRIGHT 2005 Analog Devices
+  * Created:     ?
+  * Description:
+  *
+  * Modified:
+  *
+  * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; see the file COPYING.
+  * If not, write to the Free Software Foundation,
+  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+
+#ifndef _CDEF_LPBLACKFIN_H
+#define _CDEF_LPBLACKFIN_H
+
+/*#if !defined(__ADSPLPBLACKFIN__)
+#warning cdef_LPBlackfin.h should only be included for 532 compatible chips.
+#endif
+*/
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/*Cache & SRAM Memory*/
+#define pSRAM_BASE_ADDRESS ((volatile void **)SRAM_BASE_ADDRESS)
+#define bfin_read_SRAM_BASE_ADDRESS()        bfin_read32(SRAM_BASE_ADDRESS)
+#define bfin_write_SRAM_BASE_ADDRESS(val)    bfin_write32(SRAM_BASE_ADDRESS,val)
+#define pDMEM_CONTROL ((volatile unsigned long *)DMEM_CONTROL)
+#define bfin_read_DMEM_CONTROL()             bfin_read32(DMEM_CONTROL)
+#define bfin_write_DMEM_CONTROL(val)         bfin_write32(DMEM_CONTROL,val)
+#define pDCPLB_STATUS ((volatile unsigned long *)DCPLB_STATUS)
+#define bfin_read_DCPLB_STATUS()             bfin_read32(DCPLB_STATUS)
+#define bfin_write_DCPLB_STATUS(val)         bfin_write32(DCPLB_STATUS,val)
+#define pDCPLB_FAULT_ADDR ((volatile void **)DCPLB_FAULT_ADDR)
+#define bfin_read_DCPLB_FAULT_ADDR()         bfin_read32(DCPLB_FAULT_ADDR)
+#define bfin_write_DCPLB_FAULT_ADDR(val)     bfin_write32(DCPLB_FAULT_ADDR,val)
+/*
+#define MMR_TIMEOUT            0xFFE00010
+*/
+#define pDCPLB_ADDR0 ((volatile void **)DCPLB_ADDR0)
+#define bfin_read_DCPLB_ADDR0()              bfin_read32(DCPLB_ADDR0)
+#define bfin_write_DCPLB_ADDR0(val)          bfin_write32(DCPLB_ADDR0,val)
+#define pDCPLB_ADDR1 ((volatile void **)DCPLB_ADDR1)
+#define bfin_read_DCPLB_ADDR1()              bfin_read32(DCPLB_ADDR1)
+#define bfin_write_DCPLB_ADDR1(val)          bfin_write32(DCPLB_ADDR1,val)
+#define pDCPLB_ADDR2 ((volatile void **)DCPLB_ADDR2)
+#define bfin_read_DCPLB_ADDR2()              bfin_read32(DCPLB_ADDR2)
+#define bfin_write_DCPLB_ADDR2(val)          bfin_write32(DCPLB_ADDR2,val)
+#define pDCPLB_ADDR3 ((volatile void **)DCPLB_ADDR3)
+#define bfin_read_DCPLB_ADDR3()              bfin_read32(DCPLB_ADDR3)
+#define bfin_write_DCPLB_ADDR3(val)          bfin_write32(DCPLB_ADDR3,val)
+#define pDCPLB_ADDR4 ((volatile void **)DCPLB_ADDR4)
+#define bfin_read_DCPLB_ADDR4()              bfin_read32(DCPLB_ADDR4)
+#define bfin_write_DCPLB_ADDR4(val)          bfin_write32(DCPLB_ADDR4,val)
+#define pDCPLB_ADDR5 ((volatile void **)DCPLB_ADDR5)
+#define bfin_read_DCPLB_ADDR5()              bfin_read32(DCPLB_ADDR5)
+#define bfin_write_DCPLB_ADDR5(val)          bfin_write32(DCPLB_ADDR5,val)
+#define pDCPLB_ADDR6 ((volatile void **)DCPLB_ADDR6)
+#define bfin_read_DCPLB_ADDR6()              bfin_read32(DCPLB_ADDR6)
+#define bfin_write_DCPLB_ADDR6(val)          bfin_write32(DCPLB_ADDR6,val)
+#define pDCPLB_ADDR7 ((volatile void **)DCPLB_ADDR7)
+#define bfin_read_DCPLB_ADDR7()              bfin_read32(DCPLB_ADDR7)
+#define bfin_write_DCPLB_ADDR7(val)          bfin_write32(DCPLB_ADDR7,val)
+#define pDCPLB_ADDR8 ((volatile void **)DCPLB_ADDR8)
+#define bfin_read_DCPLB_ADDR8()              bfin_read32(DCPLB_ADDR8)
+#define bfin_write_DCPLB_ADDR8(val)          bfin_write32(DCPLB_ADDR8,val)
+#define pDCPLB_ADDR9 ((volatile void **)DCPLB_ADDR9)
+#define bfin_read_DCPLB_ADDR9()              bfin_read32(DCPLB_ADDR9)
+#define bfin_write_DCPLB_ADDR9(val)          bfin_write32(DCPLB_ADDR9,val)
+#define pDCPLB_ADDR10 ((volatile void **)DCPLB_ADDR10)
+#define bfin_read_DCPLB_ADDR10()             bfin_read32(DCPLB_ADDR10)
+#define bfin_write_DCPLB_ADDR10(val)         bfin_write32(DCPLB_ADDR10,val)
+#define pDCPLB_ADDR11 ((volatile void **)DCPLB_ADDR11)
+#define bfin_read_DCPLB_ADDR11()             bfin_read32(DCPLB_ADDR11)
+#define bfin_write_DCPLB_ADDR11(val)         bfin_write32(DCPLB_ADDR11,val)
+#define pDCPLB_ADDR12 ((volatile void **)DCPLB_ADDR12)
+#define bfin_read_DCPLB_ADDR12()             bfin_read32(DCPLB_ADDR12)
+#define bfin_write_DCPLB_ADDR12(val)         bfin_write32(DCPLB_ADDR12,val)
+#define pDCPLB_ADDR13 ((volatile void **)DCPLB_ADDR13)
+#define bfin_read_DCPLB_ADDR13()             bfin_read32(DCPLB_ADDR13)
+#define bfin_write_DCPLB_ADDR13(val)         bfin_write32(DCPLB_ADDR13,val)
+#define pDCPLB_ADDR14 ((volatile void **)DCPLB_ADDR14)
+#define bfin_read_DCPLB_ADDR14()             bfin_read32(DCPLB_ADDR14)
+#define bfin_write_DCPLB_ADDR14(val)         bfin_write32(DCPLB_ADDR14,val)
+#define pDCPLB_ADDR15 ((volatile void **)DCPLB_ADDR15)
+#define bfin_read_DCPLB_ADDR15()             bfin_read32(DCPLB_ADDR15)
+#define bfin_write_DCPLB_ADDR15(val)         bfin_write32(DCPLB_ADDR15,val)
+#define pDCPLB_DATA0 ((volatile unsigned long *)DCPLB_DATA0)
+#define bfin_read_DCPLB_DATA0()              bfin_read32(DCPLB_DATA0)
+#define bfin_write_DCPLB_DATA0(val)          bfin_write32(DCPLB_DATA0,val)
+#define pDCPLB_DATA1 ((volatile unsigned long *)DCPLB_DATA1)
+#define bfin_read_DCPLB_DATA1()              bfin_read32(DCPLB_DATA1)
+#define bfin_write_DCPLB_DATA1(val)          bfin_write32(DCPLB_DATA1,val)
+#define pDCPLB_DATA2 ((volatile unsigned long *)DCPLB_DATA2)
+#define bfin_read_DCPLB_DATA2()              bfin_read32(DCPLB_DATA2)
+#define bfin_write_DCPLB_DATA2(val)          bfin_write32(DCPLB_DATA2,val)
+#define pDCPLB_DATA3 ((volatile unsigned long *)DCPLB_DATA3)
+#define bfin_read_DCPLB_DATA3()              bfin_read32(DCPLB_DATA3)
+#define bfin_write_DCPLB_DATA3(val)          bfin_write32(DCPLB_DATA3,val)
+#define pDCPLB_DATA4 ((volatile unsigned long *)DCPLB_DATA4)
+#define bfin_read_DCPLB_DATA4()              bfin_read32(DCPLB_DATA4)
+#define bfin_write_DCPLB_DATA4(val)          bfin_write32(DCPLB_DATA4,val)
+#define pDCPLB_DATA5 ((volatile unsigned long *)DCPLB_DATA5)
+#define bfin_read_DCPLB_DATA5()              bfin_read32(DCPLB_DATA5)
+#define bfin_write_DCPLB_DATA5(val)          bfin_write32(DCPLB_DATA5,val)
+#define pDCPLB_DATA6 ((volatile unsigned long *)DCPLB_DATA6)
+#define bfin_read_DCPLB_DATA6()              bfin_read32(DCPLB_DATA6)
+#define bfin_write_DCPLB_DATA6(val)          bfin_write32(DCPLB_DATA6,val)
+#define pDCPLB_DATA7 ((volatile unsigned long *)DCPLB_DATA7)
+#define bfin_read_DCPLB_DATA7()              bfin_read32(DCPLB_DATA7)
+#define bfin_write_DCPLB_DATA7(val)          bfin_write32(DCPLB_DATA7,val)
+#define pDCPLB_DATA8 ((volatile unsigned long *)DCPLB_DATA8)
+#define bfin_read_DCPLB_DATA8()              bfin_read32(DCPLB_DATA8)
+#define bfin_write_DCPLB_DATA8(val)          bfin_write32(DCPLB_DATA8,val)
+#define pDCPLB_DATA9 ((volatile unsigned long *)DCPLB_DATA9)
+#define bfin_read_DCPLB_DATA9()              bfin_read32(DCPLB_DATA9)
+#define bfin_write_DCPLB_DATA9(val)          bfin_write32(DCPLB_DATA9,val)
+#define pDCPLB_DATA10 ((volatile unsigned long *)DCPLB_DATA10)
+#define bfin_read_DCPLB_DATA10()             bfin_read32(DCPLB_DATA10)
+#define bfin_write_DCPLB_DATA10(val)         bfin_write32(DCPLB_DATA10,val)
+#define pDCPLB_DATA11 ((volatile unsigned long *)DCPLB_DATA11)
+#define bfin_read_DCPLB_DATA11()             bfin_read32(DCPLB_DATA11)
+#define bfin_write_DCPLB_DATA11(val)         bfin_write32(DCPLB_DATA11,val)
+#define pDCPLB_DATA12 ((volatile unsigned long *)DCPLB_DATA12)
+#define bfin_read_DCPLB_DATA12()             bfin_read32(DCPLB_DATA12)
+#define bfin_write_DCPLB_DATA12(val)         bfin_write32(DCPLB_DATA12,val)
+#define pDCPLB_DATA13 ((volatile unsigned long *)DCPLB_DATA13)
+#define bfin_read_DCPLB_DATA13()             bfin_read32(DCPLB_DATA13)
+#define bfin_write_DCPLB_DATA13(val)         bfin_write32(DCPLB_DATA13,val)
+#define pDCPLB_DATA14 ((volatile unsigned long *)DCPLB_DATA14)
+#define bfin_read_DCPLB_DATA14()             bfin_read32(DCPLB_DATA14)
+#define bfin_write_DCPLB_DATA14(val)         bfin_write32(DCPLB_DATA14,val)
+#define pDCPLB_DATA15 ((volatile unsigned long *)DCPLB_DATA15)
+#define bfin_read_DCPLB_DATA15()             bfin_read32(DCPLB_DATA15)
+#define bfin_write_DCPLB_DATA15(val)         bfin_write32(DCPLB_DATA15,val)
+#define pDTEST_COMMAND ((volatile unsigned long *)DTEST_COMMAND)
+#define bfin_read_DTEST_COMMAND()            bfin_read32(DTEST_COMMAND)
+#define bfin_write_DTEST_COMMAND(val)        bfin_write32(DTEST_COMMAND,val)
+/*
+#define DTEST_INDEX            0xFFE00304
+*/
+#define pDTEST_DATA0 ((volatile unsigned long *)DTEST_DATA0)
+#define bfin_read_DTEST_DATA0()              bfin_read32(DTEST_DATA0)
+#define bfin_write_DTEST_DATA0(val)          bfin_write32(DTEST_DATA0,val)
+#define pDTEST_DATA1 ((volatile unsigned long *)DTEST_DATA1)
+#define bfin_read_DTEST_DATA1()              bfin_read32(DTEST_DATA1)
+#define bfin_write_DTEST_DATA1(val)          bfin_write32(DTEST_DATA1,val)
+/*
+#define DTEST_DATA2            0xFFE00408
+#define DTEST_DATA3            0xFFE0040C
+*/
+#define pIMEM_CONTROL ((volatile unsigned long *)IMEM_CONTROL)
+#define bfin_read_IMEM_CONTROL()             bfin_read32(IMEM_CONTROL)
+#define bfin_write_IMEM_CONTROL(val)         bfin_write32(IMEM_CONTROL,val)
+#define pICPLB_STATUS ((volatile unsigned long *)ICPLB_STATUS)
+#define bfin_read_ICPLB_STATUS()             bfin_read32(ICPLB_STATUS)
+#define bfin_write_ICPLB_STATUS(val)         bfin_write32(ICPLB_STATUS,val)
+#define pICPLB_FAULT_ADDR ((volatile void **)ICPLB_FAULT_ADDR)
+#define bfin_read_ICPLB_FAULT_ADDR()         bfin_read32(ICPLB_FAULT_ADDR)
+#define bfin_write_ICPLB_FAULT_ADDR(val)     bfin_write32(ICPLB_FAULT_ADDR,val)
+#define pICPLB_ADDR0 ((volatile void **)ICPLB_ADDR0)
+#define bfin_read_ICPLB_ADDR0()              bfin_read32(ICPLB_ADDR0)
+#define bfin_write_ICPLB_ADDR0(val)          bfin_write32(ICPLB_ADDR0,val)
+#define pICPLB_ADDR1 ((volatile void **)ICPLB_ADDR1)
+#define bfin_read_ICPLB_ADDR1()              bfin_read32(ICPLB_ADDR1)
+#define bfin_write_ICPLB_ADDR1(val)          bfin_write32(ICPLB_ADDR1,val)
+#define pICPLB_ADDR2 ((volatile void **)ICPLB_ADDR2)
+#define bfin_read_ICPLB_ADDR2()              bfin_read32(ICPLB_ADDR2)
+#define bfin_write_ICPLB_ADDR2(val)          bfin_write32(ICPLB_ADDR2,val)
+#define pICPLB_ADDR3 ((volatile void **)ICPLB_ADDR3)
+#define bfin_read_ICPLB_ADDR3()              bfin_read32(ICPLB_ADDR3)
+#define bfin_write_ICPLB_ADDR3(val)          bfin_write32(ICPLB_ADDR3,val)
+#define pICPLB_ADDR4 ((volatile void **)ICPLB_ADDR4)
+#define bfin_read_ICPLB_ADDR4()              bfin_read32(ICPLB_ADDR4)
+#define bfin_write_ICPLB_ADDR4(val)          bfin_write32(ICPLB_ADDR4,val)
+#define pICPLB_ADDR5 ((volatile void **)ICPLB_ADDR5)
+#define bfin_read_ICPLB_ADDR5()              bfin_read32(ICPLB_ADDR5)
+#define bfin_write_ICPLB_ADDR5(val)          bfin_write32(ICPLB_ADDR5,val)
+#define pICPLB_ADDR6 ((volatile void **)ICPLB_ADDR6)
+#define bfin_read_ICPLB_ADDR6()              bfin_read32(ICPLB_ADDR6)
+#define bfin_write_ICPLB_ADDR6(val)          bfin_write32(ICPLB_ADDR6,val)
+#define pICPLB_ADDR7 ((volatile void **)ICPLB_ADDR7)
+#define bfin_read_ICPLB_ADDR7()              bfin_read32(ICPLB_ADDR7)
+#define bfin_write_ICPLB_ADDR7(val)          bfin_write32(ICPLB_ADDR7,val)
+#define pICPLB_ADDR8 ((volatile void **)ICPLB_ADDR8)
+#define bfin_read_ICPLB_ADDR8()              bfin_read32(ICPLB_ADDR8)
+#define bfin_write_ICPLB_ADDR8(val)          bfin_write32(ICPLB_ADDR8,val)
+#define pICPLB_ADDR9 ((volatile void **)ICPLB_ADDR9)
+#define bfin_read_ICPLB_ADDR9()              bfin_read32(ICPLB_ADDR9)
+#define bfin_write_ICPLB_ADDR9(val)          bfin_write32(ICPLB_ADDR9,val)
+#define pICPLB_ADDR10 ((volatile void **)ICPLB_ADDR10)
+#define bfin_read_ICPLB_ADDR10()             bfin_read32(ICPLB_ADDR10)
+#define bfin_write_ICPLB_ADDR10(val)         bfin_write32(ICPLB_ADDR10,val)
+#define pICPLB_ADDR11 ((volatile void **)ICPLB_ADDR11)
+#define bfin_read_ICPLB_ADDR11()             bfin_read32(ICPLB_ADDR11)
+#define bfin_write_ICPLB_ADDR11(val)         bfin_write32(ICPLB_ADDR11,val)
+#define pICPLB_ADDR12 ((volatile void **)ICPLB_ADDR12)
+#define bfin_read_ICPLB_ADDR12()             bfin_read32(ICPLB_ADDR12)
+#define bfin_write_ICPLB_ADDR12(val)         bfin_write32(ICPLB_ADDR12,val)
+#define pICPLB_ADDR13 ((volatile void **)ICPLB_ADDR13)
+#define bfin_read_ICPLB_ADDR13()             bfin_read32(ICPLB_ADDR13)
+#define bfin_write_ICPLB_ADDR13(val)         bfin_write32(ICPLB_ADDR13,val)
+#define pICPLB_ADDR14 ((volatile void **)ICPLB_ADDR14)
+#define bfin_read_ICPLB_ADDR14()             bfin_read32(ICPLB_ADDR14)
+#define bfin_write_ICPLB_ADDR14(val)         bfin_write32(ICPLB_ADDR14,val)
+#define pICPLB_ADDR15 ((volatile void **)ICPLB_ADDR15)
+#define bfin_read_ICPLB_ADDR15()             bfin_read32(ICPLB_ADDR15)
+#define bfin_write_ICPLB_ADDR15(val)         bfin_write32(ICPLB_ADDR15,val)
+#define pICPLB_DATA0 ((volatile unsigned long *)ICPLB_DATA0)
+#define bfin_read_ICPLB_DATA0()              bfin_read32(ICPLB_DATA0)
+#define bfin_write_ICPLB_DATA0(val)          bfin_write32(ICPLB_DATA0,val)
+#define pICPLB_DATA1 ((volatile unsigned long *)ICPLB_DATA1)
+#define bfin_read_ICPLB_DATA1()              bfin_read32(ICPLB_DATA1)
+#define bfin_write_ICPLB_DATA1(val)          bfin_write32(ICPLB_DATA1,val)
+#define pICPLB_DATA2 ((volatile unsigned long *)ICPLB_DATA2)
+#define bfin_read_ICPLB_DATA2()              bfin_read32(ICPLB_DATA2)
+#define bfin_write_ICPLB_DATA2(val)          bfin_write32(ICPLB_DATA2,val)
+#define pICPLB_DATA3 ((volatile unsigned long *)ICPLB_DATA3)
+#define bfin_read_ICPLB_DATA3()              bfin_read32(ICPLB_DATA3)
+#define bfin_write_ICPLB_DATA3(val)          bfin_write32(ICPLB_DATA3,val)
+#define pICPLB_DATA4 ((volatile unsigned long *)ICPLB_DATA4)
+#define bfin_read_ICPLB_DATA4()              bfin_read32(ICPLB_DATA4)
+#define bfin_write_ICPLB_DATA4(val)          bfin_write32(ICPLB_DATA4,val)
+#define pICPLB_DATA5 ((volatile unsigned long *)ICPLB_DATA5)
+#define bfin_read_ICPLB_DATA5()              bfin_read32(ICPLB_DATA5)
+#define bfin_write_ICPLB_DATA5(val)          bfin_write32(ICPLB_DATA5,val)
+#define pICPLB_DATA6 ((volatile unsigned long *)ICPLB_DATA6)
+#define bfin_read_ICPLB_DATA6()              bfin_read32(ICPLB_DATA6)
+#define bfin_write_ICPLB_DATA6(val)          bfin_write32(ICPLB_DATA6,val)
+#define pICPLB_DATA7 ((volatile unsigned long *)ICPLB_DATA7)
+#define bfin_read_ICPLB_DATA7()              bfin_read32(ICPLB_DATA7)
+#define bfin_write_ICPLB_DATA7(val)          bfin_write32(ICPLB_DATA7,val)
+#define pICPLB_DATA8 ((volatile unsigned long *)ICPLB_DATA8)
+#define bfin_read_ICPLB_DATA8()              bfin_read32(ICPLB_DATA8)
+#define bfin_write_ICPLB_DATA8(val)          bfin_write32(ICPLB_DATA8,val)
+#define pICPLB_DATA9 ((volatile unsigned long *)ICPLB_DATA9)
+#define bfin_read_ICPLB_DATA9()              bfin_read32(ICPLB_DATA9)
+#define bfin_write_ICPLB_DATA9(val)          bfin_write32(ICPLB_DATA9,val)
+#define pICPLB_DATA10 ((volatile unsigned long *)ICPLB_DATA10)
+#define bfin_read_ICPLB_DATA10()             bfin_read32(ICPLB_DATA10)
+#define bfin_write_ICPLB_DATA10(val)         bfin_write32(ICPLB_DATA10,val)
+#define pICPLB_DATA11 ((volatile unsigned long *)ICPLB_DATA11)
+#define bfin_read_ICPLB_DATA11()             bfin_read32(ICPLB_DATA11)
+#define bfin_write_ICPLB_DATA11(val)         bfin_write32(ICPLB_DATA11,val)
+#define pICPLB_DATA12 ((volatile unsigned long *)ICPLB_DATA12)
+#define bfin_read_ICPLB_DATA12()             bfin_read32(ICPLB_DATA12)
+#define bfin_write_ICPLB_DATA12(val)         bfin_write32(ICPLB_DATA12,val)
+#define pICPLB_DATA13 ((volatile unsigned long *)ICPLB_DATA13)
+#define bfin_read_ICPLB_DATA13()             bfin_read32(ICPLB_DATA13)
+#define bfin_write_ICPLB_DATA13(val)         bfin_write32(ICPLB_DATA13,val)
+#define pICPLB_DATA14 ((volatile unsigned long *)ICPLB_DATA14)
+#define bfin_read_ICPLB_DATA14()             bfin_read32(ICPLB_DATA14)
+#define bfin_write_ICPLB_DATA14(val)         bfin_write32(ICPLB_DATA14,val)
+#define pICPLB_DATA15 ((volatile unsigned long *)ICPLB_DATA15)
+#define bfin_read_ICPLB_DATA15()             bfin_read32(ICPLB_DATA15)
+#define bfin_write_ICPLB_DATA15(val)         bfin_write32(ICPLB_DATA15,val)
+#define pITEST_COMMAND ((volatile unsigned long *)ITEST_COMMAND)
+#define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
+#define bfin_write_ITEST_COMMAND(val)        bfin_write32(ITEST_COMMAND,val)
+#if 0
+#define ITEST_INDEX            0xFFE01304   /* Instruction Test Index Register */
+#endif
+#define pITEST_DATA0 ((volatile unsigned long *)ITEST_DATA0)
+#define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
+#define bfin_write_ITEST_DATA0(val)          bfin_write32(ITEST_DATA0,val)
+#define pITEST_DATA1 ((volatile unsigned long *)ITEST_DATA1)
+#define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
+#define bfin_write_ITEST_DATA1(val)          bfin_write32(ITEST_DATA1,val)
+
+/* Event/Interrupt Registers*/
+
+#define pEVT0 ((volatile void **)EVT0)
+#define bfin_read_EVT0()                     bfin_read32(EVT0)
+#define bfin_write_EVT0(val)                 bfin_write32(EVT0,val)
+#define pEVT1 ((volatile void **)EVT1)
+#define bfin_read_EVT1()                     bfin_read32(EVT1)
+#define bfin_write_EVT1(val)                 bfin_write32(EVT1,val)
+#define pEVT2 ((volatile void **)EVT2)
+#define bfin_read_EVT2()                     bfin_read32(EVT2)
+#define bfin_write_EVT2(val)                 bfin_write32(EVT2,val)
+#define pEVT3 ((volatile void **)EVT3)
+#define bfin_read_EVT3()                     bfin_read32(EVT3)
+#define bfin_write_EVT3(val)                 bfin_write32(EVT3,val)
+#define pEVT4 ((volatile void **)EVT4)
+#define bfin_read_EVT4()                     bfin_read32(EVT4)
+#define bfin_write_EVT4(val)                 bfin_write32(EVT4,val)
+#define pEVT5 ((volatile void **)EVT5)
+#define bfin_read_EVT5()                     bfin_read32(EVT5)
+#define bfin_write_EVT5(val)                 bfin_write32(EVT5,val)
+#define pEVT6 ((volatile void **)EVT6)
+#define bfin_read_EVT6()                     bfin_read32(EVT6)
+#define bfin_write_EVT6(val)                 bfin_write32(EVT6,val)
+#define pEVT7 ((volatile void **)EVT7)
+#define bfin_read_EVT7()                     bfin_read32(EVT7)
+#define bfin_write_EVT7(val)                 bfin_write32(EVT7,val)
+#define pEVT8 ((volatile void **)EVT8)
+#define bfin_read_EVT8()                     bfin_read32(EVT8)
+#define bfin_write_EVT8(val)                 bfin_write32(EVT8,val)
+#define pEVT9 ((volatile void **)EVT9)
+#define bfin_read_EVT9()                     bfin_read32(EVT9)
+#define bfin_write_EVT9(val)                 bfin_write32(EVT9,val)
+#define pEVT10 ((volatile void **)EVT10)
+#define bfin_read_EVT10()                    bfin_read32(EVT10)
+#define bfin_write_EVT10(val)                bfin_write32(EVT10,val)
+#define pEVT11 ((volatile void **)EVT11)
+#define bfin_read_EVT11()                    bfin_read32(EVT11)
+#define bfin_write_EVT11(val)                bfin_write32(EVT11,val)
+#define pEVT12 ((volatile void **)EVT12)
+#define bfin_read_EVT12()                    bfin_read32(EVT12)
+#define bfin_write_EVT12(val)                bfin_write32(EVT12,val)
+#define pEVT13 ((volatile void **)EVT13)
+#define bfin_read_EVT13()                    bfin_read32(EVT13)
+#define bfin_write_EVT13(val)                bfin_write32(EVT13,val)
+#define pEVT14 ((volatile void **)EVT14)
+#define bfin_read_EVT14()                    bfin_read32(EVT14)
+#define bfin_write_EVT14(val)                bfin_write32(EVT14,val)
+#define pEVT15 ((volatile void **)EVT15)
+#define bfin_read_EVT15()                    bfin_read32(EVT15)
+#define bfin_write_EVT15(val)                bfin_write32(EVT15,val)
+#define pIMASK ((volatile unsigned long *)IMASK)
+#define bfin_read_IMASK()                    bfin_read32(IMASK)
+#define bfin_write_IMASK(val)                bfin_write32(IMASK,val)
+#define pIPEND ((volatile unsigned long *)IPEND)
+#define bfin_read_IPEND()                    bfin_read32(IPEND)
+#define bfin_write_IPEND(val)                bfin_write32(IPEND,val)
+#define pILAT ((volatile unsigned long *)ILAT)
+#define bfin_read_ILAT()                     bfin_read32(ILAT)
+#define bfin_write_ILAT(val)                 bfin_write32(ILAT,val)
+
+/*Core Timer Registers*/
+#define pTCNTL ((volatile unsigned long *)TCNTL)
+#define bfin_read_TCNTL()                    bfin_read32(TCNTL)
+#define bfin_write_TCNTL(val)                bfin_write32(TCNTL,val)
+#define pTPERIOD ((volatile unsigned long *)TPERIOD)
+#define bfin_read_TPERIOD()                  bfin_read32(TPERIOD)
+#define bfin_write_TPERIOD(val)              bfin_write32(TPERIOD,val)
+#define pTSCALE ((volatile unsigned long *)TSCALE)
+#define bfin_read_TSCALE()                   bfin_read32(TSCALE)
+#define bfin_write_TSCALE(val)               bfin_write32(TSCALE,val)
+#define pTCOUNT ((volatile unsigned long *)TCOUNT)
+#define bfin_read_TCOUNT()                   bfin_read32(TCOUNT)
+#define bfin_write_TCOUNT(val)               bfin_write32(TCOUNT,val)
+
+/*Debug/MP/Emulation Registers*/
+#define pDSPID ((volatile unsigned long *)DSPID)
+#define bfin_read_DSPID()                    bfin_read32(DSPID)
+#define bfin_write_DSPID(val)                bfin_write32(DSPID,val)
+#define pDBGCTL ((volatile unsigned long *)DBGCTL)
+#define bfin_read_DBGCTL()                   bfin_read32(DBGCTL)
+#define bfin_write_DBGCTL(val)               bfin_write32(DBGCTL,val)
+#define pDBGSTAT ((volatile unsigned long *)DBGSTAT)
+#define bfin_read_DBGSTAT()                  bfin_read32(DBGSTAT)
+#define bfin_write_DBGSTAT(val)              bfin_write32(DBGSTAT,val)
+#define pEMUDAT ((volatile unsigned long *)EMUDAT)
+#define bfin_read_EMUDAT()                   bfin_read32(EMUDAT)
+#define bfin_write_EMUDAT(val)               bfin_write32(EMUDAT,val)
+
+/*Trace Buffer Registers*/
+#define pTBUFCTL ((volatile unsigned long *)TBUFCTL)
+#define bfin_read_TBUFCTL()                  bfin_read32(TBUFCTL)
+#define bfin_write_TBUFCTL(val)              bfin_write32(TBUFCTL,val)
+#define pTBUFSTAT ((volatile unsigned long *)TBUFSTAT)
+#define bfin_read_TBUFSTAT()                 bfin_read32(TBUFSTAT)
+#define bfin_write_TBUFSTAT(val)             bfin_write32(TBUFSTAT,val)
+#define pTBUF ((volatile void **)TBUF)
+#define bfin_read_TBUF()                     bfin_read32(TBUF)
+#define bfin_write_TBUF(val)                 bfin_write32(TBUF,val)
+
+/*Watch Point Control Registers*/
+#define pWPIACTL ((volatile unsigned long *)WPIACTL)
+#define bfin_read_WPIACTL()                  bfin_read32(WPIACTL)
+#define bfin_write_WPIACTL(val)              bfin_write32(WPIACTL,val)
+#define pWPIA0 ((volatile void **)WPIA0)
+#define bfin_read_WPIA0()                    bfin_read32(WPIA0)
+#define bfin_write_WPIA0(val)                bfin_write32(WPIA0,val)
+#define pWPIA1 ((volatile void **)WPIA1)
+#define bfin_read_WPIA1()                    bfin_read32(WPIA1)
+#define bfin_write_WPIA1(val)                bfin_write32(WPIA1,val)
+#define pWPIA2 ((volatile void **)WPIA2)
+#define bfin_read_WPIA2()                    bfin_read32(WPIA2)
+#define bfin_write_WPIA2(val)                bfin_write32(WPIA2,val)
+#define pWPIA3 ((volatile void **)WPIA3)
+#define bfin_read_WPIA3()                    bfin_read32(WPIA3)
+#define bfin_write_WPIA3(val)                bfin_write32(WPIA3,val)
+#define pWPIA4 ((volatile void **)WPIA4)
+#define bfin_read_WPIA4()                    bfin_read32(WPIA4)
+#define bfin_write_WPIA4(val)                bfin_write32(WPIA4,val)
+#define pWPIA5 ((volatile void **)WPIA5)
+#define bfin_read_WPIA5()                    bfin_read32(WPIA5)
+#define bfin_write_WPIA5(val)                bfin_write32(WPIA5,val)
+#define pWPIACNT0 ((volatile unsigned long *)WPIACNT0)
+#define bfin_read_WPIACNT0()                 bfin_read32(WPIACNT0)
+#define bfin_write_WPIACNT0(val)             bfin_write32(WPIACNT0,val)
+#define pWPIACNT1 ((volatile unsigned long *)WPIACNT1)
+#define bfin_read_WPIACNT1()                 bfin_read32(WPIACNT1)
+#define bfin_write_WPIACNT1(val)             bfin_write32(WPIACNT1,val)
+#define pWPIACNT2 ((volatile unsigned long *)WPIACNT2)
+#define bfin_read_WPIACNT2()                 bfin_read32(WPIACNT2)
+#define bfin_write_WPIACNT2(val)             bfin_write32(WPIACNT2,val)
+#define pWPIACNT3 ((volatile unsigned long *)WPIACNT3)
+#define bfin_read_WPIACNT3()                 bfin_read32(WPIACNT3)
+#define bfin_write_WPIACNT3(val)             bfin_write32(WPIACNT3,val)
+#define pWPIACNT4 ((volatile unsigned long *)WPIACNT4)
+#define bfin_read_WPIACNT4()                 bfin_read32(WPIACNT4)
+#define bfin_write_WPIACNT4(val)             bfin_write32(WPIACNT4,val)
+#define pWPIACNT5 ((volatile unsigned long *)WPIACNT5)
+#define bfin_read_WPIACNT5()                 bfin_read32(WPIACNT5)
+#define bfin_write_WPIACNT5(val)             bfin_write32(WPIACNT5,val)
+#define pWPDACTL ((volatile unsigned long *)WPDACTL)
+#define bfin_read_WPDACTL()                  bfin_read32(WPDACTL)
+#define bfin_write_WPDACTL(val)              bfin_write32(WPDACTL,val)
+#define pWPDA0 ((volatile void **)WPDA0)
+#define bfin_read_WPDA0()                    bfin_read32(WPDA0)
+#define bfin_write_WPDA0(val)                bfin_write32(WPDA0,val)
+#define pWPDA1 ((volatile void **)WPDA1)
+#define bfin_read_WPDA1()                    bfin_read32(WPDA1)
+#define bfin_write_WPDA1(val)                bfin_write32(WPDA1,val)
+#define pWPDACNT0 ((volatile unsigned long *)WPDACNT0)
+#define bfin_read_WPDACNT0()                 bfin_read32(WPDACNT0)
+#define bfin_write_WPDACNT0(val)             bfin_write32(WPDACNT0,val)
+#define pWPDACNT1 ((volatile unsigned long *)WPDACNT1)
+#define bfin_read_WPDACNT1()                 bfin_read32(WPDACNT1)
+#define bfin_write_WPDACNT1(val)             bfin_write32(WPDACNT1,val)
+#define pWPSTAT ((volatile unsigned long *)WPSTAT)
+#define bfin_read_WPSTAT()                   bfin_read32(WPSTAT)
+#define bfin_write_WPSTAT(val)               bfin_write32(WPSTAT,val)
+
+/*Performance Monitor Registers*/
+#define pPFCTL ((volatile unsigned long *)PFCTL)
+#define bfin_read_PFCTL()                    bfin_read32(PFCTL)
+#define bfin_write_PFCTL(val)                bfin_write32(PFCTL,val)
+#define pPFCNTR0 ((volatile unsigned long *)PFCNTR0)
+#define bfin_read_PFCNTR0()                  bfin_read32(PFCNTR0)
+#define bfin_write_PFCNTR0(val)              bfin_write32(PFCNTR0,val)
+#define pPFCNTR1 ((volatile unsigned long *)PFCNTR1)
+#define bfin_read_PFCNTR1()                  bfin_read32(PFCNTR1)
+#define bfin_write_PFCNTR1(val)              bfin_write32(PFCNTR1,val)
+
+/*
+#define IPRIO                  0xFFE02110
+*/
+
+#if defined(CONFIG_BFIN_ALIVE_LED)
+#define pCONFIG_BFIN_ALIVE_LED_DPORT \
+       (volatile unsigned short *)CONFIG_BFIN_ALIVE_LED_DPORT
+#define pCONFIG_BFIN_ALIVE_LED_PORT \
+       (volatile unsigned short *)CONFIG_BFIN_ALIVE_LED_PORT
+#endif
+
+#if defined(CONFIG_BFIN_IDLE_LED)
+#define pCONFIG_BFIN_IDLE_LED_DPORT \
+       (volatile unsigned short *)CONFIG_BFIN_IDLE_LED_DPORT
+#define pCONFIG_BFIN_IDLE_LED_PORT \
+       (volatile unsigned short *)CONFIG_BFIN_IDLE_LED_PORT
+#endif
+
+#endif                         /* _CDEF_LPBLACKFIN_H */
diff --git a/include/asm-blackfin/mach-common/context.S b/include/asm-blackfin/mach-common/context.S
new file mode 100644 (file)
index 0000000..fd0ebe1
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * File:         arch/blackfin/kernel/context.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * Code to save processor context.
+ *  We even save the register which are preserved by a function call
+ *      - r4, r5, r6, r7, p3, p4, p5
+ */
+.macro save_context_with_interrupts
+       [--sp] = SYSCFG;
+
+       [--sp] = P0;    /*orig_p0*/
+       [--sp] = R0;    /*orig_r0*/
+
+       [--sp] = ( R7:0, P5:0 );
+       [--sp] = fp;
+       [--sp] = usp;
+
+       [--sp] = i0;
+       [--sp] = i1;
+       [--sp] = i2;
+       [--sp] = i3;
+
+       [--sp] = m0;
+       [--sp] = m1;
+       [--sp] = m2;
+       [--sp] = m3;
+
+       [--sp] = l0;
+       [--sp] = l1;
+       [--sp] = l2;
+       [--sp] = l3;
+
+       [--sp] = b0;
+       [--sp] = b1;
+       [--sp] = b2;
+       [--sp] = b3;
+       [--sp] = a0.x;
+       [--sp] = a0.w;
+       [--sp] = a1.x;
+       [--sp] = a1.w;
+
+       [--sp] = LC0;
+       [--sp] = LC1;
+       [--sp] = LT0;
+       [--sp] = LT1;
+       [--sp] = LB0;
+       [--sp] = LB1;
+
+       [--sp] = ASTAT;
+
+       [--sp] = r0;    /* Skip reserved */
+       [--sp] = RETS;
+       r0 = RETI;
+       [--sp] = r0;
+       [--sp] = RETX;
+       [--sp] = RETN;
+       [--sp] = RETE;
+       [--sp] = SEQSTAT;
+       [--sp] = r0;    /* Skip IPEND as well. */
+       /* Switch to other method of keeping interrupts disabled.  */
+#ifdef CONFIG_DEBUG_HWERR
+       r0 = 0x3f;
+       sti r0;
+#else
+       cli r0;
+#endif
+       [--sp] = RETI;  /*orig_pc*/
+       /* Clear all L registers.  */
+       r0 = 0 (x);
+       l0 = r0;
+       l1 = r0;
+       l2 = r0;
+       l3 = r0;
+.endm
+
+.macro save_context_syscall
+       [--sp] = SYSCFG;
+
+       [--sp] = P0;    /*orig_p0*/
+       [--sp] = R0;    /*orig_r0*/
+       [--sp] = ( R7:0, P5:0 );
+       [--sp] = fp;
+       [--sp] = usp;
+
+       [--sp] = i0;
+       [--sp] = i1;
+       [--sp] = i2;
+       [--sp] = i3;
+
+       [--sp] = m0;
+       [--sp] = m1;
+       [--sp] = m2;
+       [--sp] = m3;
+
+       [--sp] = l0;
+       [--sp] = l1;
+       [--sp] = l2;
+       [--sp] = l3;
+
+       [--sp] = b0;
+       [--sp] = b1;
+       [--sp] = b2;
+       [--sp] = b3;
+       [--sp] = a0.x;
+       [--sp] = a0.w;
+       [--sp] = a1.x;
+       [--sp] = a1.w;
+
+       [--sp] = LC0;
+       [--sp] = LC1;
+       [--sp] = LT0;
+       [--sp] = LT1;
+       [--sp] = LB0;
+       [--sp] = LB1;
+
+       [--sp] = ASTAT;
+
+       [--sp] = r0;    /* Skip reserved */
+       [--sp] = RETS;
+       r0 = RETI;
+       [--sp] = r0;
+       [--sp] = RETX;
+       [--sp] = RETN;
+       [--sp] = RETE;
+       [--sp] = SEQSTAT;
+       [--sp] = r0;    /* Skip IPEND as well. */
+       [--sp] = RETI;  /*orig_pc*/
+       /* Clear all L registers.  */
+       r0 = 0 (x);
+       l0 = r0;
+       l1 = r0;
+       l2 = r0;
+       l3 = r0;
+.endm
+
+.macro save_context_no_interrupts
+       [--sp] = SYSCFG;
+       [--sp] = P0;    /* orig_p0 */
+       [--sp] = R0;    /* orig_r0 */
+       [--sp] = ( R7:0, P5:0 );
+       [--sp] = fp;
+       [--sp] = usp;
+
+       [--sp] = i0;
+       [--sp] = i1;
+       [--sp] = i2;
+       [--sp] = i3;
+
+       [--sp] = m0;
+       [--sp] = m1;
+       [--sp] = m2;
+       [--sp] = m3;
+
+       [--sp] = l0;
+       [--sp] = l1;
+       [--sp] = l2;
+       [--sp] = l3;
+
+       [--sp] = b0;
+       [--sp] = b1;
+       [--sp] = b2;
+       [--sp] = b3;
+       [--sp] = a0.x;
+       [--sp] = a0.w;
+       [--sp] = a1.x;
+       [--sp] = a1.w;
+
+       [--sp] = LC0;
+       [--sp] = LC1;
+       [--sp] = LT0;
+       [--sp] = LT1;
+       [--sp] = LB0;
+       [--sp] = LB1;
+
+       [--sp] = ASTAT;
+
+#ifdef CONFIG_KGDB
+       fp     = 0(Z);
+       r1     = sp;
+       r1    += 60;
+       r1    += 60;
+       r1    += 60;
+       [--sp] = r1;
+#else
+       [--sp] = r0;    /* Skip reserved */
+#endif
+       [--sp] = RETS;
+       r0 = RETI;
+       [--sp] = r0;
+       [--sp] = RETX;
+       [--sp] = RETN;
+       [--sp] = RETE;
+       [--sp] = SEQSTAT;
+#ifdef CONFIG_KGDB
+       r1.l = lo(IPEND);
+       r1.h = hi(IPEND);
+       [--sp] = r1;
+#else
+       [--sp] = r0;    /* Skip IPEND as well. */
+#endif
+       [--sp] = r0;  /*orig_pc*/
+       /* Clear all L registers.  */
+       r0 = 0 (x);
+       l0 = r0;
+       l1 = r0;
+       l2 = r0;
+       l3 = r0;
+.endm
+
+.macro restore_context_no_interrupts
+       sp += 4;        /* Skip orig_pc */
+       sp += 4;        /* Skip IPEND */
+       SEQSTAT = [sp++];
+       RETE = [sp++];
+       RETN = [sp++];
+       RETX = [sp++];
+       r0 = [sp++];
+       RETI = r0;      /* Restore RETI indirectly when in exception */
+       RETS = [sp++];
+
+       sp += 4;        /* Skip Reserved */
+
+       ASTAT = [sp++];
+
+       LB1 = [sp++];
+       LB0 = [sp++];
+       LT1 = [sp++];
+       LT0 = [sp++];
+       LC1 = [sp++];
+       LC0 = [sp++];
+
+       a1.w = [sp++];
+       a1.x = [sp++];
+       a0.w = [sp++];
+       a0.x = [sp++];
+       b3 = [sp++];
+       b2 = [sp++];
+       b1 = [sp++];
+       b0 = [sp++];
+
+       l3 = [sp++];
+       l2 = [sp++];
+       l1 = [sp++];
+       l0 = [sp++];
+
+       m3 = [sp++];
+       m2 = [sp++];
+       m1 = [sp++];
+       m0 = [sp++];
+
+       i3 = [sp++];
+       i2 = [sp++];
+       i1 = [sp++];
+       i0 = [sp++];
+
+       sp += 4;
+       fp = [sp++];
+
+       ( R7 : 0, P5 : 0) = [ SP ++ ];
+       sp += 8;        /* Skip orig_r0/orig_p0 */
+       SYSCFG = [sp++];
+.endm
+
+.macro restore_context_with_interrupts
+       sp += 4;        /* Skip orig_pc */
+       sp += 4;        /* Skip IPEND */
+       SEQSTAT = [sp++];
+       RETE = [sp++];
+       RETN = [sp++];
+       RETX = [sp++];
+       RETI = [sp++];
+       RETS = [sp++];
+
+       p0.h = _irq_flags;
+       p0.l = _irq_flags;
+       r0 = [p0];
+       sti r0;
+
+       sp += 4;        /* Skip Reserved */
+
+       ASTAT = [sp++];
+
+       LB1 = [sp++];
+       LB0 = [sp++];
+       LT1 = [sp++];
+       LT0 = [sp++];
+       LC1 = [sp++];
+       LC0 = [sp++];
+
+       a1.w = [sp++];
+       a1.x = [sp++];
+       a0.w = [sp++];
+       a0.x = [sp++];
+       b3 = [sp++];
+       b2 = [sp++];
+       b1 = [sp++];
+       b0 = [sp++];
+
+       l3 = [sp++];
+       l2 = [sp++];
+       l1 = [sp++];
+       l0 = [sp++];
+
+       m3 = [sp++];
+       m2 = [sp++];
+       m1 = [sp++];
+       m0 = [sp++];
+
+       i3 = [sp++];
+       i2 = [sp++];
+       i1 = [sp++];
+       i0 = [sp++];
+
+       sp += 4;
+       fp = [sp++];
+
+       ( R7 : 0, P5 : 0) = [ SP ++ ];
+       sp += 8;        /* Skip orig_r0/orig_p0 */
+       csync;
+       SYSCFG = [sp++];
+       csync;
+.endm
+
diff --git a/include/asm-blackfin/mach-common/def_LPBlackfin.h b/include/asm-blackfin/mach-common/def_LPBlackfin.h
new file mode 100644 (file)
index 0000000..7610352
--- /dev/null
@@ -0,0 +1,691 @@
+ /*
+  * File:        include/asm-blackfin/mach-common/def_LPBlackfin.h
+  * Based on:
+  * Author:      unknown
+  *              COPYRIGHT 2005 Analog Devices
+  * Created:     ?
+  * Description:
+  *
+  * Modified:
+  *
+  * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; see the file COPYING.
+  * If not, write to the Free Software Foundation,
+  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+
+/* LP Blackfin CORE REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF532/33 */
+
+#ifndef _DEF_LPBLACKFIN_H
+#define _DEF_LPBLACKFIN_H
+
+#include <asm/mach/anomaly.h>
+
+/*#if !defined(__ADSPLPBLACKFIN__)
+#warning def_LPBlackfin.h should only be included for 532 compatible chips.
+#endif
+*/
+
+#define MK_BMSK_(x) (1<<x)
+
+#if defined(ANOMALY_05000198)
+
+#define bfin_read16(addr) ({ unsigned __v; \
+                       __asm__ __volatile__ ("NOP;\n\t"\
+                                                               "%0 = w[%1] (z);\n\t"\
+  : "=d"(__v) : "a"(addr)); (unsigned short)__v; })
+
+#define bfin_read32(addr) ({ unsigned __v; \
+                      __asm__ __volatile__ ("NOP;\n\t"\
+                                            "%0 = [%1];\n\t"\
+  : "=d"(__v) : "a"(addr)); __v; })
+
+#define bfin_write16(addr,val) ({\
+                      __asm__ __volatile__ ("NOP;\n\t"\
+                                            "w[%0] = %1;\n\t"\
+  : : "a"(addr) , "d"(val) : "memory");})
+
+#define bfin_write32(addr,val) ({\
+                      __asm__ __volatile__ ("NOP;\n\t"\
+                                            "[%0] = %1;\n\t"\
+  : : "a"(addr) , "d"(val) : "memory");})
+
+#else
+
+#define bfin_read16(addr) ({ unsigned __v; \
+                       __asm__ __volatile__ (\
+                                                               "%0 = w[%1] (z);\n\t"\
+  : "=d"(__v) : "a"(addr)); (unsigned short)__v; })
+
+#define bfin_read32(addr) ({ unsigned __v; \
+                      __asm__ __volatile__ (\
+                                            "%0 = [%1];\n\t"\
+  : "=d"(__v) : "a"(addr)); __v; })
+
+#define bfin_write16(addr,val) ({\
+                      __asm__ __volatile__ (\
+                                            "w[%0] = %1;\n\t"\
+  : : "a"(addr) , "d"(val) : "memory");})
+
+#define bfin_write32(addr,val) ({\
+                      __asm__ __volatile__ (\
+                                            "[%0] = %1;\n\t"\
+  : : "a"(addr) , "d"(val) : "memory");})
+
+#endif
+
+/**************************************************
+ * System Register Bits
+ **************************************************/
+
+/**************************************************
+ * ASTAT register
+ **************************************************/
+
+/* definitions of ASTAT bit positions*/
+
+/*Result of last ALU0 or shifter operation is zero*/
+#define ASTAT_AZ_P         0x00000000
+/*Result of last ALU0 or shifter operation is negative*/
+#define ASTAT_AN_P         0x00000001
+/*Condition Code, used for holding comparison results*/
+#define ASTAT_CC_P         0x00000005
+/*Quotient Bit*/
+#define ASTAT_AQ_P         0x00000006
+/*Rounding mode, set for biased, clear for unbiased*/
+#define ASTAT_RND_MOD_P    0x00000008
+/*Result of last ALU0 operation generated a carry*/
+#define ASTAT_AC0_P        0x0000000C
+/*Result of last ALU0 operation generated a carry*/
+#define ASTAT_AC0_COPY_P   0x00000002
+/*Result of last ALU1 operation generated a carry*/
+#define ASTAT_AC1_P        0x0000000D
+/*Result of last ALU0 or MAC0 operation overflowed, sticky for MAC*/
+#define ASTAT_AV0_P        0x00000010
+/*Sticky version of ASTAT_AV0 */
+#define ASTAT_AV0S_P       0x00000011
+/*Result of last MAC1 operation overflowed, sticky for MAC*/
+#define ASTAT_AV1_P        0x00000012
+/*Sticky version of ASTAT_AV1 */
+#define ASTAT_AV1S_P       0x00000013
+/*Result of last ALU0 or MAC0 operation overflowed*/
+#define ASTAT_V_P          0x00000018
+/*Result of last ALU0 or MAC0 operation overflowed*/
+#define ASTAT_V_COPY_P     0x00000003
+/*Sticky version of ASTAT_V*/
+#define ASTAT_VS_P         0x00000019
+
+/* Masks */
+
+/*Result of last ALU0 or shifter operation is zero*/
+#define ASTAT_AZ           MK_BMSK_(ASTAT_AZ_P)
+/*Result of last ALU0 or shifter operation is negative*/
+#define ASTAT_AN           MK_BMSK_(ASTAT_AN_P)
+/*Result of last ALU0 operation generated a carry*/
+#define ASTAT_AC0          MK_BMSK_(ASTAT_AC0_P)
+/*Result of last ALU0 operation generated a carry*/
+#define ASTAT_AC0_COPY     MK_BMSK_(ASTAT_AC0_COPY_P)
+/*Result of last ALU0 operation generated a carry*/
+#define ASTAT_AC1          MK_BMSK_(ASTAT_AC1_P)
+/*Result of last ALU0 or MAC0 operation overflowed, sticky for MAC*/
+#define ASTAT_AV0          MK_BMSK_(ASTAT_AV0_P)
+/*Result of last MAC1 operation overflowed, sticky for MAC*/
+#define ASTAT_AV1          MK_BMSK_(ASTAT_AV1_P)
+/*Condition Code, used for holding comparison results*/
+#define ASTAT_CC           MK_BMSK_(ASTAT_CC_P)
+/*Quotient Bit*/
+#define ASTAT_AQ           MK_BMSK_(ASTAT_AQ_P)
+/*Rounding mode, set for biased, clear for unbiased*/
+#define ASTAT_RND_MOD      MK_BMSK_(ASTAT_RND_MOD_P)
+/*Overflow Bit*/
+#define ASTAT_V            MK_BMSK_(ASTAT_V_P)
+/*Overflow Bit*/
+#define ASTAT_V_COPY       MK_BMSK_(ASTAT_V_COPY_P)
+
+/**************************************************
+ *   SEQSTAT register
+ **************************************************/
+
+/* Bit Positions  */
+#define SEQSTAT_EXCAUSE0_P      0x00000000     /* Last exception cause bit 0 */
+#define SEQSTAT_EXCAUSE1_P      0x00000001     /* Last exception cause bit 1 */
+#define SEQSTAT_EXCAUSE2_P      0x00000002     /* Last exception cause bit 2 */
+#define SEQSTAT_EXCAUSE3_P      0x00000003     /* Last exception cause bit 3 */
+#define SEQSTAT_EXCAUSE4_P      0x00000004     /* Last exception cause bit 4 */
+#define SEQSTAT_EXCAUSE5_P      0x00000005     /* Last exception cause bit 5 */
+#define SEQSTAT_IDLE_REQ_P      0x0000000C     /* Pending idle mode request,
+                                                * set by IDLE instruction.
+                                                */
+#define SEQSTAT_SFTRESET_P      0x0000000D     /* Indicates whether the last
+                                                * reset was a software reset
+                                                * (=1)
+                                                */
+#define SEQSTAT_HWERRCAUSE0_P   0x0000000E     /* Last hw error cause bit 0 */
+#define SEQSTAT_HWERRCAUSE1_P   0x0000000F     /* Last hw error cause bit 1 */
+#define SEQSTAT_HWERRCAUSE2_P   0x00000010     /* Last hw error cause bit 2 */
+#define SEQSTAT_HWERRCAUSE3_P   0x00000011     /* Last hw error cause bit 3 */
+#define SEQSTAT_HWERRCAUSE4_P   0x00000012     /* Last hw error cause bit 4 */
+/* Masks */
+/* Exception cause */
+#define SEQSTAT_EXCAUSE        (MK_BMSK_(SEQSTAT_EXCAUSE0_P) | \
+                                MK_BMSK_(SEQSTAT_EXCAUSE1_P) | \
+                                MK_BMSK_(SEQSTAT_EXCAUSE2_P) | \
+                                MK_BMSK_(SEQSTAT_EXCAUSE3_P) | \
+                                MK_BMSK_(SEQSTAT_EXCAUSE4_P) | \
+                                MK_BMSK_(SEQSTAT_EXCAUSE5_P) | \
+                                0)
+
+/* Indicates whether the last reset was a software reset (=1) */
+#define SEQSTAT_SFTRESET       (MK_BMSK_(SEQSTAT_SFTRESET_P))
+
+/* Last hw error cause */
+#define SEQSTAT_HWERRCAUSE     (MK_BMSK_(SEQSTAT_HWERRCAUSE0_P) | \
+                                MK_BMSK_(SEQSTAT_HWERRCAUSE1_P) | \
+                                MK_BMSK_(SEQSTAT_HWERRCAUSE2_P) | \
+                                MK_BMSK_(SEQSTAT_HWERRCAUSE3_P) | \
+                                MK_BMSK_(SEQSTAT_HWERRCAUSE4_P) | \
+                                0)
+
+/* Translate bits to something useful */
+
+/* Last hw error cause */
+#define SEQSTAT_HWERRCAUSE_SHIFT         (14)
+#define SEQSTAT_HWERRCAUSE_SYSTEM_MMR    (0x02 << SEQSTAT_HWERRCAUSE_SHIFT)
+#define SEQSTAT_HWERRCAUSE_EXTERN_ADDR   (0x03 << SEQSTAT_HWERRCAUSE_SHIFT)
+#define SEQSTAT_HWERRCAUSE_PERF_FLOW     (0x12 << SEQSTAT_HWERRCAUSE_SHIFT)
+#define SEQSTAT_HWERRCAUSE_RAISE_5       (0x18 << SEQSTAT_HWERRCAUSE_SHIFT)
+
+/**************************************************
+ *   SYSCFG register
+ **************************************************/
+
+/* Bit Positions */
+#define SYSCFG_SSSTEP_P     0x00000000 /* Supervisor single step, when
+                                        * set it forces an exception
+                                        * for each instruction executed
+                                        */
+#define SYSCFG_CCEN_P       0x00000001 /* Enable cycle counter (=1) */
+#define SYSCFG_SNEN_P       0x00000002 /* Self nesting Interrupt Enable */
+
+/* Masks */
+
+/* Supervisor single step, when set it forces an exception for each
+ *instruction executed
+ */
+#define SYSCFG_SSSTEP         MK_BMSK_(SYSCFG_SSSTEP_P )
+/* Enable cycle counter (=1) */
+#define SYSCFG_CCEN           MK_BMSK_(SYSCFG_CCEN_P )
+/* Self Nesting Interrupt Enable */
+#define SYSCFG_SNEN           MK_BMSK_(SYSCFG_SNEN_P)
+/* Backward-compatibility for typos in prior releases */
+#define SYSCFG_SSSSTEP         SYSCFG_SSSTEP
+#define SYSCFG_CCCEN           SYSCFG_CCEN
+
+/****************************************************
+ * Core MMR Register Map
+ ****************************************************/
+
+/* Data Cache & SRAM Memory  (0xFFE00000 - 0xFFE00404) */
+
+#define SRAM_BASE_ADDRESS  0xFFE00000  /* SRAM Base Address Register */
+#define DMEM_CONTROL       0xFFE00004  /* Data memory control */
+#define DCPLB_STATUS       0xFFE00008  /* Data Cache Programmable Look-Aside
+                                        * Buffer Status
+                                        */
+#define DCPLB_FAULT_STATUS 0xFFE00008  /* "" (older define) */
+#define DCPLB_FAULT_ADDR   0xFFE0000C  /* Data Cache Programmable Look-Aside
+                                        * Buffer Fault Address
+                                        */
+#define DCPLB_ADDR0        0xFFE00100  /* Data Cache Protection Lookaside
+                                        * Buffer 0
+                                        */
+#define DCPLB_ADDR1        0xFFE00104  /* Data Cache Protection Lookaside
+                                        * Buffer 1
+                                        */
+#define DCPLB_ADDR2        0xFFE00108  /* Data Cache Protection Lookaside
+                                        * Buffer 2
+                                        */
+#define DCPLB_ADDR3        0xFFE0010C  /* Data Cacheability Protection
+                                        * Lookaside Buffer 3
+                                        */
+#define DCPLB_ADDR4        0xFFE00110  /* Data Cacheability Protection
+                                        * Lookaside Buffer 4
+                                        */
+#define DCPLB_ADDR5        0xFFE00114  /* Data Cacheability Protection
+                                        * Lookaside Buffer 5
+                                        */
+#define DCPLB_ADDR6        0xFFE00118  /* Data Cacheability Protection
+                                        * Lookaside Buffer 6
+                                        */
+#define DCPLB_ADDR7        0xFFE0011C  /* Data Cacheability Protection
+                                        * Lookaside Buffer 7
+                                        */
+#define DCPLB_ADDR8        0xFFE00120  /* Data Cacheability Protection
+                                        * Lookaside Buffer 8
+                                        */
+#define DCPLB_ADDR9        0xFFE00124  /* Data Cacheability Protection
+                                        * Lookaside Buffer 9
+                                        */
+#define DCPLB_ADDR10       0xFFE00128  /* Data Cacheability Protection
+                                        * Lookaside Buffer 10
+                                        */
+#define DCPLB_ADDR11       0xFFE0012C  /* Data Cacheability Protection
+                                        * Lookaside Buffer 11
+                                        */
+#define DCPLB_ADDR12       0xFFE00130  /* Data Cacheability Protection
+                                        * Lookaside Buffer 12
+                                        */
+#define DCPLB_ADDR13       0xFFE00134  /* Data Cacheability Protection
+                                        * Lookaside Buffer 13
+                                        */
+#define DCPLB_ADDR14       0xFFE00138  /* Data Cacheability Protection
+                                        * Lookaside Buffer 14
+                                        */
+#define DCPLB_ADDR15       0xFFE0013C  /* Data Cacheability Protection
+                                        * Lookaside Buffer 15
+                                        */
+#define DCPLB_DATA0        0xFFE00200  /* Data Cache 0 Status */
+#define DCPLB_DATA1        0xFFE00204  /* Data Cache 1 Status */
+#define DCPLB_DATA2        0xFFE00208  /* Data Cache 2 Status */
+#define DCPLB_DATA3        0xFFE0020C  /* Data Cache 3 Status */
+#define DCPLB_DATA4        0xFFE00210  /* Data Cache 4 Status */
+#define DCPLB_DATA5        0xFFE00214  /* Data Cache 5 Status */
+#define DCPLB_DATA6        0xFFE00218  /* Data Cache 6 Status */
+#define DCPLB_DATA7        0xFFE0021C  /* Data Cache 7 Status */
+#define DCPLB_DATA8        0xFFE00220  /* Data Cache 8 Status */
+#define DCPLB_DATA9        0xFFE00224  /* Data Cache 9 Status */
+#define DCPLB_DATA10       0xFFE00228  /* Data Cache 10 Status */
+#define DCPLB_DATA11       0xFFE0022C  /* Data Cache 11 Status */
+#define DCPLB_DATA12       0xFFE00230  /* Data Cache 12 Status */
+#define DCPLB_DATA13       0xFFE00234  /* Data Cache 13 Status */
+#define DCPLB_DATA14       0xFFE00238  /* Data Cache 14 Status */
+#define DCPLB_DATA15       0xFFE0023C  /* Data Cache 15 Status */
+#define DCPLB_DATA16       0xFFE00240  /* Extra Dummy entry */
+
+#define DTEST_COMMAND      0xFFE00300  /* Data Test Command Register */
+#define DTEST_DATA0        0xFFE00400  /* Data Test Data Register */
+#define DTEST_DATA1        0xFFE00404  /* Data Test Data Register */
+
+/* Instruction Cache & SRAM Memory  (0xFFE01004 - 0xFFE01404) */
+
+#define IMEM_CONTROL       0xFFE01004  /* Instruction Memory Control */
+#define ICPLB_STATUS       0xFFE01008  /* Instruction Cache miss status */
+#define CODE_FAULT_STATUS  0xFFE01008  /* "" (older define) */
+#define ICPLB_FAULT_ADDR   0xFFE0100C  /* Instruction Cache miss address */
+#define CODE_FAULT_ADDR    0xFFE0100C  /* "" (older define) */
+#define ICPLB_ADDR0        0xFFE01100  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 0
+                                        */
+#define ICPLB_ADDR1        0xFFE01104  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 1
+                                        */
+#define ICPLB_ADDR2        0xFFE01108  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 2
+                                        */
+#define ICPLB_ADDR3        0xFFE0110C  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 3
+                                        */
+#define ICPLB_ADDR4        0xFFE01110  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 4
+                                        */
+#define ICPLB_ADDR5        0xFFE01114  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 5
+                                        */
+#define ICPLB_ADDR6        0xFFE01118  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 6
+                                        */
+#define ICPLB_ADDR7        0xFFE0111C  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 7
+                                        */
+#define ICPLB_ADDR8        0xFFE01120  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 8
+                                        */
+#define ICPLB_ADDR9        0xFFE01124  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 9
+                                        */
+#define ICPLB_ADDR10       0xFFE01128  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 10
+                                        */
+#define ICPLB_ADDR11       0xFFE0112C  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 11
+                                        */
+#define ICPLB_ADDR12       0xFFE01130  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 12
+                                        */
+#define ICPLB_ADDR13       0xFFE01134  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 13
+                                        */
+#define ICPLB_ADDR14       0xFFE01138  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 14
+                                        */
+#define ICPLB_ADDR15       0xFFE0113C  /* Instruction Cacheability
+                                        * Protection Lookaside Buffer 15
+                                        */
+#define ICPLB_DATA0        0xFFE01200  /* Instruction Cache 0 Status */
+#define ICPLB_DATA1        0xFFE01204  /* Instruction Cache 1 Status */
+#define ICPLB_DATA2        0xFFE01208  /* Instruction Cache 2 Status */
+#define ICPLB_DATA3        0xFFE0120C  /* Instruction Cache 3 Status */
+#define ICPLB_DATA4        0xFFE01210  /* Instruction Cache 4 Status */
+#define ICPLB_DATA5        0xFFE01214  /* Instruction Cache 5 Status */
+#define ICPLB_DATA6        0xFFE01218  /* Instruction Cache 6 Status */
+#define ICPLB_DATA7        0xFFE0121C  /* Instruction Cache 7 Status */
+#define ICPLB_DATA8        0xFFE01220  /* Instruction Cache 8 Status */
+#define ICPLB_DATA9        0xFFE01224  /* Instruction Cache 9 Status */
+#define ICPLB_DATA10       0xFFE01228  /* Instruction Cache 10 Status */
+#define ICPLB_DATA11       0xFFE0122C  /* Instruction Cache 11 Status */
+#define ICPLB_DATA12       0xFFE01230  /* Instruction Cache 12 Status */
+#define ICPLB_DATA13       0xFFE01234  /* Instruction Cache 13 Status */
+#define ICPLB_DATA14       0xFFE01238  /* Instruction Cache 14 Status */
+#define ICPLB_DATA15       0xFFE0123C  /* Instruction Cache 15 Status */
+#define ITEST_COMMAND      0xFFE01300  /* Instruction Test Command Register */
+#define ITEST_DATA0        0xFFE01400  /* Instruction Test Data Register */
+#define ITEST_DATA1        0xFFE01404  /* Instruction Test Data Register */
+
+/* Event/Interrupt Controller Registers   (0xFFE02000 - 0xFFE02110) */
+
+#define EVT0               0xFFE02000  /* Event Vector 0 ESR Address */
+#define EVT1               0xFFE02004  /* Event Vector 1 ESR Address */
+#define EVT2               0xFFE02008  /* Event Vector 2 ESR Address */
+#define EVT3               0xFFE0200C  /* Event Vector 3 ESR Address */
+#define EVT4               0xFFE02010  /* Event Vector 4 ESR Address */
+#define EVT5               0xFFE02014  /* Event Vector 5 ESR Address */
+#define EVT6               0xFFE02018  /* Event Vector 6 ESR Address */
+#define EVT7               0xFFE0201C  /* Event Vector 7 ESR Address */
+#define EVT8               0xFFE02020  /* Event Vector 8 ESR Address */
+#define EVT9               0xFFE02024  /* Event Vector 9 ESR Address */
+#define EVT10              0xFFE02028  /* Event Vector 10 ESR Address */
+#define EVT11              0xFFE0202C  /* Event Vector 11 ESR Address */
+#define EVT12              0xFFE02030  /* Event Vector 12 ESR Address */
+#define EVT13              0xFFE02034  /* Event Vector 13 ESR Address */
+#define EVT14              0xFFE02038  /* Event Vector 14 ESR Address */
+#define EVT15              0xFFE0203C  /* Event Vector 15 ESR Address */
+#define IMASK              0xFFE02104  /* Interrupt Mask Register */
+#define IPEND              0xFFE02108  /* Interrupt Pending Register */
+#define ILAT               0xFFE0210C  /* Interrupt Latch Register */
+#define IPRIO              0xFFE02110  /* Core Interrupt Priority Register */
+
+/* Core Timer Registers     (0xFFE03000 - 0xFFE0300C) */
+
+#define TCNTL              0xFFE03000  /* Core Timer Control Register */
+#define TPERIOD            0xFFE03004  /* Core Timer Period Register */
+#define TSCALE             0xFFE03008  /* Core Timer Scale Register */
+#define TCOUNT             0xFFE0300C  /* Core Timer Count Register */
+
+/* Debug/MP/Emulation Registers     (0xFFE05000 - 0xFFE05008) */
+#define DSPID              0xFFE05000  /* DSP Processor ID Register for
+                                        * MP implementations
+                                        */
+
+#define DBGSTAT            0xFFE05008  /* Debug Status Register */
+
+/* Trace Buffer Registers     (0xFFE06000 - 0xFFE06100) */
+
+#define TBUFCTL            0xFFE06000  /* Trace Buffer Control Register */
+#define TBUFSTAT           0xFFE06004  /* Trace Buffer Status Register */
+#define TBUF               0xFFE06100  /* Trace Buffer */
+
+/* Watchpoint Control Registers (0xFFE07000 - 0xFFE07200) */
+
+/* Watchpoint Instruction Address Control Register */
+#define WPIACTL            0xFFE07000
+/* Watchpoint Instruction Address Register 0 */
+#define WPIA0              0xFFE07040
+/* Watchpoint Instruction Address Register 1 */
+#define WPIA1              0xFFE07044
+/* Watchpoint Instruction Address Register 2 */
+#define WPIA2              0xFFE07048
+/* Watchpoint Instruction Address Register 3 */
+#define WPIA3              0xFFE0704C
+/* Watchpoint Instruction Address Register 4 */
+#define WPIA4              0xFFE07050
+/* Watchpoint Instruction Address Register 5 */
+#define WPIA5              0xFFE07054
+/* Watchpoint Instruction Address Count Register 0 */
+#define WPIACNT0           0xFFE07080
+/* Watchpoint Instruction Address Count Register 1 */
+#define WPIACNT1           0xFFE07084
+/* Watchpoint Instruction Address Count Register 2 */
+#define WPIACNT2           0xFFE07088
+/* Watchpoint Instruction Address Count Register 3 */
+#define WPIACNT3           0xFFE0708C
+/* Watchpoint Instruction Address Count Register 4 */
+#define WPIACNT4           0xFFE07090
+/* Watchpoint Instruction Address Count Register 5 */
+#define WPIACNT5           0xFFE07094
+/* Watchpoint Data Address Control Register */
+#define WPDACTL            0xFFE07100
+/* Watchpoint Data Address Register 0 */
+#define WPDA0              0xFFE07140
+/* Watchpoint Data Address Register 1 */
+#define WPDA1              0xFFE07144
+/* Watchpoint Data Address Count Value Register 0 */
+#define WPDACNT0           0xFFE07180
+/* Watchpoint Data Address Count Value Register 1 */
+#define WPDACNT1           0xFFE07184
+/* Watchpoint Status Register */
+#define WPSTAT             0xFFE07200
+
+/* Performance Monitor Registers    (0xFFE08000 - 0xFFE08104) */
+
+/* Performance Monitor Control Register */
+#define PFCTL              0xFFE08000
+/* Performance Monitor Counter Register 0 */
+#define PFCNTR0            0xFFE08100
+/* Performance Monitor Counter Register 1 */
+#define PFCNTR1            0xFFE08104
+
+/****************************************************
+ * Core MMR Register Bits
+ ****************************************************/
+
+/**************************************************
+ * EVT registers (ILAT, IMASK, and IPEND).
+ **************************************************/
+
+/* Bit Positions */
+#define EVT_EMU_P        0x00000000    /* Emulator interrupt bit position */
+#define EVT_RST_P        0x00000001    /* Reset interrupt bit position */
+#define EVT_NMI_P        0x00000002    /* Non Maskable interrupt bit position */
+#define EVT_EVX_P        0x00000003    /* Exception bit position */
+#define EVT_IRPTEN_P     0x00000004    /* Global interrupt enable bit position */
+#define EVT_IVHW_P       0x00000005    /* Hardware Error interrupt bit position */
+#define EVT_IVTMR_P      0x00000006    /* Timer interrupt bit position */
+#define EVT_IVG7_P       0x00000007    /* IVG7 interrupt bit position */
+#define EVT_IVG8_P       0x00000008    /* IVG8 interrupt bit position */
+#define EVT_IVG9_P       0x00000009    /* IVG9 interrupt bit position */
+#define EVT_IVG10_P      0x0000000a    /* IVG10 interrupt bit position */
+#define EVT_IVG11_P      0x0000000b    /* IVG11 interrupt bit position */
+#define EVT_IVG12_P      0x0000000c    /* IVG12 interrupt bit position */
+#define EVT_IVG13_P      0x0000000d    /* IVG13 interrupt bit position */
+#define EVT_IVG14_P      0x0000000e    /* IVG14 interrupt bit position */
+#define EVT_IVG15_P      0x0000000f    /* IVG15 interrupt bit position */
+
+/* Masks */
+#define EVT_EMU       MK_BMSK_(EVT_EMU_P   )   /* Emulator interrupt mask */
+#define EVT_RST       MK_BMSK_(EVT_RST_P   )   /* Reset interrupt mask */
+#define EVT_NMI       MK_BMSK_(EVT_NMI_P   )   /* Non Maskable interrupt mask */
+#define EVT_EVX       MK_BMSK_(EVT_EVX_P   )   /* Exception mask */
+#define EVT_IRPTEN    MK_BMSK_(EVT_IRPTEN_P)   /* Global interrupt enable mask */
+#define EVT_IVHW      MK_BMSK_(EVT_IVHW_P  )   /* Hardware Error interrupt mask */
+#define EVT_IVTMR     MK_BMSK_(EVT_IVTMR_P )   /* Timer interrupt mask */
+#define EVT_IVG7      MK_BMSK_(EVT_IVG7_P  )   /* IVG7 interrupt mask */
+#define EVT_IVG8      MK_BMSK_(EVT_IVG8_P  )   /* IVG8 interrupt mask */
+#define EVT_IVG9      MK_BMSK_(EVT_IVG9_P  )   /* IVG9 interrupt mask */
+#define EVT_IVG10     MK_BMSK_(EVT_IVG10_P )   /* IVG10 interrupt mask */
+#define EVT_IVG11     MK_BMSK_(EVT_IVG11_P )   /* IVG11 interrupt mask */
+#define EVT_IVG12     MK_BMSK_(EVT_IVG12_P )   /* IVG12 interrupt mask */
+#define EVT_IVG13     MK_BMSK_(EVT_IVG13_P )   /* IVG13 interrupt mask */
+#define EVT_IVG14     MK_BMSK_(EVT_IVG14_P )   /* IVG14 interrupt mask */
+#define EVT_IVG15     MK_BMSK_(EVT_IVG15_P )   /* IVG15 interrupt mask */
+
+/**************************************************
+ *  DMEM_CONTROL Register
+ **************************************************/
+/* Bit Positions */
+#define ENDM_P                 0x00    /* (doesn't really exist) Enable
+                                        *Data Memory L1
+                                        */
+#define DMCTL_ENDM_P           ENDM_P  /* "" (older define) */
+
+#define ENDCPLB_P              0x01    /* Enable DCPLBS */
+#define DMCTL_ENDCPLB_P                ENDCPLB_P       /* "" (older define) */
+#define DMC0_P                 0x02    /* L1 Data Memory Configure bit 0 */
+#define DMCTL_DMC0_P           DMC0_P  /* "" (older define) */
+#define DMC1_P                 0x03    /* L1 Data Memory Configure bit 1 */
+#define DMCTL_DMC1_P           DMC1_P  /* "" (older define) */
+#define DCBS_P                 0x04    /* L1 Data Cache Bank Select */
+#define PORT_PREF0_P           0x12    /* DAG0 Port Preference */
+#define PORT_PREF1_P           0x13    /* DAG1 Port Preference */
+
+/* Masks */
+#define ENDM               0x00000001  /* (doesn't really exist) Enable
+                                        * Data Memory L1
+                                        */
+#define ENDCPLB            0x00000002  /* Enable DCPLB */
+#define ASRAM_BSRAM        0x00000000
+#define ACACHE_BSRAM       0x00000008
+#define ACACHE_BCACHE      0x0000000C
+#define DCBS               0x00000010  /*  L1 Data Cache Bank Select */
+#define PORT_PREF0        0x00001000   /* DAG0 Port Preference */
+#define PORT_PREF1        0x00002000   /* DAG1 Port Preference */
+
+/* IMEM_CONTROL Register */
+/* Bit Positions */
+#define ENIM_P                 0x00    /* Enable L1 Code Memory  */
+#define IMCTL_ENIM_P            0x00   /* "" (older define) */
+#define ENICPLB_P              0x01    /* Enable ICPLB */
+#define IMCTL_ENICPLB_P                0x01    /* "" (older define) */
+#define IMC_P                  0x02    /* Enable  */
+#define IMCTL_IMC_P            0x02    /* Configure L1 code memory as
+                                        * cache (0=SRAM)
+                                        */
+#define ILOC0_P                        0x03    /* Lock Way 0 */
+#define ILOC1_P                        0x04    /* Lock Way 1 */
+#define ILOC2_P                        0x05    /* Lock Way 2 */
+#define ILOC3_P                        0x06    /* Lock Way 3 */
+#define LRUPRIORST_P           0x0D    /* Least Recently Used Replacement
+                                        * Priority
+                                        */
+/* Masks */
+#define ENIM               0x00000001  /* Enable L1 Code Memory */
+#define ENICPLB            0x00000002  /* Enable ICPLB */
+#define IMC                0x00000004  /* Configure L1 code memory as
+                                        * cache (0=SRAM)
+                                        */
+#define ILOC0             0x00000008   /* Lock Way 0 */
+#define ILOC1             0x00000010   /* Lock Way 1 */
+#define ILOC2             0x00000020   /* Lock Way 2 */
+#define ILOC3             0x00000040   /* Lock Way 3 */
+#define LRUPRIORST        0x00002000   /* Least Recently Used Replacement
+                                        * Priority
+                                        */
+
+/* TCNTL Masks */
+#define TMPWR              0x00000001  /* Timer Low Power Control,
+                                        * 0=low power mode, 1=active state
+                                        */
+#define TMREN              0x00000002  /* Timer enable, 0=disable, 1=enable */
+#define TAUTORLD           0x00000004  /* Timer auto reload */
+#define TINT               0x00000008  /* Timer generated interrupt 0=no
+                                        * interrupt has been generated,
+                                        * 1=interrupt has been generated
+                                        * (sticky)
+                                        */
+
+/* DCPLB_DATA and ICPLB_DATA Registers */
+/* Bit Positions */
+#define CPLB_VALID_P       0x00000000  /* 0=invalid entry, 1=valid entry */
+#define CPLB_LOCK_P        0x00000001  /* 0=entry may be replaced, 1=entry
+                                        * locked
+                                        */
+#define CPLB_USER_RD_P     0x00000002  /* 0=no read access, 1=read access
+                                        * allowed (user mode)
+                                        */
+/* Masks */
+#define CPLB_VALID         0x00000001  /* 0=invalid entry, 1=valid entry */
+#define CPLB_LOCK          0x00000002  /* 0=entry may be replaced, 1=entry
+                                        * locked
+                                        */
+#define CPLB_USER_RD       0x00000004  /* 0=no read access, 1=read access
+                                        * allowed (user mode)
+                                        */
+#define PAGE_SIZE_1KB      0x00000000  /* 1 KB page size */
+#define PAGE_SIZE_4KB      0x00010000  /* 4 KB page size */
+#define PAGE_SIZE_1MB      0x00020000  /* 1 MB page size */
+#define PAGE_SIZE_4MB      0x00030000  /* 4 MB page size */
+#define CPLB_L1SRAM        0x00000020  /* 0=SRAM mapped in L1, 0=SRAM not
+                                        * mapped to L1
+                                        */
+#define CPLB_PORTPRIO     0x00000200   /* 0=low priority port, 1= high
+                                        * priority port
+                                        */
+#define CPLB_L1_CHBL       0x00001000  /* 0=non-cacheable in L1, 1=cacheable
+                                        * in L1
+                                        */
+/* ICPLB_DATA only */
+#define CPLB_LRUPRIO      0x00000100   /* 0=can be replaced by any line,
+                                        * 1=priority for non-replacement
+                                        */
+/* DCPLB_DATA only */
+#define CPLB_USER_WR       0x00000008  /* 0=no write access, 0=write
+                                        * access allowed (user mode)
+                                        */
+#define CPLB_SUPV_WR       0x00000010  /* 0=no write access, 0=write
+                                        * access allowed (supervisor mode)
+                                        */
+#define CPLB_DIRTY         0x00000080  /* 1=dirty, 0=clean */
+#define CPLB_L1_AOW       0x00008000   /* 0=do not allocate cache lines on
+                                        * write-through writes,
+                                        * 1= allocate cache lines on
+                                        * write-through writes.
+                                        */
+#define CPLB_WT            0x00004000  /* 0=write-back, 1=write-through */
+
+/* TBUFCTL Masks */
+#define TBUFPWR            0x0001
+#define TBUFEN             0x0002
+#define TBUFOVF            0x0004
+#define TBUFCMPLP_SINGLE   0x0008
+#define TBUFCMPLP_DOUBLE   0x0010
+#define TBUFCMPLP          (TBUFCMPLP_SINGLE | TBUFCMPLP_DOUBLE)
+
+/* TBUFSTAT Masks */
+#define TBUFCNT            0x001F
+
+/* ITEST_COMMAND and DTEST_COMMAND Registers */
+/* Masks */
+#define TEST_READ         0x00000000   /* Read Access */
+#define TEST_WRITE        0x00000002   /* Write Access */
+#define TEST_TAG          0x00000000   /* Access TAG */
+#define TEST_DATA         0x00000004   /* Access DATA */
+#define TEST_DW0          0x00000000   /* Select Double Word 0 */
+#define TEST_DW1          0x00000008   /* Select Double Word 1 */
+#define TEST_DW2          0x00000010   /* Select Double Word 2 */
+#define TEST_DW3          0x00000018   /* Select Double Word 3 */
+#define TEST_MB0          0x00000000   /* Select Mini-Bank 0 */
+#define TEST_MB1          0x00010000   /* Select Mini-Bank 1 */
+#define TEST_MB2          0x00020000   /* Select Mini-Bank 2 */
+#define TEST_MB3          0x00030000   /* Select Mini-Bank 3 */
+#define TEST_SET(x)       ((x << 5) & 0x03E0)  /* Set Index 0->31 */
+#define TEST_WAY0         0x00000000   /* Access Way0 */
+#define TEST_WAY1         0x04000000   /* Access Way1 */
+/* ITEST_COMMAND only */
+#define TEST_WAY2         0x08000000   /* Access Way2 */
+#define TEST_WAY3         0x0C000000   /* Access Way3 */
+/* DTEST_COMMAND only */
+#define TEST_BNKSELA      0x00000000   /* Access SuperBank A */
+#define TEST_BNKSELB      0x00800000   /* Access SuperBank B */
+
+#endif                         /* _DEF_LPBLACKFIN_H */
diff --git a/include/asm-blackfin/macros.h b/include/asm-blackfin/macros.h
new file mode 100644 (file)
index 0000000..c0c04a2
--- /dev/null
@@ -0,0 +1,95 @@
+/************************************************************************
+ *
+ * macros.h
+ *
+ * (c) Copyright 2001-2003 Analog Devices, Inc.  All rights reserved.
+ *
+ ************************************************************************/
+
+/* Defines various assembly macros. */
+
+#ifndef _MACROS_H
+#define _MACROS_H
+
+#define LO(con32) ((con32) & 0xFFFF)
+#define lo(con32) ((con32) & 0xFFFF)
+#define HI(con32) (((con32) >> 16) & 0xFFFF)
+#define hi(con32) (((con32) >> 16) & 0xFFFF)
+
+/*
+ * Set the corresponding bits in a System Register (SR);
+ * All bits set in "mask" will be set in the system register
+ * specified by "sys_reg" bitset_SR(sys_reg, mask), where
+ * sys_reg is the system register and mask are the bits to be set.
+ */
+#define bitset_SR(sys_reg, mask)\
+               [--SP] = (R7:6);\
+               r7 = sys_reg;\
+               r6.l = (mask) & 0xffff;\
+               r6.h = (mask) >> 16;\
+               r7 = r7 | r6;\
+               sys_reg = r7;\
+               csync;\
+               (R7:6) = [SP++]
+
+/*
+ * Clear the corresponding bits in a System Register (SR);
+ * All bits set in "mask" will be cleared in the SR
+ * specified by "sys_reg" bitclr_SR(sys_reg, mask), where
+ * sys_reg is the SR and mask are the bits to be cleared.
+ */
+#define bitclr_SR(sys_reg, mask)\
+               [--SP] = (R7:6);\
+               r7 = sys_reg;\
+               r7 =~ r7;\
+               r6.l = (mask) & 0xffff;\
+               r6.h = (mask) >> 16;\
+               r7 = r7 | r6;\
+               r7 =~ r7;\
+               sys_reg = r7;\
+               csync;\
+               (R7:6) = [SP++]
+
+/*
+ * Set the corresponding bits in a Memory Mapped Register (MMR);
+ * All bits set in "mask" will be set in the MMR specified by "mmr_reg"
+ * bitset_MMR(mmr_reg, mask), where mmr_reg is the MMR and mask are
+ * the bits to be set.
+ */
+#define bitset_MMR(mmr_reg, mask)\
+               [--SP] = (R7:6);\
+               [--SP] = P5;\
+               p5.l = mmr_reg & 0xffff;\
+               p5.h = mmr_reg >> 16;\
+               r7 = [p5];\
+               r6.l = (mask) & 0xffff;\
+               r6.h = (mask) >> 16;\
+               r7 = r7 | r6;\
+               [p5] = r7;\
+               csync;\
+               p5 = [SP++];\
+               (R7:6) = [SP++]
+
+/*
+ * Clear the corresponding bits in a Memory Mapped Register (MMR);
+ * All bits set in "mask" will be cleared in the MMR specified by "mmr_reg"
+ * bitclr_MMRreg(mmr_reg, mask), where sys_reg is the MMR and mask are
+ * the bits to be cleared.
+ */
+#define bitclr_MMR(mmr_reg, mask)\
+               [--SP] = (R7:6);\
+               [--SP] = P5;\
+               p5.l = mmr_reg & 0xffff;\
+               p5.h = mmr_reg >> 16;\
+               r7 = [p5];\
+               r7 =~ r7;\
+               r6.l = (mask) & 0xffff;\
+               r6.h = (mask) >> 16;\
+               r7 = r7 | r6;\
+               r7 =~ r7;\
+               [p5] = r7;\
+               csync;\
+               p5 = [SP++];\
+               (R7:6) = [SP++]
+
+#endif                         /* _MACROS_H */
diff --git a/include/asm-blackfin/mem_map.h b/include/asm-blackfin/mem_map.h
new file mode 100644 (file)
index 0000000..42d1f37
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * mem_map.h
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _MEM_MAP_H_
+#define _MEM_MAP_H_
+
+#include <asm/mach/mem_map.h>
+
+#endif                         /* _MEM_MAP_H_ */
diff --git a/include/asm-blackfin/mman.h b/include/asm-blackfin/mman.h
new file mode 100644 (file)
index 0000000..4d504f9
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __BFIN_MMAN_H__
+#define __BFIN_MMAN_H__
+
+#define PROT_READ      0x1     /* page can be read */
+#define PROT_WRITE     0x2     /* page can be written */
+#define PROT_EXEC      0x4     /* page can be executed */
+#define PROT_SEM       0x8     /* page may be used for atomic ops */
+#define PROT_NONE      0x0     /* page can not be accessed */
+#define PROT_GROWSDOWN 0x01000000      /* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP   0x02000000      /* mprotect flag: extend change to end of growsup vma */
+
+#define MAP_SHARED     0x01    /* Share changes */
+#define MAP_PRIVATE    0x02    /* Changes are private */
+#define MAP_TYPE       0x0f    /* Mask for type of mapping */
+#define MAP_FIXED      0x10    /* Interpret addr exactly */
+#define MAP_ANONYMOUS  0x20    /* don't use a file */
+
+#define MAP_GROWSDOWN  0x0100  /* stack-like segment */
+#define MAP_DENYWRITE  0x0800  /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000  /* mark it as an executable */
+#define MAP_LOCKED     0x2000  /* pages are locked */
+#define MAP_NORESERVE  0x4000  /* don't check for reservations */
+#define MAP_POPULATE   0x8000  /* populate (prefault) pagetables */
+#define MAP_NONBLOCK   0x10000 /* do not block on IO */
+#define MAP_UNINITIALIZE 0x4000000  /* For anonymous mmap, memory could
+                                    be uninitialized. */
+
+#define MS_ASYNC       1       /* sync memory asynchronously */
+#define MS_INVALIDATE  2       /* invalidate the caches */
+#define MS_SYNC                4       /* synchronous memory sync */
+
+#define MCL_CURRENT    1       /* lock all current mappings */
+#define MCL_FUTURE     2       /* lock all future mappings */
+
+#define MADV_NORMAL    0x0     /* default page-in behavior */
+#define MADV_RANDOM    0x1     /* page-in minimum required */
+#define MADV_SEQUENTIAL        0x2     /* read-ahead aggressively */
+#define MADV_WILLNEED  0x3     /* pre-fault pages */
+#define MADV_DONTNEED  0x4     /* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON       MAP_ANONYMOUS
+#define MAP_FILE       0
+
+#endif                         /* __BFIN_MMAN_H__ */
diff --git a/include/asm-blackfin/mmu.h b/include/asm-blackfin/mmu.h
new file mode 100644 (file)
index 0000000..11d52f1
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
+
+struct sram_list_struct {
+       struct sram_list_struct *next;
+       void *addr;
+       size_t length;
+};
+
+typedef struct {
+       struct vm_list_struct *vmlist;
+       unsigned long end_brk;
+       unsigned long stack_start;
+
+       /* Points to the location in SDRAM where the L1 stack is normally
+          saved, or NULL if the stack is always in SDRAM.  */
+       void *l1_stack_save;
+
+       struct sram_list_struct *sram_list;
+
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+       unsigned long   exec_fdpic_loadmap;
+       unsigned long   interp_fdpic_loadmap;
+#endif
+
+} mm_context_t;
+
+#endif
diff --git a/include/asm-blackfin/mmu_context.h b/include/asm-blackfin/mmu_context.h
new file mode 100644 (file)
index 0000000..c5c71a6
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * File:         include/asm-blackfin/mmu_context.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __BLACKFIN_MMU_CONTEXT_H__
+#define __BLACKFIN_MMU_CONTEXT_H__
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+extern void *current_l1_stack_save;
+extern int nr_l1stack_tasks;
+extern void *l1_stack_base;
+extern unsigned long l1_stack_len;
+
+extern int l1sram_free(const void*);
+extern void *l1sram_alloc_max(void*);
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/* Called when creating a new context during fork() or execve().  */
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+       return 0;
+}
+
+static inline void free_l1stack(void)
+{
+       nr_l1stack_tasks--;
+       if (nr_l1stack_tasks == 0)
+               l1sram_free(l1_stack_base);
+}
+static inline void destroy_context(struct mm_struct *mm)
+{
+       struct sram_list_struct *tmp;
+
+       if (current_l1_stack_save == mm->context.l1_stack_save)
+               current_l1_stack_save = 0;
+       if (mm->context.l1_stack_save)
+               free_l1stack();
+
+       while ((tmp = mm->context.sram_list)) {
+               mm->context.sram_list = tmp->next;
+               sram_free(tmp->addr);
+               kfree(tmp);
+       }
+}
+
+static inline unsigned long
+alloc_l1stack(unsigned long length, unsigned long *stack_base)
+{
+       if (nr_l1stack_tasks == 0) {
+               l1_stack_base = l1sram_alloc_max(&l1_stack_len);
+               if (!l1_stack_base)
+                       return 0;
+       }
+
+       if (l1_stack_len < length) {
+               if (nr_l1stack_tasks == 0)
+                       l1sram_free(l1_stack_base);
+               return 0;
+       }
+       *stack_base = (unsigned long)l1_stack_base;
+       nr_l1stack_tasks++;
+       return l1_stack_len;
+}
+
+static inline int
+activate_l1stack(struct mm_struct *mm, unsigned long sp_base)
+{
+       if (current_l1_stack_save)
+               memcpy(current_l1_stack_save, l1_stack_base, l1_stack_len);
+       mm->context.l1_stack_save = current_l1_stack_save = (void*)sp_base;
+       memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len);
+       return 1;
+}
+
+#define deactivate_mm(tsk,mm)  do { } while (0)
+
+static inline void activate_mm(struct mm_struct *prev_mm,
+                              struct mm_struct *next_mm)
+{
+       if (!next_mm->context.l1_stack_save)
+               return;
+       if (next_mm->context.l1_stack_save == current_l1_stack_save)
+               return;
+       if (current_l1_stack_save) {
+               memcpy(current_l1_stack_save, l1_stack_base, l1_stack_len);
+       }
+       current_l1_stack_save = next_mm->context.l1_stack_save;
+       memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len);
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+                            struct task_struct *tsk)
+{
+       activate_mm(prev, next);
+}
+
+#endif
diff --git a/include/asm-blackfin/module.h b/include/asm-blackfin/module.h
new file mode 100644 (file)
index 0000000..3c7ce16
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_BFIN_MODULE_H
+#define _ASM_BFIN_MODULE_H
+
+#define MODULE_SYMBOL_PREFIX "_"
+
+#define Elf_Shdr        Elf32_Shdr
+#define Elf_Sym         Elf32_Sym
+#define Elf_Ehdr        Elf32_Ehdr
+#define FLG_CODE_IN_L1 0x10
+#define FLG_DATA_IN_L1 0x20
+
+struct mod_arch_specific {
+       Elf_Shdr        *text_l1;
+       Elf_Shdr        *data_a_l1;
+       Elf_Shdr        *bss_a_l1;
+       Elf_Shdr        *data_b_l1;
+       Elf_Shdr        *bss_b_l1;
+};
+#endif                         /* _ASM_BFIN_MODULE_H */
diff --git a/include/asm-blackfin/msgbuf.h b/include/asm-blackfin/msgbuf.h
new file mode 100644 (file)
index 0000000..6fcbe8c
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _BFIN_MSGBUF_H
+#define _BFIN_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for bfin architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long __unused3;
+       unsigned long msg_cbytes;       /* current number of bytes on queue */
+       unsigned long msg_qnum; /* number of messages in queue */
+       unsigned long msg_qbytes;       /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long __unused4;
+       unsigned long __unused5;
+};
+
+#endif                         /* _BFIN_MSGBUF_H */
diff --git a/include/asm-blackfin/mutex.h b/include/asm-blackfin/mutex.h
new file mode 100644 (file)
index 0000000..458c1f7
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-blackfin/namei.h b/include/asm-blackfin/namei.h
new file mode 100644 (file)
index 0000000..8b89a2d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm/namei.h
+ *
+ * Included from linux/fs/namei.c
+ *
+ * Changes made by Lineo Inc.    May 2001
+ */
+
+#ifndef __BFIN_NAMEI_H
+#define __BFIN_NAMEI_H
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif
diff --git a/include/asm-blackfin/page.h b/include/asm-blackfin/page.h
new file mode 100644 (file)
index 0000000..ffad947
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef _BLACKFIN_PAGE_H
+#define _BLACKFIN_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+
+#define PAGE_SHIFT     12
+#define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#define PAGE_MASK      (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+
+#include <asm/setup.h>
+
+#ifndef __ASSEMBLY__
+
+#define get_user_page(vaddr)           __get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)     free_page(addr)
+
+#define clear_page(page)       memset((page), 0, PAGE_SIZE)
+#define copy_page(to,from)     memcpy((to), (from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr,pg)        clear_page(page)
+#define copy_user_page(to, from, vaddr,pg)     copy_page(to, from)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct {
+       unsigned long pte;
+} pte_t;
+typedef struct {
+       unsigned long pmd[16];
+} pmd_t;
+typedef struct {
+       unsigned long pgd;
+} pgd_t;
+typedef struct {
+       unsigned long pgprot;
+} pgprot_t;
+
+#define pte_val(x)     ((x).pte)
+#define pmd_val(x)     ((&x)->pmd[0])
+#define pgd_val(x)     ((x).pgd)
+#define pgprot_val(x)  ((x).pgprot)
+
+#define __pte(x)       ((pte_t) { (x) } )
+#define __pmd(x)       ((pmd_t) { (x) } )
+#define __pgd(x)       ((pgd_t) { (x) } )
+#define __pgprot(x)    ((pgprot_t) { (x) } )
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
+#endif                         /* !__ASSEMBLY__ */
+
+#include <asm/page_offset.h>
+#include <asm/io.h>
+
+#define PAGE_OFFSET            (PAGE_OFFSET_RAW)
+
+#ifndef __ASSEMBLY__
+
+#define __pa(vaddr)            virt_to_phys((void *)(vaddr))
+#define __va(paddr)            phys_to_virt((unsigned long)(paddr))
+
+#define MAP_NR(addr)           (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
+
+#define virt_to_pfn(kaddr)     (__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_virt(pfn)       __va((pfn) << PAGE_SHIFT)
+#define virt_to_page(addr)     (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
+#define page_to_virt(page)     ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
+
+#define pfn_to_page(pfn)       virt_to_page(pfn_to_virt(pfn))
+#define page_to_pfn(page)      virt_to_pfn(page_to_virt(page))
+#define pfn_valid(pfn)         ((pfn) < max_mapnr)
+
+#define        virt_addr_valid(kaddr)  (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
+                               ((void *)(kaddr) < (void *)memory_end))
+
+#include <asm-generic/page.h>
+
+#endif                         /* __ASSEMBLY__ */
+#endif                         /* __KERNEL__ */
+
+#endif                         /* _BLACKFIN_PAGE_H */
diff --git a/include/asm-blackfin/page_offset.h b/include/asm-blackfin/page_offset.h
new file mode 100644 (file)
index 0000000..3b671d5
--- /dev/null
@@ -0,0 +1,6 @@
+
+/* This handles the memory map.. */
+
+#ifdef CONFIG_BFIN
+#define PAGE_OFFSET_RAW                0x00000000
+#endif
diff --git a/include/asm-blackfin/param.h b/include/asm-blackfin/param.h
new file mode 100644 (file)
index 0000000..41564a6
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _BLACKFIN_PARAM_H
+#define _BLACKFIN_PARAM_H
+
+#ifdef __KERNEL__
+#define HZ             CONFIG_HZ
+#define        USER_HZ         100
+#define        CLOCKS_PER_SEC  (USER_HZ)
+#endif
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE  4096
+
+#ifndef NOGROUP
+#define NOGROUP                (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64      /* max length of hostname */
+
+#endif                         /* _BLACKFIN_PARAM_H */
diff --git a/include/asm-blackfin/pci.h b/include/asm-blackfin/pci.h
new file mode 100644 (file)
index 0000000..6127735
--- /dev/null
@@ -0,0 +1,148 @@
+/* Changed from asm-m68k version, Lineo Inc.   May 2001        */
+
+#ifndef _ASM_BFIN_PCI_H
+#define _ASM_BFIN_PCI_H
+
+#include <asm/scatterlist.h>
+
+/*
+ *
+ * Written by Wout Klaren.
+ */
+
+/* Added by Chang Junxiao */
+#define PCIBIOS_MIN_IO 0x00001000
+#define PCIBIOS_MIN_MEM 0x10000000
+
+#define PCI_DMA_BUS_IS_PHYS       (1)
+struct pci_ops;
+
+/*
+ * Structure with hardware dependent information and functions of the
+ * PCI bus.
+ */
+struct pci_bus_info {
+
+       /*
+        * Resources of the PCI bus.
+        */
+       struct resource mem_space;
+       struct resource io_space;
+
+       /*
+        * System dependent functions.
+        */
+       struct pci_ops *bfin_pci_ops;
+       void (*fixup) (int pci_modify);
+       void (*conf_device) (unsigned char bus, unsigned char device_fn);
+};
+
+#define pcibios_assign_all_busses()    0
+static inline void pcibios_set_master(struct pci_dev *dev)
+{
+
+       /* No special bus mastering setup handling */
+}
+static inline void pcibios_penalize_isa_irq(int irq)
+{
+
+       /* We don't do dynamic PCI IRQ allocation */
+}
+static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
+                                       size_t size, int direction)
+{
+       if (direction == PCI_DMA_NONE)
+               BUG();
+
+        /* return virt_to_bus(ptr); */
+       return (dma_addr_t) ptr;
+}
+
+/* Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+                                   size_t size, int direction)
+{
+       if (direction == PCI_DMA_NONE)
+               BUG();
+
+       /* Nothing to do */
+}
+
+/* Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+                            int nents, int direction)
+{
+       if (direction == PCI_DMA_NONE)
+               BUG();
+       return nents;
+}
+
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+                               int nents, int direction)
+{
+       if (direction == PCI_DMA_NONE)
+               BUG();
+
+       /* Nothing to do */
+}
+
+/* Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
+ */
+static inline void pci_dma_sync_single(struct pci_dev *hwdev,
+                                      dma_addr_t dma_handle, size_t size,
+                                      int direction)
+{
+       if (direction == PCI_DMA_NONE)
+               BUG();
+
+       /* Nothing to do */
+}
+
+/* Make physical memory consistent for a set of streaming
+ * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
+                                  struct scatterlist *sg, int nelems,
+                                  int direction)
+{
+       if (direction == PCI_DMA_NONE)
+               BUG();
+
+       /* Nothing to do */
+}
+
+#endif                         /* _ASM_BFIN_PCI_H */
diff --git a/include/asm-blackfin/percpu.h b/include/asm-blackfin/percpu.h
new file mode 100644 (file)
index 0000000..78dd61f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ARCH_BLACKFIN_PERCPU__
+#define __ARCH_BLACKFIN_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif                         /* __ARCH_BLACKFIN_PERCPU__ */
diff --git a/include/asm-blackfin/pgalloc.h b/include/asm-blackfin/pgalloc.h
new file mode 100644 (file)
index 0000000..c686e05
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _BLACKFIN_PGALLOC_H
+#define _BLACKFIN_PGALLOC_H
+
+#include <asm/setup.h>
+
+#define check_pgt_cache()      do { } while (0)
+
+#endif                         /* _BLACKFIN_PGALLOC_H */
diff --git a/include/asm-blackfin/pgtable.h b/include/asm-blackfin/pgtable.h
new file mode 100644 (file)
index 0000000..5a8f9e4
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef _BLACKFIN_PGTABLE_H
+#define _BLACKFIN_PGTABLE_H
+
+#include <asm-generic/4level-fixup.h>
+
+#include <asm/page.h>
+#include <asm/cplb.h>
+
+typedef pte_t *pte_addr_t;
+/*
+* Trivial page table functions.
+*/
+#define pgd_present(pgd)       (1)
+#define pgd_none(pgd)          (0)
+#define pgd_bad(pgd)           (0)
+#define pgd_clear(pgdp)
+#define kern_addr_valid(addr)  (1)
+
+#define pmd_offset(a, b)       ((void *)0)
+#define pmd_none(x)            (!pmd_val(x))
+#define pmd_present(x)         (pmd_val(x))
+#define pmd_clear(xp)          do { set_pmd(xp, __pmd(0)); } while (0)
+#define pmd_bad(x)             (pmd_val(x) & ~PAGE_MASK)
+
+#define kern_addr_valid(addr) (1)
+
+#define PAGE_NONE              __pgprot(0)     /* these mean nothing to NO_MM */
+#define PAGE_SHARED            __pgprot(0)     /* these mean nothing to NO_MM */
+#define PAGE_COPY              __pgprot(0)     /* these mean nothing to NO_MM */
+#define PAGE_READONLY          __pgprot(0)     /* these mean nothing to NO_MM */
+#define PAGE_KERNEL            __pgprot(0)     /* these mean nothing to NO_MM */
+
+extern void paging_init(void);
+
+#define __swp_type(x)          (0)
+#define __swp_offset(x)                (0)
+#define __swp_entry(typ,off)   ((swp_entry_t) { ((typ) | ((off) << 7)) })
+#define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
+
+static inline int pte_file(pte_t pte)
+{
+       return 0;
+}
+
+#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
+
+/*
+ * Page assess control based on Blackfin CPLB management
+ */
+#define _PAGE_RD       (CPLB_USER_RD)
+#define _PAGE_WR       (CPLB_USER_WR)
+#define _PAGE_USER     (CPLB_USER_RD | CPLB_USER_WR)
+#define _PAGE_ACCESSED CPLB_ALL_ACCESS
+#define _PAGE_DIRTY    (CPLB_DIRTY)
+
+#define PTE_BIT_FUNC(fn, op) \
+       static inline pte_t pte_##fn(pte_t _pte) { _pte.pte op; return _pte; }
+
+PTE_BIT_FUNC(rdprotect, &= ~_PAGE_RD);
+PTE_BIT_FUNC(mkread, |= _PAGE_RD);
+PTE_BIT_FUNC(wrprotect, &= ~_PAGE_WR);
+PTE_BIT_FUNC(mkwrite, |= _PAGE_WR);
+PTE_BIT_FUNC(exprotect, &= ~_PAGE_USER);
+PTE_BIT_FUNC(mkexec, |= _PAGE_USER);
+PTE_BIT_FUNC(mkclean, &= ~_PAGE_DIRTY);
+PTE_BIT_FUNC(mkdirty, |= _PAGE_DIRTY);
+PTE_BIT_FUNC(mkold, &= ~_PAGE_ACCESSED);
+PTE_BIT_FUNC(mkyoung, |= _PAGE_ACCESSED);
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+#define ZERO_PAGE(vaddr)       (virt_to_page(0))
+
+extern unsigned int kobjsize(const void *objp);
+
+#define swapper_pg_dir ((pgd_t *) 0)
+/*
+ * No page table caches to initialise.
+ */
+#define pgtable_cache_init()   do { } while (0)
+#define io_remap_pfn_range      remap_pfn_range
+
+/*
+ * All 32bit addresses are effectively valid for vmalloc...
+ * Sort of meaningless for non-VM targets.
+ */
+#define        VMALLOC_START   0
+#define        VMALLOC_END     0xffffffff
+
+#include <asm-generic/pgtable.h>
+
+#endif                         /* _BLACKFIN_PGTABLE_H */
diff --git a/include/asm-blackfin/poll.h b/include/asm-blackfin/poll.h
new file mode 100644 (file)
index 0000000..94cc263
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __BFIN_POLL_H
+#define __BFIN_POLL_H
+
+#define POLLIN           1
+#define POLLPRI                  2
+#define POLLOUT                  4
+#define POLLERR                  8
+#define POLLHUP                 16
+#define POLLNVAL        32
+#define POLLRDNORM      64
+#define POLLWRNORM     POLLOUT
+#define POLLRDBAND     128
+#define POLLWRBAND     256
+#define POLLMSG                0x0400
+#define POLLREMOVE     0x1000
+#define POLLRDHUP       0x2000
+
+struct pollfd {
+       int fd;
+       short events;
+       short revents;
+};
+
+#endif                         /* __BFIN_POLL_H */
diff --git a/include/asm-blackfin/posix_types.h b/include/asm-blackfin/posix_types.h
new file mode 100644 (file)
index 0000000..c3fa50f
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __ARCH_BFIN_POSIX_TYPES_H
+#define __ARCH_BFIN_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned int __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_timer_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_daddr_t;
+typedef char *__kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef unsigned short __kernel_old_dev_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+       int val[2];
+#else                          /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+       int __val[2];
+#endif                         /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+
+#undef __FD_CLR
+#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+
+#undef __FD_ISSET
+#define        __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif                         /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif
diff --git a/include/asm-blackfin/processor.h b/include/asm-blackfin/processor.h
new file mode 100644 (file)
index 0000000..997465c
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef __ASM_BFIN_PROCESSOR_H
+#define __ASM_BFIN_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <asm/blackfin.h>
+#include <asm/segment.h>
+#include <linux/compiler.h>
+
+static inline unsigned long rdusp(void)
+{
+       unsigned long usp;
+
+       __asm__ __volatile__("%0 = usp;\n\t":"=da"(usp));
+       return usp;
+}
+
+static inline void wrusp(unsigned long usp)
+{
+       __asm__ __volatile__("usp = %0;\n\t"::"da"(usp));
+}
+
+/*
+ * User space process size: 1st byte beyond user address space.
+ */
+extern unsigned long memory_end;
+#define TASK_SIZE      (memory_end)
+
+#define TASK_UNMAPPED_BASE     0
+
+struct thread_struct {
+       unsigned long ksp;      /* kernel stack pointer */
+       unsigned long usp;      /* user stack pointer */
+       unsigned short seqstat; /* saved status register */
+       unsigned long esp0;     /* points to SR of stack frame pt_regs */
+       unsigned long pc;       /* instruction pointer */
+       void *        debuggerinfo;
+};
+
+#define INIT_THREAD  {                                         \
+       sizeof(init_stack) + (unsigned long) init_stack, 0,     \
+       PS_S, 0, 0                                              \
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ *
+ * pass the data segment into user programs if it exists,
+ * it can't hurt anything as far as I can tell
+ */
+#define start_thread(_regs, _pc, _usp)                                 \
+do {                                                                   \
+       set_fs(USER_DS);                                                \
+       (_regs)->pc = (_pc);                                            \
+       if (current->mm)                                                \
+               (_regs)->p5 = current->mm->start_data;                  \
+       current->thread_info->l1_task_info.stack_start                  \
+               = (void *)current->mm->context.stack_start;             \
+       current->thread_info->l1_task_info.lowest_sp = (void *)(_usp);          \
+       memcpy(L1_SCRATCH_TASK_INFO, &current->thread_info->l1_task_info,       \
+               sizeof(*L1_SCRATCH_TASK_INFO));                         \
+       wrusp(_usp);                                                    \
+} while(0)
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+#define prepare_to_copy(tsk)   do { } while (0)
+
+extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);
+
+/*
+ * Free current thread data structures etc..
+ */
+static inline void exit_thread(void)
+{
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+#define thread_saved_pc(tsk)   (tsk->thread.pc)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define        KSTK_EIP(tsk)                                                   \
+    ({                                                                 \
+       unsigned long eip = 0;                                          \
+       if ((tsk)->thread.esp0 > PAGE_SIZE &&                           \
+           MAP_NR((tsk)->thread.esp0) < max_mapnr)                     \
+             eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc;        \
+       eip; })
+#define        KSTK_ESP(tsk)   ((tsk) == current ? rdusp() : (tsk)->thread.usp)
+
+#define cpu_relax()            barrier()
+
+/* Get the Silicon Revision of the chip */
+static inline uint32_t bfin_revid(void)
+{
+       /* stored in the upper 4 bits */
+       return bfin_read_CHIPID() >> 28;
+}
+
+static inline uint32_t bfin_compiled_revid(void)
+{
+#if defined(CONFIG_BF_REV_0_0)
+       return 0;
+#elif defined(CONFIG_BF_REV_0_1)
+       return 1;
+#elif defined(CONFIG_BF_REV_0_2)
+       return 2;
+#elif defined(CONFIG_BF_REV_0_3)
+       return 3;
+#elif defined(CONFIG_BF_REV_0_4)
+       return 4;
+#elif defined(CONFIG_BF_REV_0_5)
+       return 5;
+#endif
+}
+
+#endif
diff --git a/include/asm-blackfin/ptrace.h b/include/asm-blackfin/ptrace.h
new file mode 100644 (file)
index 0000000..b8346cd
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef _BFIN_PTRACE_H
+#define _BFIN_PTRACE_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *       0 - 7 are data registers R0-R7
+ *       8 - 15 are address registers P0-P7
+ *      16 - 31 dsp registers I/B/L0 -- I/B/L3 & M0--M3
+ *      32 - 33 A registers A0 & A1
+ *      34 -    status register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *      32-33 --- Low 32-bit of A0&1
+ *      34-35 --- High 8-bit of A0&1
+ */
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+       long orig_pc;
+       long ipend;
+       long seqstat;
+       long rete;
+       long retn;
+       long retx;
+       long pc;                /* PC == RETI */
+       long rets;
+       long reserved;          /* Used as scratch during system calls */
+       long astat;
+       long lb1;
+       long lb0;
+       long lt1;
+       long lt0;
+       long lc1;
+       long lc0;
+       long a1w;
+       long a1x;
+       long a0w;
+       long a0x;
+       long b3;
+       long b2;
+       long b1;
+       long b0;
+       long l3;
+       long l2;
+       long l1;
+       long l0;
+       long m3;
+       long m2;
+       long m1;
+       long m0;
+       long i3;
+       long i2;
+       long i1;
+       long i0;
+       long usp;
+       long fp;
+       long p5;
+       long p4;
+       long p3;
+       long p2;
+       long p1;
+       long p0;
+       long r7;
+       long r6;
+       long r5;
+       long r4;
+       long r3;
+       long r2;
+       long r1;
+       long r0;
+       long orig_r0;
+       long orig_p0;
+       long syscfg;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13   /* ptrace signal  */
+
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+#define PTRACE_GETFDPIC           31
+#define PTRACE_GETFDPIC_EXEC      0
+#define PTRACE_GETFDPIC_INTERP    1
+#endif
+
+#define PS_S  (0x0002)
+
+/* user_mode returns true if only one bit is set in IPEND, other than the
+   master interrupt enable.  */
+#define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
+#define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
+extern void show_regs(struct pt_regs *);
+
+#endif                         /* __ASSEMBLY__ */
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ */
+
+#define PT_R0 204
+#define PT_R1 200
+#define PT_R2 196
+#define PT_R3 192
+#define PT_R4 188
+#define PT_R5 184
+#define PT_R6 180
+#define PT_R7 176
+#define PT_P0 172
+#define PT_P1 168
+#define PT_P2 164
+#define PT_P3 160
+#define PT_P4 156
+#define PT_P5 152
+#define PT_FP 148
+#define PT_USP 144
+#define PT_I0 140
+#define PT_I1 136
+#define PT_I2 132
+#define PT_I3 128
+#define PT_M0 124
+#define PT_M1 120
+#define PT_M2 116
+#define PT_M3 112
+#define PT_L0 108
+#define PT_L1 104
+#define PT_L2 100
+#define PT_L3 96
+#define PT_B0 92
+#define PT_B1 88
+#define PT_B2 84
+#define PT_B3 80
+#define PT_A0X 76
+#define PT_A0W 72
+#define PT_A1X 68
+#define PT_A1W 64
+#define PT_LC0 60
+#define PT_LC1 56
+#define PT_LT0 52
+#define PT_LT1 48
+#define PT_LB0 44
+#define PT_LB1 40
+#define PT_ASTAT 36
+#define PT_RESERVED 32
+#define PT_RETS 28
+#define PT_PC 24
+#define PT_RETX 20
+#define PT_RETN 16
+#define PT_RETE 12
+#define PT_SEQSTAT 8
+#define PT_IPEND 4
+
+#define PT_SYSCFG 216
+#define PT_TEXT_ADDR 220
+#define PT_TEXT_END_ADDR 224
+#define PT_DATA_ADDR 228
+#define PT_FDPIC_EXEC 232
+#define PT_FDPIC_INTERP 236
+
+#endif                         /* _BFIN_PTRACE_H */
diff --git a/include/asm-blackfin/resource.h b/include/asm-blackfin/resource.h
new file mode 100644 (file)
index 0000000..091355a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _BFIN_RESOURCE_H
+#define _BFIN_RESOURCE_H
+
+#include <asm-generic/resource.h>
+
+#endif                         /* _BFIN_RESOURCE_H */
diff --git a/include/asm-blackfin/scatterlist.h b/include/asm-blackfin/scatterlist.h
new file mode 100644 (file)
index 0000000..60e07b9
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _BLACKFIN_SCATTERLIST_H
+#define _BLACKFIN_SCATTERLIST_H
+
+#include <linux/mm.h>
+
+struct scatterlist {
+       struct page *page;
+       unsigned int offset;
+       dma_addr_t dma_address;
+       unsigned int length;
+};
+
+/*
+ * These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_address(sg) (page_address((sg)->page) + (sg)->offset)
+#define sg_dma_address(sg)      ((sg)->dma_address)
+#define sg_dma_len(sg)          ((sg)->length)
+
+#define ISA_DMA_THRESHOLD      (0xffffffff)
+
+#endif                         /* !(_BLACKFIN_SCATTERLIST_H) */
diff --git a/include/asm-blackfin/sections.h b/include/asm-blackfin/sections.h
new file mode 100644 (file)
index 0000000..1443c33
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _BLACKFIN_SECTIONS_H
+#define _BLACKFIN_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/include/asm-blackfin/segment.h b/include/asm-blackfin/segment.h
new file mode 100644 (file)
index 0000000..02cfd09
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _BFIN_SEGMENT_H
+#define _BFIN_SEGMENT_H
+
+#define KERNEL_DS   (0x5)
+#define USER_DS     (0x1)
+
+#endif                         /* _BFIN_SEGMENT_H */
diff --git a/include/asm-blackfin/semaphore-helper.h b/include/asm-blackfin/semaphore-helper.h
new file mode 100644 (file)
index 0000000..9082b0d
--- /dev/null
@@ -0,0 +1,82 @@
+/* Based on M68K version,      Lineo Inc.      May 2001 */
+
+#ifndef _BFIN_SEMAPHORE_HELPER_H
+#define _BFIN_SEMAPHORE_HELPER_H
+
+/*
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ *
+ */
+
+#include <asm/errno.h>
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+static inline void wake_one_more(struct semaphore *sem)
+{
+       atomic_inc(&sem->waking);
+}
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+       int ret;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&semaphore_wake_lock, flags);
+       ret = 0;
+       if (atomic_read(&sem->waking) > 0) {
+               atomic_dec(&sem->waking);
+               ret = 1;
+       }
+       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+       return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ *     1       got the lock
+ *     0       go to sleep
+ *     -EINTR  interrupted
+ */
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+                                               struct task_struct *tsk)
+{
+       int ret = 0;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&semaphore_wake_lock, flags);
+       if (atomic_read(&sem->waking) > 0) {
+               atomic_dec(&sem->waking);
+               ret = 1;
+       } else if (signal_pending(tsk)) {
+               atomic_inc(&sem->count);
+               ret = -EINTR;
+       }
+       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+       return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ *     1       failed to lock
+ *     0       got the lock
+ */
+static inline int waking_non_zero_trylock(struct semaphore *sem)
+{
+       int ret = 1;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&semaphore_wake_lock, flags);
+       if (atomic_read(&sem->waking) > 0) {
+               atomic_dec(&sem->waking);
+               ret = 0;
+       } else
+               atomic_inc(&sem->count);
+       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+       return ret;
+}
+
+#endif                         /* _BFIN_SEMAPHORE_HELPER_H */
diff --git a/include/asm-blackfin/semaphore.h b/include/asm-blackfin/semaphore.h
new file mode 100644 (file)
index 0000000..94c04d7
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef _BFIN_SEMAPHORE_H
+#define _BFIN_SEMAPHORE_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/rwsem.h>
+#include <asm/atomic.h>
+
+/*
+ * Interrupt-safe semaphores..
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ *
+ * BFIN version by akbar hussain Lineo Inc  April 2001
+ *
+ */
+
+struct semaphore {
+       atomic_t count;
+       int sleepers;
+       wait_queue_head_t wait;
+};
+
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .sleepers       = 0,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+       struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static inline void sema_init(struct semaphore *sem, int val)
+{
+       *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+}
+
+static inline void init_MUTEX(struct semaphore *sem)
+{
+       sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+{
+       sema_init(sem, 0);
+}
+
+asmlinkage void __down(struct semaphore *sem);
+asmlinkage int __down_interruptible(struct semaphore *sem);
+asmlinkage int __down_trylock(struct semaphore *sem);
+asmlinkage void __up(struct semaphore *sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+/*
+ * This is ugly, but we want the default case to fall through.
+ * "down_failed" is a special asm handler that calls the C
+ * routine that actually waits.
+ */
+static inline void down(struct semaphore *sem)
+{
+       might_sleep();
+       if (atomic_dec_return(&sem->count) < 0)
+               __down(sem);
+}
+
+static inline int down_interruptible(struct semaphore *sem)
+{
+       int ret = 0;
+
+       might_sleep();
+       if (atomic_dec_return(&sem->count) < 0)
+               ret = __down_interruptible(sem);
+       return (ret);
+}
+
+static inline int down_trylock(struct semaphore *sem)
+{
+       int ret = 0;
+
+       if (atomic_dec_return(&sem->count) < 0)
+               ret = __down_trylock(sem);
+       return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ * The default case (no contention) will result in NO
+ * jumps for both down() and up().
+ */
+static inline void up(struct semaphore *sem)
+{
+       if (atomic_inc_return(&sem->count) <= 0)
+               __up(sem);
+}
+
+#endif                         /* __ASSEMBLY__ */
+#endif                         /* _BFIN_SEMAPHORE_H */
diff --git a/include/asm-blackfin/sembuf.h b/include/asm-blackfin/sembuf.h
new file mode 100644 (file)
index 0000000..18deb5c
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _BFIN_SEMBUF_H
+#define _BFIN_SEMBUF_H
+
+/*
+ * The semid64_ds structure for bfin architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;     /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;      /* last semop time */
+       unsigned long __unused1;
+       __kernel_time_t sem_ctime;      /* last change time */
+       unsigned long __unused2;
+       unsigned long sem_nsems;        /* no. of semaphores in array */
+       unsigned long __unused3;
+       unsigned long __unused4;
+};
+
+#endif                         /* _BFIN_SEMBUF_H */
diff --git a/include/asm-blackfin/setup.h b/include/asm-blackfin/setup.h
new file mode 100644 (file)
index 0000000..01c8c6c
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+** asm/setup.h -- Definition of the Linux/bfin setup information
+**
+** This file is subject to the terms and conditions of the GNU General Public
+** License.  See the file COPYING in the main directory of this archive
+** for more details.
+**
+** Copyright Lineo, Inc 2001          Tony Kou
+**
+*/
+
+#ifndef _BFIN_SETUP_H
+#define _BFIN_SETUP_H
+
+#define COMMAND_LINE_SIZE      512
+
+#endif                         /* _BFIN_SETUP_H */
diff --git a/include/asm-blackfin/shmbuf.h b/include/asm-blackfin/shmbuf.h
new file mode 100644 (file)
index 0000000..6124363
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _BFIN_SHMBUF_H
+#define _BFIN_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for bfin architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm shm_perm;     /* operation perms */
+       size_t shm_segsz;       /* size of segment (bytes) */
+       __kernel_time_t shm_atime;      /* last attach time */
+       unsigned long __unused1;
+       __kernel_time_t shm_dtime;      /* last detach time */
+       unsigned long __unused2;
+       __kernel_time_t shm_ctime;      /* last change time */
+       unsigned long __unused3;
+       __kernel_pid_t shm_cpid;        /* pid of creator */
+       __kernel_pid_t shm_lpid;        /* pid of last operator */
+       unsigned long shm_nattch;       /* no. of current attaches */
+       unsigned long __unused4;
+       unsigned long __unused5;
+};
+
+struct shminfo64 {
+       unsigned long shmmax;
+       unsigned long shmmin;
+       unsigned long shmmni;
+       unsigned long shmseg;
+       unsigned long shmall;
+       unsigned long __unused1;
+       unsigned long __unused2;
+       unsigned long __unused3;
+       unsigned long __unused4;
+};
+
+#endif                         /* _BFIN_SHMBUF_H */
diff --git a/include/asm-blackfin/shmparam.h b/include/asm-blackfin/shmparam.h
new file mode 100644 (file)
index 0000000..3c03906
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _BFIN_SHMPARAM_H
+#define _BFIN_SHMPARAM_H
+
+#define        SHMLBA PAGE_SIZE        /* attach addr a multiple of this */
+
+#endif                         /* _BFIN_SHMPARAM_H */
diff --git a/include/asm-blackfin/sigcontext.h b/include/asm-blackfin/sigcontext.h
new file mode 100644 (file)
index 0000000..ce00b03
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _ASM_BLACKFIN_SIGCONTEXT_H
+#define _ASM_BLACKFIN_SIGCONTEXT_H
+
+/* Add new entries at the end of the structure only.  */
+struct sigcontext {
+       unsigned long sc_r0;
+       unsigned long sc_r1;
+       unsigned long sc_r2;
+       unsigned long sc_r3;
+       unsigned long sc_r4;
+       unsigned long sc_r5;
+       unsigned long sc_r6;
+       unsigned long sc_r7;
+       unsigned long sc_p0;
+       unsigned long sc_p1;
+       unsigned long sc_p2;
+       unsigned long sc_p3;
+       unsigned long sc_p4;
+       unsigned long sc_p5;
+       unsigned long sc_usp;
+       unsigned long sc_a0w;
+       unsigned long sc_a1w;
+       unsigned long sc_a0x;
+       unsigned long sc_a1x;
+       unsigned long sc_astat;
+       unsigned long sc_rets;
+       unsigned long sc_pc;
+       unsigned long sc_retx;
+       unsigned long sc_fp;
+       unsigned long sc_i0;
+       unsigned long sc_i1;
+       unsigned long sc_i2;
+       unsigned long sc_i3;
+       unsigned long sc_m0;
+       unsigned long sc_m1;
+       unsigned long sc_m2;
+       unsigned long sc_m3;
+       unsigned long sc_l0;
+       unsigned long sc_l1;
+       unsigned long sc_l2;
+       unsigned long sc_l3;
+       unsigned long sc_b0;
+       unsigned long sc_b1;
+       unsigned long sc_b2;
+       unsigned long sc_b3;
+       unsigned long sc_lc0;
+       unsigned long sc_lc1;
+       unsigned long sc_lt0;
+       unsigned long sc_lt1;
+       unsigned long sc_lb0;
+       unsigned long sc_lb1;
+       unsigned long sc_seqstat;
+};
+
+#endif
diff --git a/include/asm-blackfin/siginfo.h b/include/asm-blackfin/siginfo.h
new file mode 100644 (file)
index 0000000..eca4565
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _BFIN_SIGINFO_H
+#define _BFIN_SIGINFO_H
+
+#include <linux/types.h>
+#include <asm-generic/siginfo.h>
+
+#define UID16_SIGINFO_COMPAT_NEEDED
+
+#define si_uid16       _sifields._kill._uid
+
+#define ILL_ILLPARAOP  (__SI_FAULT|2)  /* illegal opcode combine ********** */
+#define ILL_ILLEXCPT   (__SI_FAULT|4)  /* unrecoverable exception ********** */
+#define ILL_CPLB_VI    (__SI_FAULT|9)  /* D/I CPLB protect violation ******** */
+#define ILL_CPLB_MISS  (__SI_FAULT|10) /* D/I CPLB miss ******** */
+#define ILL_CPLB_MULHIT        (__SI_FAULT|11) /* D/I CPLB multiple hit ******** */
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_OPFETCH    (__SI_FAULT|4)  /* error from instruction fetch ******** */
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_STEP      (__SI_FAULT|1)  /* single-step breakpoint************* */
+#define TRAP_TRACEFLOW (__SI_FAULT|2)  /* trace buffer overflow ************* */
+#define TRAP_WATCHPT   (__SI_FAULT|3)  /* watchpoint match      ************* */
+#define TRAP_ILLTRAP   (__SI_FAULT|4)  /* illegal trap          ************* */
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_STACKFLOW (__SI_FAULT|3)  /* stack overflow */
+
+#endif
diff --git a/include/asm-blackfin/signal.h b/include/asm-blackfin/signal.h
new file mode 100644 (file)
index 0000000..0250429
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef _BLACKFIN_SIGNAL_H
+#define _BLACKFIN_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG          64
+#define _NSIG_BPW      32
+#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;    /* at least 32 bits */
+
+typedef struct {
+       unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif                         /* __KERNEL__ */
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002      /* not supported yet */
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#include <asm-generic/signal.h>
+
+#ifdef __KERNEL__
+struct old_sigaction {
+       __sighandler_t sa_handler;
+       old_sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer) (void);
+};
+
+struct sigaction {
+       __sighandler_t sa_handler;
+       unsigned long sa_flags;
+       void (*sa_restorer) (void);
+       sigset_t sa_mask;       /* mask last for extensibility */
+};
+
+struct k_sigaction {
+       struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+               __sighandler_t _sa_handler;
+               void (*_sa_sigaction) (int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer) (void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif                         /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+
+#include <asm/sigcontext.h>
+#undef __HAVE_ARCH_SIG_BITOPS
+
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif                         /* __KERNEL__ */
+
+#endif                         /* _BLACKFIN_SIGNAL_H */
diff --git a/include/asm-blackfin/socket.h b/include/asm-blackfin/socket.h
new file mode 100644 (file)
index 0000000..5213c96
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET     1
+
+#define SO_DEBUG       1
+#define SO_REUSEADDR   2
+#define SO_TYPE                3
+#define SO_ERROR       4
+#define SO_DONTROUTE   5
+#define SO_BROADCAST   6
+#define SO_SNDBUF      7
+#define SO_RCVBUF      8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE   9
+#define SO_OOBINLINE   10
+#define SO_NO_CHECK    11
+#define SO_PRIORITY    12
+#define SO_LINGER      13
+#define SO_BSDCOMPAT   14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED    16
+#define SO_PEERCRED    17
+#define SO_RCVLOWAT    18
+#define SO_SNDLOWAT    19
+#define SO_RCVTIMEO    20
+#define SO_SNDTIMEO    21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION             22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
+#define SO_SECURITY_ENCRYPTION_NETWORK         24
+
+#define SO_BINDTODEVICE        25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER       26
+#define SO_DETACH_FILTER       27
+
+#define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
+
+#define SO_ACCEPTCONN          30
+#define SO_PEERSEC             31
+#define SO_PASSSEC             34
+#define SO_TIMESTAMPNS         35
+#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
+#endif                         /* _ASM_SOCKET_H */
diff --git a/include/asm-blackfin/sockios.h b/include/asm-blackfin/sockios.h
new file mode 100644 (file)
index 0000000..426b89b
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ARCH_BFIN_SOCKIOS__
+#define __ARCH_BFIN_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN      0x8901
+#define SIOCSPGRP      0x8902
+#define FIOGETOWN      0x8903
+#define SIOCGPGRP      0x8904
+#define SIOCATMARK     0x8905
+#define SIOCGSTAMP     0x8906  /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   0x8907  /* Get stamp (timespec) */
+
+#endif                         /* __ARCH_BFIN_SOCKIOS__ */
diff --git a/include/asm-blackfin/spinlock.h b/include/asm-blackfin/spinlock.h
new file mode 100644 (file)
index 0000000..64e908a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __BFIN_SPINLOCK_H
+#define __BFIN_SPINLOCK_H
+
+#error blackfin architecture does not support SMP spin lock yet
+
+#endif
diff --git a/include/asm-blackfin/stat.h b/include/asm-blackfin/stat.h
new file mode 100644 (file)
index 0000000..d2b6f11
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef _BFIN_STAT_H
+#define _BFIN_STAT_H
+
+struct stat {
+       unsigned short st_dev;
+       unsigned short __pad1;
+       unsigned long st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned short __pad2;
+       unsigned long st_size;
+       unsigned long st_blksize;
+       unsigned long st_blocks;
+       unsigned long st_atime;
+       unsigned long __unused1;
+       unsigned long st_mtime;
+       unsigned long __unused2;
+       unsigned long st_ctime;
+       unsigned long __unused3;
+       unsigned long __unused4;
+       unsigned long __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned long long st_dev;
+       unsigned char __pad1[4];
+
+#define STAT64_HAS_BROKEN_ST_INO       1
+       unsigned long __st_ino;
+
+       unsigned int st_mode;
+       unsigned int st_nlink;
+
+       unsigned long st_uid;
+       unsigned long st_gid;
+
+       unsigned long long st_rdev;
+       unsigned char __pad2[4];
+
+       long long st_size;
+       unsigned long st_blksize;
+
+       long long st_blocks;    /* Number 512-byte blocks allocated. */
+
+       unsigned long st_atime;
+       unsigned long st_atime_nsec;
+
+       unsigned long st_mtime;
+       unsigned long st_mtime_nsec;
+
+       unsigned long st_ctime;
+       unsigned long st_ctime_nsec;
+
+       unsigned long long st_ino;
+};
+
+#endif                         /* _BFIN_STAT_H */
diff --git a/include/asm-blackfin/statfs.h b/include/asm-blackfin/statfs.h
new file mode 100644 (file)
index 0000000..3506720
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _BFIN_STATFS_H
+#define _BFIN_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif                         /* _BFIN_STATFS_H */
diff --git a/include/asm-blackfin/string.h b/include/asm-blackfin/string.h
new file mode 100644 (file)
index 0000000..6f1eb7d
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef _BLACKFIN_STRING_H_
+#define _BLACKFIN_STRING_H_
+
+#ifdef __KERNEL__              /* only set these up for kernel code */
+
+#define __HAVE_ARCH_STRCPY
+extern inline char *strcpy(char *dest, const char *src)
+{
+       char *xdest = dest;
+       char temp = 0;
+
+       __asm__ __volatile__
+           ("1:\t%2 = B [%1++] (Z);\n\t"
+            "B [%0++] = %2;\n\t"
+            "CC = %2;\n\t"
+        "if cc jump 1b (bp);\n"
+       : "+&a" (dest), "+&a" (src), "=&d" (temp)
+            ::"memory", "CC");
+       return xdest;
+}
+
+#define __HAVE_ARCH_STRNCPY
+extern inline char *strncpy(char *dest, const char *src, size_t n)
+{
+       char *xdest = dest;
+       char temp = 0;
+
+       if (n == 0)
+               return xdest;
+
+       __asm__ __volatile__
+           ("1:\t%3 = B [%1++] (Z);\n\t"
+            "B [%0++] = %3;\n\t"
+            "CC = %3;\n\t"
+            "if ! cc jump 2f;\n\t"
+            "%2 += -1;\n\t"
+            "CC = %2 == 0;\n\t"
+            "if ! cc jump 1b (bp);\n"
+        "2:\n"
+       : "+&a" (dest), "+&a" (src), "+&da" (n), "=&d" (temp)
+            ::"memory", "CC");
+       return xdest;
+}
+
+#define __HAVE_ARCH_STRCMP
+extern inline int strcmp(const char *cs, const char *ct)
+{
+       char __res1, __res2;
+
+       __asm__
+       ("1:\t%2 = B[%0++] (Z);\n\t" /* get *cs */
+               "%3 = B[%1++] (Z);\n\t" /* get *ct */
+               "CC = %2 == %3;\n\t"    /* compare a byte */
+               "if ! cc jump 2f;\n\t"  /* not equal, break out */
+               "CC = %2;\n\t"  /* at end of cs? */
+               "if cc jump 1b (bp);\n\t"       /* no, keep going */
+               "jump.s 3f;\n"  /* strings are equal */
+               "2:\t%2 = %2 - %3;\n"   /* *cs - *ct */
+        "3:\n"
+       : "+&a" (cs), "+&a" (ct), "=&d" (__res1), "=&d" (__res2)
+      : :      "CC");
+
+       return __res1;
+}
+
+#define __HAVE_ARCH_STRNCMP
+extern inline int strncmp(const char *cs, const char *ct, size_t count)
+{
+       char __res1, __res2;
+
+       if (!count)
+               return 0;
+       __asm__
+       ("1:\t%3 = B[%0++] (Z);\n\t"        /* get *cs */
+               "%4 = B[%1++] (Z);\n\t" /* get *ct */
+               "CC = %3 == %4;\n\t"    /* compare a byte */
+               "if ! cc jump 3f;\n\t"  /* not equal, break out */
+               "CC = %3;\n\t"  /* at end of cs? */
+               "if ! cc jump 4f;\n\t"  /* yes, all done */
+               "%2 += -1;\n\t" /* no, adjust count */
+       "CC = %2 == 0;\n\t"
+        "if ! cc jump 1b;\n"                 /* more to do, keep going */
+               "2:\t%3 = 0;\n\t"       /* strings are equal */
+        "jump.s    4f;\n"
+        "3:\t%3 = %3 - %4;\n"          /* *cs - *ct */
+        "4:"
+       : "+&a" (cs), "+&a" (ct), "+&da" (count), "=&d" (__res1), "=&d" (__res2)
+      : :      "CC");
+       return __res1;
+}
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *s, int c, size_t count);
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *d, const void *s, size_t count);
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *, const void *, __kernel_size_t);
+#define        __HAVE_ARCH_MEMCHR
+extern void *memchr(const void *s, int c, size_t n);
+#define        __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *dest, const void *src, size_t count);
+
+#endif /*__KERNEL__*/
+#endif                         /* _BLACKFIN_STRING_H_ */
diff --git a/include/asm-blackfin/system.h b/include/asm-blackfin/system.h
new file mode 100644 (file)
index 0000000..758bac7
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * File:        include/asm/system.h
+ * Based on:
+ * Author:      Tony Kou (tonyko@lineo.ca)
+ *              Copyright (c) 2002 Arcturus Networks Inc.
+ *                    (www.arcturusnetworks.com)
+ *              Copyright (c) 2003 Metrowerks (www.metrowerks.com)
+ *              Copyright (c) 2004 Analog Device Inc.
+ * Created:     25Jan2001 - Tony Kou
+ * Description: system.h include file
+ *
+ * Modified:     22Sep2006 - Robin Getz
+ *                - move include blackfin.h down, so I can get access to
+ *                   irq functions in other include files.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BLACKFIN_SYSTEM_H
+#define _BLACKFIN_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/compiler.h>
+
+/*
+ * Interrupt configuring macros.
+ */
+
+extern unsigned long irq_flags;
+
+#define local_irq_enable() do {                \
+       __asm__ __volatile__ (          \
+               "sti %0;"               \
+               ::"d"(irq_flags));      \
+} while (0)
+
+#define local_irq_disable() do {       \
+       int _tmp_dummy;                 \
+       __asm__ __volatile__ (          \
+               "cli %0;"               \
+               :"=d" (_tmp_dummy):);   \
+} while (0)
+
+#if defined(ANOMALY_05000244) && defined (CONFIG_BLKFIN_CACHE)
+#define idle_with_irq_disabled() do {   \
+        __asm__ __volatile__ (          \
+                "nop; nop;\n"           \
+                ".align 8;\n"           \
+                "sti %0; idle;\n"       \
+                ::"d" (irq_flags));     \
+} while (0)
+#else
+#define idle_with_irq_disabled() do {   \
+       __asm__ __volatile__ (          \
+               ".align 8;\n"           \
+               "sti %0; idle;\n"       \
+               ::"d" (irq_flags));     \
+} while (0)
+#endif
+
+#ifdef CONFIG_DEBUG_HWERR
+#define __save_and_cli(x) do {                 \
+       __asm__ __volatile__ (                  \
+               "cli %0;\n\tsti %1;"            \
+               :"=&d"(x): "d" (0x3F));         \
+} while (0)
+#else
+#define __save_and_cli(x) do {         \
+       __asm__ __volatile__ (          \
+               "cli %0;"               \
+               :"=&d"(x):);            \
+} while (0)
+#endif
+
+#define local_save_flags(x) asm volatile ("cli %0;"     \
+                                         "sti %0;"     \
+                                         :"=d"(x):);
+
+#ifdef CONFIG_DEBUG_HWERR
+#define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0)
+#else
+#define irqs_enabled_from_flags(x) ((x) != 0x1f)
+#endif
+
+#define local_irq_restore(x) do {                      \
+       if (irqs_enabled_from_flags(x))                 \
+               local_irq_enable ();                    \
+} while (0)
+
+/* For spinlocks etc */
+#define local_irq_save(x) __save_and_cli(x)
+
+#define        irqs_disabled()                         \
+({                                             \
+       unsigned long flags;                    \
+       local_save_flags(flags);                \
+       !irqs_enabled_from_flags(flags);        \
+})
+
+/*
+ * Force strict CPU ordering.
+ */
+#define nop()  asm volatile ("nop;\n\t"::)
+#define mb()   asm volatile (""   : : :"memory")
+#define rmb()  asm volatile (""   : : :"memory")
+#define wmb()  asm volatile (""   : : :"memory")
+#define set_rmb(var, value)    do { (void) xchg(&var, value); } while (0)
+#define set_mb(var, value)     set_rmb(var, value)
+#define set_wmb(var, value)    do { var = value; wmb(); } while (0)
+
+#define read_barrier_depends()                 do { } while(0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) ((void)xchg((ptr),1))
+
+struct __xchg_dummy {
+       unsigned long a[100];
+};
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                  int size)
+{
+       unsigned long tmp = 0;
+       unsigned long flags = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               __asm__ __volatile__
+                       ("%0 = b%2 (z);\n\t"
+                        "b%2 = %1;\n\t"
+                        : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__
+                       ("%0 = w%2 (z);\n\t"
+                        "w%2 = %1;\n\t"
+                        : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__
+                       ("%0 = %2;\n\t"
+                        "%2 = %1;\n\t"
+                        : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       }
+       local_irq_restore(flags);
+       return tmp;
+}
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       unsigned long tmp = 0;
+       unsigned long flags = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               __asm__ __volatile__
+                       ("%0 = b%3 (z);\n\t"
+                        "CC = %1 == %0;\n\t"
+                        "IF !CC JUMP 1f;\n\t"
+                        "b%3 = %2;\n\t"
+                        "1:\n\t"
+                        : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__
+                       ("%0 = w%3 (z);\n\t"
+                        "CC = %1 == %0;\n\t"
+                        "IF !CC JUMP 1f;\n\t"
+                        "w%3 = %2;\n\t"
+                        "1:\n\t"
+                        : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__
+                       ("%0 = %3;\n\t"
+                        "CC = %1 == %0;\n\t"
+                        "IF !CC JUMP 1f;\n\t"
+                        "%3 = %2;\n\t"
+                        "1:\n\t"
+                        : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");
+               break;
+       }
+       local_irq_restore(flags);
+       return tmp;
+}
+
+#define cmpxchg(ptr,o,n)\
+        ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+                                        (unsigned long)(n),sizeof(*(ptr))))
+
+#define prepare_to_switch()     do { } while(0)
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.
+ */
+
+#include <asm/blackfin.h>
+
+asmlinkage struct task_struct *resume(struct task_struct *prev, struct task_struct *next);
+
+#define switch_to(prev,next,last) \
+do {    \
+       memcpy (&prev->thread_info->l1_task_info, L1_SCRATCH_TASK_INFO, \
+               sizeof *L1_SCRATCH_TASK_INFO); \
+       memcpy (L1_SCRATCH_TASK_INFO, &next->thread_info->l1_task_info, \
+               sizeof *L1_SCRATCH_TASK_INFO); \
+       (last) = resume (prev, next);   \
+} while (0)
+
+#endif                         /* _BLACKFIN_SYSTEM_H */
diff --git a/include/asm-blackfin/termbits.h b/include/asm-blackfin/termbits.h
new file mode 100644 (file)
index 0000000..2fd9dab
--- /dev/null
@@ -0,0 +1,184 @@
+#ifndef __ARCH_BFIN_TERMBITS_H__
+#define __ARCH_BFIN_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+struct termios {
+       tcflag_t c_iflag;       /* input mode flags */
+       tcflag_t c_oflag;       /* output mode flags */
+       tcflag_t c_cflag;       /* control mode flags */
+       tcflag_t c_lflag;       /* local mode flags */
+       cc_t c_line;            /* line discipline */
+       cc_t c_cc[NCCS];        /* control characters */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK  0000020
+#define ISTRIP 0000040
+#define INLCR  0000100
+#define IGNCR  0000200
+#define ICRNL  0000400
+#define IUCLC  0001000
+#define IXON   0002000
+#define IXANY  0004000
+#define IXOFF  0010000
+#define IMAXBEL        0020000
+#define IUTF8  0040000
+
+/* c_oflag bits */
+#define OPOST  0000001
+#define OLCUC  0000002
+#define ONLCR  0000004
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define   NL0  0000000
+#define   NL1  0000400
+#define CRDLY  0003000
+#define   CR0  0000000
+#define   CR1  0001000
+#define   CR2  0002000
+#define   CR3  0003000
+#define TABDLY 0014000
+#define   TAB0 0000000
+#define   TAB1 0004000
+#define   TAB2 0010000
+#define   TAB3 0014000
+#define   XTABS        0014000
+#define BSDLY  0020000
+#define   BS0  0000000
+#define   BS1  0020000
+#define VTDLY  0040000
+#define   VT0  0000000
+#define   VT1  0040000
+#define FFDLY  0100000
+#define   FF0  0000000
+#define   FF1  0100000
+
+/* c_cflag bit meaning */
+#define CBAUD  0010017
+#define  B0    0000000         /* hang up */
+#define  B50   0000001
+#define  B75   0000002
+#define  B110  0000003
+#define  B134  0000004
+#define  B150  0000005
+#define  B200  0000006
+#define  B300  0000007
+#define  B600  0000010
+#define  B1200 0000011
+#define  B1800 0000012
+#define  B2400 0000013
+#define  B4800 0000014
+#define  B9600 0000015
+#define  B19200        0000016
+#define  B38400        0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE  0000060
+#define   CS5  0000000
+#define   CS6  0000020
+#define   CS7  0000040
+#define   CS8  0000060
+#define CSTOPB 0000100
+#define CREAD  0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL  0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD   002003600000  /* input baud rate (not used) */
+#define CMSPAR   010000000000  /* mark or space (stick) parity */
+#define CRTSCTS          020000000000  /* flow control */
+
+/* c_lflag bits */
+#define ISIG   0000001
+#define ICANON 0000002
+#define XCASE  0000004
+#define ECHO   0000010
+#define ECHOE  0000020
+#define ECHOK  0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL        0001000
+#define ECHOPRT        0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* tcflow() and TCXONC use these */
+#define        TCOOFF          0
+#define        TCOON           1
+#define        TCIOFF          2
+#define        TCION           3
+
+/* tcflush() and TCFLSH use these */
+#define        TCIFLUSH        0
+#define        TCOFLUSH        1
+#define        TCIOFLUSH       2
+
+/* tcsetattr uses these */
+#define        TCSANOW         0
+#define        TCSADRAIN       1
+#define        TCSAFLUSH       2
+
+#endif                         /* __ARCH_BFIN_TERMBITS_H__ */
diff --git a/include/asm-blackfin/termios.h b/include/asm-blackfin/termios.h
new file mode 100644 (file)
index 0000000..5c41478
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __BFIN_TERMIOS_H__
+#define __BFIN_TERMIOS_H__
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag; /* input mode flags */
+       unsigned short c_oflag; /* output mode flags */
+       unsigned short c_cflag; /* control mode flags */
+       unsigned short c_lflag; /* local mode flags */
+       unsigned char c_line;   /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY          0
+#define N_SLIP         1
+#define N_MOUSE                2
+#define N_PPP          3
+#define N_STRIP                4
+#define N_AX25         5
+#define N_X25          6       /* X.25 async */
+#define N_6PACK                7
+#define N_MASC         8       /* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964                9       /* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL 10      /* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA         11      /* Linux IR - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14      /* synchronous PPP */
+#define N_HCI          15      /* Bluetooth HCI UART */
+
+#ifdef __KERNEL__
+
+/*     intr=^C         quit=^\         erase=del       kill=^U
+       eof=^D          vtime=\0        vmin=\1         sxtc=\0
+       start=^Q        stop=^S         susp=^Z         eol=\0
+       reprint=^R      discard=^U      werase=^W       lnext=^V
+       eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+       unsigned short __tmp; \
+       get_user(__tmp,&(termio)->x); \
+       *(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+       put_user((termios)->c_iflag, &(termio)->c_iflag); \
+       put_user((termios)->c_oflag, &(termio)->c_oflag); \
+       put_user((termios)->c_cflag, &(termio)->c_cflag); \
+       put_user((termios)->c_lflag, &(termio)->c_lflag); \
+       put_user((termios)->c_line,  &(termio)->c_line); \
+       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif                         /* __KERNEL__ */
+
+#endif                         /* __BFIN_TERMIOS_H__ */
diff --git a/include/asm-blackfin/thread_info.h b/include/asm-blackfin/thread_info.h
new file mode 100644 (file)
index 0000000..fa8f08c
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * File:         include/asm-blackfin/thread_info.h
+ * Based on:     include/asm-m68knommu/thread_info.h
+ * Author:       LG Soft India
+ *               Copyright (C) 2004-2005 Analog Devices Inc.
+ * Created:      Tue Sep 21 2004
+ * Description:  Blackfin low-level thread information
+ * Modified:
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#include <asm/page.h>
+#include <asm/entry.h>
+#include <asm/l1layout.h>
+#include <linux/compiler.h>
+
+#ifdef __KERNEL__
+
+/* Thread Align Mask to reach to the top of the stack
+ * for any process
+ */
+#define ALIGN_PAGE_MASK         0xffffe000
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_segment_t;
+
+/*
+ * low level task data.
+ * If you change this, change the TI_* offsets below to match.
+ */
+
+struct thread_info {
+       struct task_struct *task;       /* main task structure */
+       struct exec_domain *exec_domain;        /* execution domain */
+       unsigned long flags;    /* low level flags */
+       int cpu;                /* cpu we're on */
+       int preempt_count;      /* 0 => preemptable, <0 => BUG */
+       mm_segment_t addr_limit;        /* address limit */
+       struct restart_block restart_block;
+       struct l1_scratch_task_info l1_task_info;
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#define INIT_THREAD_INFO(tsk)                  \
+{                                              \
+       .task           = &tsk,                 \
+       .exec_domain    = &default_exec_domain, \
+       .flags          = 0,                    \
+       .cpu            = 0,                    \
+       .preempt_count  = 1,                    \
+       .restart_block  = {                     \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
+}
+#define init_thread_info       (init_thread_union.thread_info)
+#define init_stack             (init_thread_union.stack)
+
+/*
+ * Size of kernel stack for each process. This must be a power of 2...
+ */
+#define THREAD_SIZE            8192    /* 2 pages */
+
+/* How to get the thread information struct from C */
+
+static inline struct thread_info *current_thread_info(void)
+    __attribute__ ((__const__));
+
+/* Given a task stack pointer, you can find it's task structure
+ * just by masking it to the 8K boundary.
+ */
+static inline struct thread_info *current_thread_info(void)
+{
+       struct thread_info *ti;
+      __asm__("%0 = sp;": "=&d"(ti):
+       );
+       return (struct thread_info *)((long)ti & ~8191UL);
+}
+
+/* thread information allocation */
+#define alloc_thread_info(tsk) ((struct thread_info *) \
+                               __get_free_pages(GFP_KERNEL, 1))
+#define free_thread_info(ti)   free_pages((unsigned long) (ti), 1)
+#endif                         /* __ASSEMBLY__ */
+
+/*
+ * Offsets in thread_info structure, used in assembly code
+ */
+#define TI_TASK                0
+#define TI_EXECDOMAIN  4
+#define TI_FLAGS       8
+#define TI_CPU         12
+#define TI_PREEMPT     16
+
+#define        PREEMPT_ACTIVE  0x4000000
+
+/*
+ * thread information flag bit numbers
+ */
+#define TIF_SYSCALL_TRACE      0       /* syscall trace active */
+#define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
+#define TIF_SIGPENDING         2       /* signal pending */
+#define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_POLLING_NRFLAG     4       /* true if poll_idle() is polling
+                                          TIF_NEED_RESCHED */
+#define TIF_MEMDIE              5
+#define TIF_RESTORE_SIGMASK    6       /* restore signal mask in do_signal() */
+#define TIF_FREEZE              7       /* is freezing for suspend */
+
+/* as above, but as bit values */
+#define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE             (1<<TIF_FREEZE)
+
+#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
+
+#endif                         /* __KERNEL__ */
+
+#endif                         /* _ASM_THREAD_INFO_H */
diff --git a/include/asm-blackfin/timex.h b/include/asm-blackfin/timex.h
new file mode 100644 (file)
index 0000000..8285901
--- /dev/null
@@ -0,0 +1,18 @@
+/* blackfin architecture timex specifications: Lineo Inc. 2001
+ *
+ * Based on: include/asm-m68knommu/timex.h
+ */
+
+#ifndef _ASMBLACKFIN_TIMEX_H
+#define _ASMBLACKFIN_TIMEX_H
+
+#define CLOCK_TICK_RATE        1000000 /* Underlying HZ */
+
+typedef unsigned long cycles_t;
+
+static inline cycles_t get_cycles(void)
+{
+       return 0;
+}
+
+#endif
diff --git a/include/asm-blackfin/tlb.h b/include/asm-blackfin/tlb.h
new file mode 100644 (file)
index 0000000..89a12ee
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _BLACKFIN_TLB_H
+#define _BLACKFIN_TLB_H
+
+#define tlb_start_vma(tlb, vma)        do { } while (0)
+#define tlb_end_vma(tlb, vma)  do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)     do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it
+ * fills up.
+ */
+#define tlb_flush(tlb)         flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif                         /* _BLACKFIN_TLB_H */
diff --git a/include/asm-blackfin/tlbflush.h b/include/asm-blackfin/tlbflush.h
new file mode 100644 (file)
index 0000000..10a07ba
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _BLACKFIN_TLBFLUSH_H
+#define _BLACKFIN_TLBFLUSH_H
+
+/*
+ * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
+ * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
+ */
+
+#include <asm/setup.h>
+
+/*
+ * flush all user-space atc entries.
+ */
+static inline void __flush_tlb(void)
+{
+       BUG();
+}
+
+static inline void __flush_tlb_one(unsigned long addr)
+{
+       BUG();
+}
+
+#define flush_tlb() __flush_tlb()
+
+/*
+ * flush all atc entries (both kernel and user-space entries).
+ */
+static inline void flush_tlb_all(void)
+{
+       BUG();
+}
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+       BUG();
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                                 unsigned long addr)
+{
+       BUG();
+}
+
+static inline void flush_tlb_range(struct mm_struct *mm,
+                                  unsigned long start, unsigned long end)
+{
+       BUG();
+}
+
+static inline void flush_tlb_kernel_page(unsigned long addr)
+{
+       BUG();
+}
+
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+                                     unsigned long start, unsigned long end)
+{
+       BUG();
+}
+
+#endif
diff --git a/include/asm-blackfin/topology.h b/include/asm-blackfin/topology.h
new file mode 100644 (file)
index 0000000..acee239
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_BLACKFIN_TOPOLOGY_H
+#define _ASM_BLACKFIN_TOPOLOGY_H
+
+#include <asm-generic/topology.h>
+
+#endif                         /* _ASM_BLACKFIN_TOPOLOGY_H */
diff --git a/include/asm-blackfin/traps.h b/include/asm-blackfin/traps.h
new file mode 100644 (file)
index 0000000..fe365b1
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  linux/include/asm/traps.h
+ *
+ *  Copyright (C) 1993        Hamish Macdonald
+ *
+ *  Lineo, Inc    Jul 2001    Tony Kou
+ *
+ * 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.
+ */
+
+#ifndef _BFIN_TRAPS_H
+#define _BFIN_TRAPS_H
+
+#define VEC_SYS                (0)
+#define VEC_EXCPT01    (1)
+#define VEC_EXCPT02    (2)
+#define VEC_EXCPT03    (3)
+#define VEC_EXCPT04    (4)
+#define VEC_EXCPT05    (5)
+#define VEC_EXCPT06    (6)
+#define VEC_EXCPT07    (7)
+#define VEC_EXCPT08    (8)
+#define VEC_EXCPT09    (9)
+#define VEC_EXCPT10    (10)
+#define VEC_EXCPT11    (11)
+#define VEC_EXCPT12    (12)
+#define VEC_EXCPT13    (13)
+#define VEC_EXCPT14    (14)
+#define VEC_EXCPT15    (15)
+#define VEC_STEP       (16)
+#define VEC_OVFLOW     (17)
+#define VEC_UNDEF_I    (33)
+#define VEC_ILGAL_I    (34)
+#define VEC_CPLB_VL    (35)
+#define VEC_MISALI_D   (36)
+#define VEC_UNCOV      (37)
+#define VEC_CPLB_M     (38)
+#define VEC_CPLB_MHIT  (39)
+#define VEC_WATCH      (40)
+#define VEC_ISTRU_VL   (41)    /*ADSP-BF535 only (MH) */
+#define VEC_MISALI_I   (42)
+#define VEC_CPLB_I_VL  (43)
+#define VEC_CPLB_I_M   (44)
+#define VEC_CPLB_I_MHIT        (45)
+#define VEC_ILL_RES    (46)    /* including unvalid supervisor mode insn */
+
+#ifndef __ASSEMBLY__
+
+#define HWC_x2 "System MMR Error\nAn error occurred due to an invalid access to an System MMR location\nPossible reason: a 32-bit register is accessed with a 16-bit instruction,\nor a 16-bit register is accessed with a 32-bit instruction.\n"
+#define HWC_x3 "External Memory Addressing Error\n"
+#define HWC_x12 "Performance Monitor Overflow\n"
+#define HWC_x18 "RAISE 5 instruction\n Software issued a RAISE 5 instruction to invoke the Hardware\n"
+#define HWC_default "Reserved\n"
+
+#define EXC_0x03 "Application stack overflow\n - Please increase the stack size of the application using elf2flt -s option,\n and/or reduce the stack use of the application.\n"
+#define EXC_0x10 "Single step\n - When the processor is in single step mode, every instruction\n generates an exception. Primarily used for debugging.\n"
+#define EXC_0x11 "Exception caused by a trace buffer full condition\n - The processor takes this exception when the trace\n buffer overflows (only when enabled by the Trace Unit Control register).\n"
+#define EXC_0x21 "Undefined instruction\n - May be used to emulate instructions that are not defined for\n a particular processor implementation.\n"
+#define EXC_0x22 "Illegal instruction combination\n - See section for multi-issue rules in the ADSP-BF53x Blackfin\n Processor Instruction Set Reference.\n"
+#define EXC_0x23 "Data access CPLB protection violation\n - Attempted read or write to Supervisor resource,\n or illegal data memory access. \n"
+#define EXC_0x24 "Data access misaligned address violation\n - Attempted misaligned data memory or data cache access.\n"
+#define EXC_0x25 "Unrecoverable event\n - For example, an exception generated while processing a previous exception.\n"
+#define EXC_0x26 "Data access CPLB miss\n - Used by the MMU to signal a CPLB miss on a data access.\n"
+#define EXC_0x27 "Data access multiple CPLB hits\n - More than one CPLB entry matches data fetch address.\n"
+#define EXC_0x28 "Program Sequencer Exception caused by an emulation watchpoint match\n - There is a watchpoint match, and one of the EMUSW\n bits in the Watchpoint Instruction Address Control register (WPIACTL) is set.\n"
+#define EXC_0x2A "Instruction fetch misaligned address violation\n - Attempted misaligned instruction cache fetch. On a misaligned instruction fetch exception,\n the return address provided in RETX is the destination address which is misaligned, rather than the address of the offending instruction.\n"
+#define EXC_0x2B "CPLB protection violation\n - Illegal instruction fetch access (memory protection violation).\n"
+#define EXC_0x2C "Instruction fetch CPLB miss\n - CPLB miss on an instruction fetch.\n"
+#define EXC_0x2D "Instruction fetch multiple CPLB hits\n - More than one CPLB entry matches instruction fetch address.\n"
+#define EXC_0x2E "Illegal use of supervisor resource\n - Attempted to use a Supervisor register or instruction from User mode.\n Supervisor resources are registers and instructions that are reserved\n for Supervisor use: Supervisor only registers, all MMRs, and Supervisor\n only instructions.\n"
+
+#endif                         /* __ASSEMBLY__ */
+#endif                         /* _BFIN_TRAPS_H */
diff --git a/include/asm-blackfin/types.h b/include/asm-blackfin/types.h
new file mode 100644 (file)
index 0000000..36f8dc8
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef _BFIN_TYPES_H
+#define _BFIN_TYPES_H
+
+/*
+ * This file is never included by application software unless
+ * explicitly requested (e.g., via linux/types.h) in which case the
+ * application is Linux specific so (user-) name space pollution is
+ * not a major issue.  However, for interoperability, libraries still
+ * need to be careful to avoid a name clashes.
+ */
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/* HK0617   -- Changes to unsigned long temporarily */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+#endif                         /* __ASSEMBLY__ */
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#define BITS_PER_LONG 32
+
+#ifndef __ASSEMBLY__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+typedef u64 dma64_addr_t;
+
+#endif                         /* __ASSEMBLY__ */
+
+#endif                         /* __KERNEL__ */
+
+#endif                         /* _BFIN_TYPES_H */
diff --git a/include/asm-blackfin/uaccess.h b/include/asm-blackfin/uaccess.h
new file mode 100644 (file)
index 0000000..bfcb679
--- /dev/null
@@ -0,0 +1,271 @@
+/* Changes made by Lineo Inc.    May 2001
+ *
+ * Based on: include/asm-m68knommu/uaccess.h
+ */
+
+#ifndef __BLACKFIN_UACCESS_H
+#define __BLACKFIN_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include <asm/segment.h>
+#ifndef CONFIG_NO_ACCESS_CHECK
+# include <asm/bfin-global.h>
+#endif
+
+#define get_ds()        (KERNEL_DS)
+#define get_fs()        (current_thread_info()->addr_limit)
+
+static inline void set_fs(mm_segment_t fs)
+{
+       current_thread_info()->addr_limit = fs;
+}
+
+#define segment_eq(a,b) ((a) == (b))
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
+
+static inline int is_in_rom(unsigned long addr)
+{
+       /*
+        * What we are really trying to do is determine if addr is
+        * in an allocated kernel memory region. If not then assume
+        * we cannot free it or otherwise de-allocate it. Ideally
+        * we could restrict this to really being in a ROM or flash,
+        * but that would need to be done on a board by board basis,
+        * not globally.
+        */
+       if ((addr < _ramstart) || (addr >= _ramend))
+               return (1);
+
+       /* Default case, not in ROM */
+       return (0);
+}
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ */
+
+#ifdef CONFIG_NO_ACCESS_CHECK
+static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; }
+#else
+#ifdef CONFIG_ACCESS_OK_L1
+extern int _access_ok(unsigned long addr, unsigned long size)__attribute__((l1_text));
+#else
+extern int _access_ok(unsigned long addr, unsigned long size);
+#endif
+#endif
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+       unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ */
+
+#define put_user(x,p)                                          \
+       ({                                                      \
+               int _err = 0;                                   \
+               typeof(*(p)) _x = (x);                          \
+               typeof(*(p)) *_p = (p);                         \
+               if (!access_ok(VERIFY_WRITE, _p, sizeof(*(_p)))) {\
+                       _err = -EFAULT;                         \
+               }                                               \
+               else {                                          \
+               switch (sizeof (*(_p))) {                       \
+               case 1:                                         \
+                       __put_user_asm(_x, _p, B);              \
+                       break;                                  \
+               case 2:                                         \
+                       __put_user_asm(_x, _p, W);              \
+                       break;                                  \
+               case 4:                                         \
+                       __put_user_asm(_x, _p,  );              \
+                       break;                                  \
+               case 8: {                                       \
+                       long _xl, _xh;                          \
+                       _xl = ((long *)&_x)[0];                 \
+                       _xh = ((long *)&_x)[1];                 \
+                       __put_user_asm(_xl, ((long *)_p)+0, );  \
+                       __put_user_asm(_xh, ((long *)_p)+1, );  \
+               } break;                                        \
+               default:                                        \
+                       _err = __put_user_bad();                \
+                       break;                                  \
+               }                                               \
+               }                                               \
+               _err;                                           \
+       })
+
+#define __put_user(x,p) put_user(x,p)
+static inline int bad_user_access_length(void)
+{
+       panic("bad_user_access_length");
+       return -1;
+}
+
+#define __put_user_bad() (printk(KERN_INFO "put_user_bad %s:%d %s\n",\
+                           __FILE__, __LINE__, __FUNCTION__),\
+                           bad_user_access_length(), (-EFAULT))
+
+/*
+ * Tell gcc we read from memory instead of writing: this is because
+ * we do not write to any memory gcc knows about, so there are no
+ * aliasing issues.
+ */
+
+#define __ptr(x) ((unsigned long *)(x))
+
+#define __put_user_asm(x,p,bhw)                                \
+       __asm__ (#bhw"[%1] = %0;\n\t"                   \
+                : /* no outputs */                     \
+                :"d" (x),"a" (__ptr(p)) : "memory")
+
+#define get_user(x,p)                                                  \
+       ({                                                              \
+               int _err = 0;                                           \
+               typeof(*(p)) *_p = (p);                                 \
+               if (!access_ok(VERIFY_READ, _p, sizeof(*(_p)))) {       \
+                       _err = -EFAULT;                                 \
+               }                                                       \
+               else {                                                  \
+               switch (sizeof(*(_p))) {                                \
+               case 1:                                                 \
+                       __get_user_asm(x, _p, B,(Z));                   \
+                       break;                                          \
+               case 2:                                                 \
+                       __get_user_asm(x, _p, W,(Z));                   \
+                       break;                                          \
+               case 4:                                                 \
+                       __get_user_asm(x, _p,  , );                     \
+                       break;                                          \
+               case 8: {                                               \
+                       unsigned long _xl, _xh;                         \
+                       __get_user_asm(_xl, ((unsigned long *)_p)+0,  , ); \
+                       __get_user_asm(_xh, ((unsigned long *)_p)+1,  , ); \
+                       ((unsigned long *)&x)[0] = _xl;                 \
+                       ((unsigned long *)&x)[1] = _xh;                 \
+               } break;                                                \
+               default:                                                \
+                       x = 0;                                          \
+                       printk(KERN_INFO "get_user_bad: %s:%d %s\n",    \
+                              __FILE__, __LINE__, __FUNCTION__);       \
+                       _err = __get_user_bad();                        \
+                       break;                                          \
+               }                                                       \
+               }                                                       \
+               _err;                                                   \
+       })
+
+#define __get_user(x,p) get_user(x,p)
+
+#define __get_user_bad() (bad_user_access_length(), (-EFAULT))
+
+#define __get_user_asm(x,p,bhw,option)                         \
+       {                                                       \
+               unsigned long _tmp;                             \
+               __asm__ ("%0 =" #bhw "[%1]"#option";\n\t"       \
+                        : "=d" (_tmp)                          \
+                        : "a" (__ptr(p)));                     \
+               (x) = (__typeof__(*(p))) _tmp;                  \
+       }
+
+#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
+#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n))\
+                                                return retval; })
+
+#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n))\
+                                                   return retval; })
+
+static inline long copy_from_user(void *to,
+                                 const void __user * from, unsigned long n)
+{
+       if (access_ok(VERIFY_READ, from, n))
+               memcpy(to, from, n);
+       else
+               return n;
+       return 0;
+}
+
+static inline long copy_to_user(void *to,
+                               const void __user * from, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               memcpy(to, from, n);
+       else
+               return n;
+       return 0;
+}
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+static inline long strncpy_from_user(char *dst,
+                                     const char *src, long count)
+{
+       char *tmp;
+       if (!access_ok(VERIFY_READ, src, 1))
+               return -EFAULT;
+       strncpy(dst, src, count);
+       for (tmp = dst; *tmp && count > 0; tmp++, count--) ;
+       return (tmp - dst);
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+static inline long strnlen_user(const char *src, long n)
+{
+       return (strlen(src) + 1);
+}
+
+#define strlen_user(str) strnlen_user(str, 32767)
+
+/*
+ * Zero Userspace
+ */
+
+static inline unsigned long __clear_user(void *to, unsigned long n)
+{
+       memset(to, 0, n);
+       return 0;
+}
+
+#define clear_user(to, n) __clear_user(to, n)
+
+#endif                         /* _BLACKFIN_UACCESS_H */
diff --git a/include/asm-blackfin/ucontext.h b/include/asm-blackfin/ucontext.h
new file mode 100644 (file)
index 0000000..4a4e385
--- /dev/null
@@ -0,0 +1,17 @@
+/** Changes made by Tony Kou   Lineo Inc.    May 2001
+ *
+ *  Based on: include/m68knommu/ucontext.h
+ */
+
+#ifndef _BLACKFIN_UCONTEXT_H
+#define _BLACKFIN_UCONTEXT_H
+
+struct ucontext {
+       unsigned long uc_flags; /* the others are necessary */
+       struct ucontext *uc_link;
+       stack_t uc_stack;
+       struct sigcontext uc_mcontext;
+       sigset_t uc_sigmask;    /* mask last for extensibility */
+};
+
+#endif                         /* _BLACKFIN_UCONTEXT_H */
diff --git a/include/asm-blackfin/unaligned.h b/include/asm-blackfin/unaligned.h
new file mode 100644 (file)
index 0000000..10081dc
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __BFIN_UNALIGNED_H
+#define __BFIN_UNALIGNED_H
+
+#include <asm-generic/unaligned.h>
+
+#endif                         /* __BFIN_UNALIGNED_H */
diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h
new file mode 100644 (file)
index 0000000..4df8790
--- /dev/null
@@ -0,0 +1,382 @@
+#ifndef __ASM_BFIN_UNISTD_H
+#define __ASM_BFIN_UNISTD_H
+/*
+ * This file contains the system call numbers.
+ */
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+                               /* 7 __NR_waitpid obsolete */
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_chown              16
+                               /* 17 __NR_break obsolete */
+                               /* 18 __NR_oldstat obsolete */
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+                               /* 22 __NR_umount obsolete */
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+                               /* 28 __NR_oldfstat obsolete */
+#define __NR_pause              29
+                               /* 30 __NR_utime obsolete */
+                               /* 31 __NR_stty obsolete */
+                               /* 32 __NR_gtty obsolete */
+#define __NR_access             33
+#define __NR_nice               34
+                               /* 35 __NR_ftime obsolete */
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+                               /* 44 __NR_prof obsolete */
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+                               /* 48 __NR_signal obsolete */
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+                               /* 53 __NR_lock obsolete */
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+                               /* 56 __NR_mpx obsolete */
+#define __NR_setpgid            57
+                               /* 58 __NR_ulimit obsolete */
+                               /* 59 __NR_oldolduname obsolete */
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+                               /* 67 __NR_sigaction obsolete */
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+                               /* 72 __NR_sigsuspend obsolete */
+                               /* 73 __NR_sigpending obsolete */
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+                               /* 76 __NR_old_getrlimit obsolete */
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+                               /* 82 __NR_select obsolete */
+#define __NR_symlink            83
+                               /* 84 __NR_oldlstat obsolete */
+#define __NR_readlink           85
+                               /* 86 __NR_uselib obsolete */
+                               /* 87 __NR_swapon obsolete */
+#define __NR_reboot             88
+                               /* 89 __NR_readdir obsolete */
+                               /* 90 __NR_mmap obsolete */
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+                               /* 98 __NR_profil obsolete */
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+                               /* 101 __NR_ioperm */
+                               /* 102 __NR_socketcall obsolete */
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+                               /* 109 __NR_olduname obsolete */
+                               /* 110 __NR_iopl obsolete */
+#define __NR_vhangup           111
+                               /* 112 __NR_idle obsolete */
+                               /* 113 __NR_vm86old */
+#define __NR_wait4             114
+                               /* 115 __NR_swapoff obsolete */
+#define __NR_sysinfo           116
+                               /* 117 __NR_ipc oboslete */
+#define __NR_fsync             118
+                               /* 119 __NR_sigreturn obsolete */
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+                               /* 123 __NR_modify_ldt obsolete */
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+                               /* 126 __NR_sigprocmask obsolete */
+                               /* 127 __NR_create_module obsolete */
+#define __NR_init_module       128
+#define __NR_delete_module     129
+                               /* 130 __NR_get_kernel_syms obsolete */
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+                               /* 135 was sysfs */
+#define __NR_personality       136
+                               /* 137 __NR_afs_syscall */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+                               /* 142 __NR__newselect obsolete */
+#define __NR_flock             143
+                               /* 144 __NR_msync obsolete */
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+                               /* 150 __NR_mlock */
+                               /* 151 __NR_munlock */
+                               /* 152 __NR_mlockall */
+                               /* 153 __NR_munlockall */
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+                               /* 163 __NR_mremap */
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+                               /* 166 __NR_vm86 */
+                               /* 167 __NR_query_module */
+                               /* 168 __NR_poll */
+                               /* 169 __NR_nfsservctl */
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl             172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread             180
+#define __NR_pwrite            181
+#define __NR_lchown            182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+                               /* 188 __NR_getpmsg */
+                               /* 189 __NR_putpmsg */
+#define __NR_vfork             190
+#define __NR_getrlimit         191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+                               /* 218 __NR_mincore */
+                               /* 219 __NR_madvise */
+#define __NR_getdents64                220
+#define __NR_fcntl64           221
+                               /* 222 reserved for TUX */
+                               /* 223 reserved for TUX */
+#define __NR_gettid            224
+                               /* 225 __NR_readahead */
+#define __NR_setxattr          226
+#define __NR_lsetxattr         227
+#define __NR_fsetxattr         228
+#define __NR_getxattr          229
+#define __NR_lgetxattr         230
+#define __NR_fgetxattr         231
+#define __NR_listxattr         232
+#define __NR_llistxattr                233
+#define __NR_flistxattr                234
+#define __NR_removexattr       235
+#define __NR_lremovexattr      236
+#define __NR_fremovexattr      237
+#define __NR_tkill             238
+#define __NR_sendfile64                239
+#define __NR_futex             240
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+                               /* 243 __NR_set_thread_area */
+                               /* 244 __NR_get_thread_area */
+#define __NR_io_setup          245
+#define __NR_io_destroy                246
+#define __NR_io_getevents      247
+#define __NR_io_submit         248
+#define __NR_io_cancel         249
+                               /* 250 __NR_alloc_hugepages */
+                               /* 251 __NR_free_hugepages */
+#define __NR_exit_group                252
+#define __NR_lookup_dcookie     253
+#define __NR_bfin_spinlock      254
+
+#define __NR_epoll_create      255
+#define __NR_epoll_ctl         256
+#define __NR_epoll_wait                257
+                               /* 258 __NR_remap_file_pages */
+#define __NR_set_tid_address   259
+#define __NR_timer_create      260
+#define __NR_timer_settime     (__NR_timer_create+1)
+#define __NR_timer_gettime     (__NR_timer_create+2)
+#define __NR_timer_getoverrun  (__NR_timer_create+3)
+#define __NR_timer_delete      (__NR_timer_create+4)
+#define __NR_clock_settime     (__NR_timer_create+5)
+#define __NR_clock_gettime     (__NR_timer_create+6)
+#define __NR_clock_getres      (__NR_timer_create+7)
+#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_statfs64          269
+#define __NR_fstatfs64         270
+#define __NR_tgkill            271
+#define __NR_utimes            272
+#define __NR_fadvise64_64      273
+                               /* 274 __NR_vserver */
+                               /* 275 __NR_mbind */
+                               /* 276 __NR_get_mempolicy */
+                               /* 277 __NR_set_mempolicy */
+#define __NR_mq_open           278
+#define __NR_mq_unlink         (__NR_mq_open+1)
+#define __NR_mq_timedsend      (__NR_mq_open+2)
+#define __NR_mq_timedreceive   (__NR_mq_open+3)
+#define __NR_mq_notify         (__NR_mq_open+4)
+#define __NR_mq_getsetattr     (__NR_mq_open+5)
+                               /* 284 __NR_sys_kexec_load */
+#define __NR_waitid            285
+#define __NR_add_key           286
+#define __NR_request_key       287
+#define __NR_keyctl            288
+#define __NR_ioprio_set                289
+#define __NR_ioprio_get                290
+#define __NR_inotify_init      291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch  293
+                               /* 294 __NR_migrate_pages */
+#define __NR_openat            295
+#define __NR_mkdirat           296
+#define __NR_mknodat           297
+#define __NR_fchownat          298
+#define __NR_futimesat         299
+#define __NR_fstatat64         300
+#define __NR_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#define __NR_faccessat         307
+#define __NR_pselect6          308
+#define __NR_ppoll             309
+#define __NR_unshare           310
+
+/* Blackfin private syscalls */
+#define __NR_sram_alloc                311
+#define __NR_sram_free         312
+#define __NR_dma_memcpy                313
+
+/* socket syscalls */
+#define __NR_accept            314
+#define __NR_bind              315
+#define __NR_connect           316
+#define __NR_getpeername       317
+#define __NR_getsockname       318
+#define __NR_getsockopt                319
+#define __NR_listen            320
+#define __NR_recv              321
+#define __NR_recvfrom          322
+#define __NR_recvmsg           323
+#define __NR_send              324
+#define __NR_sendmsg           325
+#define __NR_sendto            326
+#define __NR_setsockopt                327
+#define __NR_shutdown          328
+#define __NR_socket            329
+#define __NR_socketpair                330
+
+/* sysv ipc syscalls */
+#define __NR_semctl            331
+#define __NR_semget            332
+#define __NR_semop             333
+#define __NR_msgctl            334
+#define __NR_msgget            335
+#define __NR_msgrcv            336
+#define __NR_msgsnd            337
+#define __NR_shmat             338
+#define __NR_shmctl            339
+#define __NR_shmdt             340
+#define __NR_shmget            341
+
+#define __NR_syscall           342
+#define NR_syscalls            __NR_syscall
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#endif
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t_" #x "\n\t.set\t_" #x ",_sys_ni_syscall");
+
+#endif                         /* __ASM_BFIN_UNISTD_H */
diff --git a/include/asm-blackfin/user.h b/include/asm-blackfin/user.h
new file mode 100644 (file)
index 0000000..abc3462
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef _BFIN_USER_H
+#define _BFIN_USER_H
+
+/* Changes by Tony Kou   Lineo, Inc.  July, 2001
+ *
+ * Based include/asm-m68knommu/user.h
+ *
+ */
+
+/* Core file format: The core file is written in such a way that gdb
+   can understand it and provide useful information to the user (under
+   linux we use the 'trad-core' bfd).  There are quite a number of
+   obstacles to being able to view the contents of the floating point
+   registers, and until these are solved you will not be able to view the
+   contents of them.  Actually, you can read in the core file and look at
+   the contents of the user struct to find out what the floating point
+   registers contain.
+   The actual file contents are as follows:
+   UPAGE: 1 page consisting of a user struct that tells gdb what is present
+   in the file.  Directly after this is a copy of the task_struct, which
+   is currently not used by gdb, but it may come in useful at some point.
+   All of the registers are stored as part of the upage.  The upage should
+   always be only one page.
+   DATA: The data area is stored.  We use current->end_text to
+   current->brk to pick up all of the user variables, plus any memory
+   that may have been malloced.  No attempt is made to determine if a page
+   is demand-zero or if a page is totally unused, we just cover the entire
+   range.  All of the addresses are rounded in such a way that an integral
+   number of pages is written.
+   STACK: We need the stack information in order to get a meaningful
+   backtrace.  We need to write the data from (esp) to
+   current->start_stack, so we round each of these off in order to be able
+   to write an integer number of pages.
+   The minimum core file size is 3 pages, or 12288 bytes.
+*/
+struct user_bfinfp_struct {
+};
+
+/* This is the old layout of "struct pt_regs" as of Linux 1.x, and
+   is still the layout used by user (the new pt_regs doesn't have
+   all registers). */
+struct user_regs_struct {
+       long r0, r1, r2, r3, r4, r5, r6, r7;
+       long p0, p1, p2, p3, p4, p5, usp, fp;
+       long i0, i1, i2, i3;
+       long l0, l1, l2, l3;
+       long b0, b1, b2, b3;
+       long m0, m1, m2, m3;
+       long a0w, a1w;
+       long a0x, a1x;
+       unsigned long rets;
+       unsigned long astat;
+       unsigned long pc;
+       unsigned long orig_p0;
+};
+
+/* When the kernel dumps core, it starts by dumping the user struct -
+   this will be used by gdb to figure out where the data and stack segments
+   are within the file, and what virtual addresses to use. */
+
+struct user {
+/* We start with the registers, to mimic the way that "memory" is returned
+   from the ptrace(3,...) function.  */
+
+       struct user_regs_struct regs;   /* Where the registers are actually stored */
+
+/* The rest of this junk is to help gdb figure out what goes where */
+       unsigned long int u_tsize;      /* Text segment size (pages). */
+       unsigned long int u_dsize;      /* Data segment size (pages). */
+       unsigned long int u_ssize;      /* Stack segment size (pages). */
+       unsigned long start_code;       /* Starting virtual address of text. */
+       unsigned long start_stack;      /* Starting virtual address of stack area.
+                                          This is actually the bottom of the stack,
+                                          the top of the stack is always found in the
+                                          esp register.  */
+       long int signal;        /* Signal that caused the core dump. */
+       int reserved;           /* No longer used */
+       struct user_regs_struct *u_ar0;
+       /* Used by gdb to help find the values for */
+       /* the registers. */
+       unsigned long magic;    /* To uniquely identify a core file */
+       char u_comm[32];        /* User command that was responsible */
+};
+#define NBPG PAGE_SIZE
+#define UPAGES 1
+#define HOST_TEXT_START_ADDR (u.start_code)
+#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
+
+#endif
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 42a3ac4..41be646 100644 (file)
@@ -61,6 +61,5 @@ static __inline__ int irq_canonicalize(int irq)
 
 extern void enable_irq(unsigned int);
 extern void disable_irq(unsigned int);
-#define disable_irq_nosync(x)  disable_irq(x)
 
 #endif /* _H8300_IRQ_H_ */
diff --git a/include/asm-h8300/irq_regs.h b/include/asm-h8300/irq_regs.h
new file mode 100644 (file)
index 0000000..3dd9c0b
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
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 8b7c685..ddd07f4 100644 (file)
@@ -73,4 +73,5 @@ extern int is_in_rom(unsigned long);
 #define        VMALLOC_START   0
 #define        VMALLOC_END     0xffffffff
 
+#define arch_enter_lazy_cpu_mode()    do {} while (0)
 #endif /* _H8300_PGTABLE_H */
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..e16359f 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
@@ -283,12 +296,25 @@ do {                                                                      \
        }                                                               \
 } while (0)
 
-/*
- * We don't actually have these, but we want to advertise them so that
- * we can encompass the flush here.
- */
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define ptep_test_and_clear_dirty(vma, addr, ptep) ({                  \
+       int ret = 0;                                                    \
+       if (pte_dirty(*ptep))                                           \
+               ret = test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); \
+       if (ret)                                                        \
+               pte_update_defer(vma->vm_mm, addr, ptep);               \
+       ret;                                                            \
+})
+
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define ptep_test_and_clear_young(vma, addr, ptep) ({                  \
+       int ret = 0;                                                    \
+       if (pte_young(*ptep))                                           \
+               ret = test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); \
+       if (ret)                                                        \
+               pte_update_defer(vma->vm_mm, addr, ptep);               \
+       ret;                                                            \
+})
 
 /*
  * Rules for using ptep_establish: the pte MUST be a user pte, and
@@ -305,12 +331,9 @@ do {                                                                       \
 #define ptep_clear_flush_dirty(vma, address, ptep)                     \
 ({                                                                     \
        int __dirty;                                                    \
-       __dirty = pte_dirty(*(ptep));                                   \
-       if (__dirty) {                                                  \
-               clear_bit(_PAGE_BIT_DIRTY, &(ptep)->pte_low);           \
-               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
+       __dirty = ptep_test_and_clear_dirty((vma), (address), (ptep));  \
+       if (__dirty)                                                    \
                flush_tlb_page(vma, address);                           \
-       }                                                               \
        __dirty;                                                        \
 })
 
@@ -318,19 +341,16 @@ do {                                                                      \
 #define ptep_clear_flush_young(vma, address, ptep)                     \
 ({                                                                     \
        int __young;                                                    \
-       __young = pte_young(*(ptep));                                   \
-       if (__young) {                                                  \
-               clear_bit(_PAGE_BIT_ACCESSED, &(ptep)->pte_low);        \
-               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
+       __young = ptep_test_and_clear_young((vma), (address), (ptep));  \
+       if (__young)                                                    \
                flush_tlb_page(vma, address);                           \
-       }                                                               \
        __young;                                                        \
 })
 
 #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 +360,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 +493,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 +519,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 4b187bb..bf01d4b 100644 (file)
@@ -95,12 +95,14 @@ static inline struct thread_info *current_thread_info(void)
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info(tsk) ((struct thread_info *) \
+       __get_free_pages(GFP_KERNEL| __GFP_ZERO, get_order(THREAD_SIZE)))
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info(tsk) ((struct thread_info *) \
+       __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)))
 #endif
 
-#define free_thread_info(info) kfree(info)
+#define free_thread_info(info) free_pages((unsigned long)(info), get_order(THREAD_SIZE))
 
 #else /* !__ASSEMBLY__ */
 
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 c22b465..c1642fd 100644 (file)
@@ -103,6 +103,16 @@ name:
 # define FSYS_RETURN   br.ret.sptk.many b6
 #endif
 
+/*
+ * If physical stack register size is different from DEF_NUM_STACK_REG,
+ * dynamically patch the kernel for correct size.
+ */
+       .section ".data.patch.phys_stack_reg", "a"
+       .previous
+#define LOAD_PHYS_STACK_REG_SIZE(reg)                  \
+[1:]   adds reg=IA64_NUM_PHYS_STACK_REG*8+8,r0;        \
+       .xdata4 ".data.patch.phys_stack_reg", 1b-.
+
 /*
  * Up until early 2004, use of .align within a function caused bad unwind info.
  * TEXT_ALIGN(n) expands into ".align n" if a fixed GAS is available or into nothing
index 6311e16..eb17a86 100644 (file)
@@ -421,11 +421,7 @@ __writeq (unsigned long val, volatile void __iomem *addr)
 
 extern void __iomem * ioremap(unsigned long offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
-
-static inline void
-iounmap (volatile void __iomem *addr)
-{
-}
+extern void iounmap (volatile void __iomem *addr);
 
 /* Use normal IO mappings for DMI */
 #define dmi_ioremap ioremap
index 221b5cb..7e55a58 100644 (file)
@@ -29,8 +29,7 @@
  */
 #define IA64_TR_KERNEL         0       /* itr0, dtr0: maps kernel image (code & data) */
 #define IA64_TR_PALCODE                1       /* itr1: maps PALcode as required by EFI */
-#define IA64_TR_PERCPU_DATA    1       /* dtr1: percpu data */
-#define IA64_TR_CURRENT_STACK  2       /* dtr2: maps kernel's memory- & register-stacks */
+#define IA64_TR_CURRENT_STACK  1       /* dtr1: maps kernel's memory- & register-stacks */
 
 /* Processor status register bits: */
 #define IA64_PSR_BE_BIT                1
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 67656ce..abfcb3a 100644 (file)
@@ -89,6 +89,8 @@
 #define PAL_GET_PSTATE_TYPE_AVGNORESET 2
 #define PAL_GET_PSTATE_TYPE_INSTANT    3
 
+#define PAL_MC_ERROR_INJECT    276     /* Injects processor error or returns injection capabilities */
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -1235,6 +1237,37 @@ ia64_pal_mc_error_info (u64 info_index, u64 type_index, u64 *size, u64 *error_in
        return iprv.status;
 }
 
+/* Injects the requested processor error or returns info on
+ * supported injection capabilities for current processor implementation
+ */
+static inline s64
+ia64_pal_mc_error_inject_phys (u64 err_type_info, u64 err_struct_info,
+                       u64 err_data_buffer, u64 *capabilities, u64 *resources)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL_PHYS_STK(iprv, PAL_MC_ERROR_INJECT, err_type_info,
+                         err_struct_info, err_data_buffer);
+       if (capabilities)
+               *capabilities= iprv.v0;
+       if (resources)
+               *resources= iprv.v1;
+       return iprv.status;
+}
+
+static inline s64
+ia64_pal_mc_error_inject_virt (u64 err_type_info, u64 err_struct_info,
+                       u64 err_data_buffer, u64 *capabilities, u64 *resources)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL_STK(iprv, PAL_MC_ERROR_INJECT, err_type_info,
+                         err_struct_info, err_data_buffer);
+       if (capabilities)
+               *capabilities= iprv.v0;
+       if (resources)
+               *resources= iprv.v1;
+       return iprv.status;
+}
+
 /* Inform PALE_CHECK whether a machine check is expected so that PALE_CHECK willnot
  * attempt to correct any expected machine checks.
  */
index 4797f35..a715430 100644 (file)
@@ -20,6 +20,7 @@ extern void ia64_patch_imm60 (u64 insn_addr, u64 val);                /* patch "brl" w/ip-rel
 
 extern void ia64_patch_mckinley_e9 (unsigned long start, unsigned long end);
 extern void ia64_patch_vtop (unsigned long start, unsigned long end);
+extern void ia64_patch_phys_stack_reg(unsigned long val);
 extern void ia64_patch_gate (void);
 
 #endif /* _ASM_IA64_PATCH_H */
index 4f4ee1c..db81ba4 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/ptrace.h>
 #include <asm/ustack.h>
 
+#define IA64_NUM_PHYS_STACK_REG        96
 #define IA64_NUM_DBG_REGS      8
 
 #define DEFAULT_MAP_BASE       __IA64_UL_CONST(0x2000000000000000)
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 e9eb7f6..dc42a35 100644 (file)
@@ -11,6 +11,7 @@
 extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
 extern char __start___vtop_patchlist[], __end___vtop_patchlist[];
 extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
+extern char __start___phys_stack_reg_patchlist[], __end___phys_stack_reg_patchlist[];
 extern char __start_gate_section[];
 extern char __start_gate_mckinley_e9_patchlist[], __end_gate_mckinley_e9_patchlist[];
 extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[];
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 09bb7b0..3f8c12f 100644 (file)
@@ -9,6 +9,4 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-#include <asm-generic/dma-mapping-broken.h>
-
 #endif /* _ASM_DMA_MAPPING_H */
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 2f89dd0..794c36d 100644 (file)
@@ -2,50 +2,80 @@
 #define __ASM_SH_BUG_H
 
 #ifdef CONFIG_BUG
-
-struct bug_frame {
-       unsigned short  opcode;
-       unsigned short  line;
-       const char      *file;
-       const char      *func;
-};
-
-struct pt_regs;
-
-extern void handle_BUG(struct pt_regs *);
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_WARN_ON
 
 #define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
 
+/**
+ * _EMIT_BUG_ENTRY
+ * %1 - __FILE__
+ * %2 - __LINE__
+ * %3 - trap type
+ * %4 - sizeof(struct bug_entry)
+ *
+ * The trapa opcode itself sits in %0.
+ * The %O notation is used to avoid # generation.
+ *
+ * The offending file and line are encoded in the __bug_table section.
+ */
 #ifdef CONFIG_DEBUG_BUGVERBOSE
+#define _EMIT_BUG_ENTRY                                \
+       "\t.pushsection __bug_table,\"a\"\n"    \
+       "2:\t.long 1b, %O1\n"                   \
+       "\t.short %O2, %O3\n"                   \
+       "\t.org 2b+%O4\n"                       \
+       "\t.popsection\n"
+#else
+#define _EMIT_BUG_ENTRY                                \
+       "\t.pushsection __bug_table,\"a\"\n"    \
+       "2:\t.long 1b\n"                        \
+       "\t.short %O3\n"                        \
+       "\t.org 2b+%O4\n"                       \
+       "\t.popsection\n"
+#endif
 
 #define BUG()                                          \
 do {                                                   \
        __asm__ __volatile__ (                          \
-               ".align 2\n\t"                          \
-               ".short %O0\n\t"                        \
-               ".short %O1\n\t"                        \
-               ".long  %O2\n\t"                        \
-               ".long  %O3\n\t"                        \
-               :                                       \
-               : "n" (TRAPA_BUG_OPCODE),               \
-                 "i" (__LINE__), "X" (__FILE__),       \
-                 "X" (__FUNCTION__));                  \
+               "1:\t.short %O0\n"                      \
+               _EMIT_BUG_ENTRY                         \
+                :                                      \
+                : "n" (TRAPA_BUG_OPCODE),              \
+                  "i" (__FILE__),                      \
+                  "i" (__LINE__), "i" (0),             \
+                  "i" (sizeof(struct bug_entry)));     \
 } while (0)
 
-#else
-
-#define BUG()                                  \
-do {                                           \
-       __asm__ __volatile__ (                  \
-               ".align 2\n\t"                  \
-               ".short %O0\n\t"                \
-               :                               \
-               : "n" (TRAPA_BUG_OPCODE));      \
+#define __WARN()                                       \
+do {                                                   \
+       __asm__ __volatile__ (                          \
+               "1:\t.short %O0\n"                      \
+                _EMIT_BUG_ENTRY                        \
+                :                                      \
+                : "n" (TRAPA_BUG_OPCODE),              \
+                  "i" (__FILE__),                      \
+                  "i" (__LINE__),                      \
+                  "i" (BUGFLAG_WARNING),               \
+                  "i" (sizeof(struct bug_entry)));     \
 } while (0)
 
-#endif /* CONFIG_DEBUG_BUGVERBOSE */
+#define WARN_ON(x) ({                                          \
+       typeof(x) __ret_warn_on = (x);                          \
+       if (__builtin_constant_p(__ret_warn_on)) {              \
+               if (__ret_warn_on)                              \
+                       __WARN();                               \
+       } else {                                                \
+               if (unlikely(__ret_warn_on))                    \
+                       __WARN();                               \
+       }                                                       \
+       unlikely(__ret_warn_on);                                \
+})
 
-#define HAVE_ARCH_BUG
+struct pt_regs;
+
+/* arch/sh/kernel/traps.c */
+void handle_BUG(struct pt_regs *);
 
 #endif /* CONFIG_BUG */
 
index 1df9280..386d797 100644 (file)
@@ -13,7 +13,7 @@ struct clk_ops {
        void (*enable)(struct clk *clk);
        void (*disable)(struct clk *clk);
        void (*recalc)(struct clk *clk);
-       int (*set_rate)(struct clk *clk, unsigned long rate);
+       int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
 };
 
 struct clk {
@@ -48,6 +48,34 @@ void clk_recalc_rate(struct clk *);
 int clk_register(struct clk *);
 void clk_unregister(struct clk *);
 
-int show_clocks(struct seq_file *m);
+/* the exported API, in addition to clk_set_rate */
+/**
+ * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ * @algo_id: algorithm id to be passed down to ops->set_rate
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id);
 
+enum clk_sh_algo_id {
+       NO_CHANGE = 0,
+
+       IUS_N1_N1,
+       IUS_322,
+       IUS_522,
+       IUS_N11,
+
+       SB_N1,
+
+       SB3_N1,
+       SB3_32,
+       SB3_43,
+       SB3_54,
+
+       BP_N1,
+
+       IP_N1,
+};
 #endif /* __ASM_SH_CLOCK_H */
index bccb7dd..4704e86 100644 (file)
@@ -32,6 +32,7 @@
     defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300) || \
     defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7712) || \
     defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define INTEVT 0xa4000000      /* INTEVTE2(0xa4000000) */
 #else
index 602d061..86564e7 100644 (file)
 
 #if defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7722)
 #define FRQCR                  0xa4150000
+#define VCLKCR                 0xa4150004
+#define SCLKACR                        0xa4150008
+#define SCLKBCR                        0xa415000c
+#define IrDACLKCR              0xa4150010
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define        FRQCR                   0xffc80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
+#define FRQCR0                 0xffc80000
+#define FRQCR1                 0xffc80004
+#define FRQMR1                 0xffc80014
 #else
 #define FRQCR                  0xffc00000
 #endif
index afe188f..e81bf21 100644 (file)
@@ -2,94 +2,13 @@
 #define __ASM_SH_IRQ_H
 
 #include <asm/machvec.h>
-#include <asm/ptrace.h>                /* for pt_regs */
 
-/* NR_IRQS is made from three components:
- *   1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules
- *   2. PINT_NR_IRQS   - number of PINT interrupts
- *   3. OFFCHIP_NR_IRQS - numbe of IRQs from off-chip peripherial modules
+/*
+ * A sane default based on a reasonable vector table size, platforms are
+ * advised to cap this at the hard limit that they're interested in
+ * through the machvec.
  */
-
-/* 1. ONCHIP_NR_IRQS */
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
-# define ONCHIP_NR_IRQS 24     // Actually 21
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707)
-# define ONCHIP_NR_IRQS 64
-# define PINT_NR_IRQS   16
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-# define ONCHIP_NR_IRQS 32
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7705)
-# define ONCHIP_NR_IRQS 64     // Actually 61
-# define PINT_NR_IRQS   16
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
-# define ONCHIP_NR_IRQS 104
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750)
-# define ONCHIP_NR_IRQS 48     // Actually 44
-#elif defined(CONFIG_CPU_SUBTYPE_SH7751)
-# define ONCHIP_NR_IRQS 72
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define ONCHIP_NR_IRQS 112    /* XXX */
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define ONCHIP_NR_IRQS 72
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-# define ONCHIP_NR_IRQS 144
-#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-      defined(CONFIG_CPU_SUBTYPE_SH73180) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7343) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7722)
-# define ONCHIP_NR_IRQS 109
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-# define ONCHIP_NR_IRQS 111
-#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
-# define ONCHIP_NR_IRQS 256
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-# define ONCHIP_NR_IRQS 128
-#elif defined(CONFIG_SH_UNKNOWN)       /* Most be last */
-# define ONCHIP_NR_IRQS 144
-#endif
-
-/* 2. PINT_NR_IRQS */
-#ifdef CONFIG_SH_UNKNOWN
-# define PINT_NR_IRQS 16
-#else
-# ifndef PINT_NR_IRQS
-#  define PINT_NR_IRQS 0
-# endif
-#endif
-
-#if PINT_NR_IRQS > 0
-# define PINT_IRQ_BASE  ONCHIP_NR_IRQS
-#endif
-
-/* 3. OFFCHIP_NR_IRQS */
-#if defined(CONFIG_HD64461)
-# define OFFCHIP_NR_IRQS 18
-#elif defined(CONFIG_HD64465)
-# define OFFCHIP_NR_IRQS 16
-#elif defined (CONFIG_SH_DREAMCAST)
-# define OFFCHIP_NR_IRQS 96
-#elif defined (CONFIG_SH_TITAN)
-# define OFFCHIP_NR_IRQS 4
-#elif defined(CONFIG_SH_R7780RP)
-# define OFFCHIP_NR_IRQS 16
-#elif defined(CONFIG_SH_7343_SOLUTION_ENGINE)
-# define OFFCHIP_NR_IRQS 12
-#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
-# define OFFCHIP_NR_IRQS 14
-#elif defined(CONFIG_SH_UNKNOWN)
-# define OFFCHIP_NR_IRQS 16    /* Must also be last */
-#else
-# define OFFCHIP_NR_IRQS 0
-#endif
-
-#if OFFCHIP_NR_IRQS > 0
-# define OFFCHIP_IRQ_BASE (ONCHIP_NR_IRQS + PINT_NR_IRQS)
-#endif
-
-/* NR_IRQS. 1+2+3 */
-#define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS)
+#define NR_IRQS 256
 
 /*
  * Convert back and forth between INTEVT and IRQ values.
diff --git a/include/asm-sh/kdebug.h b/include/asm-sh/kdebug.h
new file mode 100644 (file)
index 0000000..ef009ba
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __ASM_SH_KDEBUG_H
+#define __ASM_SH_KDEBUG_H
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+       struct pt_regs *regs;
+       int trapnr;
+};
+
+int register_die_notifier(struct notifier_block *nb);
+int unregister_die_notifier(struct notifier_block *nb);
+int register_page_fault_notifier(struct notifier_block *nb);
+int unregister_page_fault_notifier(struct notifier_block *nb);
+extern struct atomic_notifier_head shdie_chain;
+
+/* Grossly misnamed. */
+enum die_val {
+       DIE_TRAP,
+       DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val, struct pt_regs *regs,
+                            int trap, int sig)
+{
+       struct die_args args = {
+               .regs = regs,
+               .trapnr = trap,
+       };
+
+       return atomic_notifier_call_chain(&shdie_chain, val, &args);
+}
+#endif /* __ASM_SH_KDEBUG_H */
index 9d235af..da36a75 100644 (file)
@@ -1,5 +1,8 @@
-#ifndef _SH_KEXEC_H
-#define _SH_KEXEC_H
+#ifndef __ASM_SH_KEXEC_H
+#define __ASM_SH_KEXEC_H
+
+#include <asm/ptrace.h>
+#include <asm/string.h>
 
 /*
  * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
 
 #define MAX_NOTE_BYTES 1024
 
-/* Provide a dummy definition to avoid build failures. */
 static inline void crash_setup_regs(struct pt_regs *newregs,
-                                       struct pt_regs *oldregs) { }
+                                   struct pt_regs *oldregs)
+{
+       if (oldregs)
+               memcpy(newregs, oldregs, sizeof(*newregs));
+       else {
+               __asm__ __volatile__ ("mov r0, %0" : "=r" (newregs->regs[0]));
+               __asm__ __volatile__ ("mov r1, %0" : "=r" (newregs->regs[1]));
+               __asm__ __volatile__ ("mov r2, %0" : "=r" (newregs->regs[2]));
+               __asm__ __volatile__ ("mov r3, %0" : "=r" (newregs->regs[3]));
+               __asm__ __volatile__ ("mov r4, %0" : "=r" (newregs->regs[4]));
+               __asm__ __volatile__ ("mov r5, %0" : "=r" (newregs->regs[5]));
+               __asm__ __volatile__ ("mov r6, %0" : "=r" (newregs->regs[6]));
+               __asm__ __volatile__ ("mov r7, %0" : "=r" (newregs->regs[7]));
+               __asm__ __volatile__ ("mov r8, %0" : "=r" (newregs->regs[8]));
+               __asm__ __volatile__ ("mov r9, %0" : "=r" (newregs->regs[9]));
+               __asm__ __volatile__ ("mov r10, %0" : "=r" (newregs->regs[10]));
+               __asm__ __volatile__ ("mov r11, %0" : "=r" (newregs->regs[11]));
+               __asm__ __volatile__ ("mov r12, %0" : "=r" (newregs->regs[12]));
+               __asm__ __volatile__ ("mov r13, %0" : "=r" (newregs->regs[13]));
+               __asm__ __volatile__ ("mov r14, %0" : "=r" (newregs->regs[14]));
+               __asm__ __volatile__ ("mov r15, %0" : "=r" (newregs->regs[15]));
+
+               __asm__ __volatile__ ("sts pr, %0" : "=r" (newregs->pr));
+               __asm__ __volatile__ ("sts macl, %0" : "=r" (newregs->macl));
+               __asm__ __volatile__ ("sts mach, %0" : "=r" (newregs->mach));
+
+               __asm__ __volatile__ ("stc gbr, %0" : "=r" (newregs->gbr));
+               __asm__ __volatile__ ("stc sr, %0" : "=r" (newregs->sr));
 
-#endif /* _SH_KEXEC_H */
+               newregs->pc = (unsigned long)current_text_addr();
+       }
+}
+#endif /* __ASM_SH_KEXEC_H */
index 0095c66..74bd095 100644 (file)
@@ -17,6 +17,7 @@
 #define __KGDB_H
 
 #include <asm/ptrace.h>
+#include <asm/cacheflush.h>
 
 struct console;
 
@@ -45,35 +46,21 @@ extern int kgdb_portnum;
 extern int kgdb_baud;
 extern char kgdb_parity;
 extern char kgdb_bits;
-extern int kgdb_console_setup(struct console *, char *);
 
 /* Init and interface stuff */
 extern int kgdb_init(void);
-extern int (*kgdb_serial_setup)(void);
 extern int (*kgdb_getchar)(void);
 extern void (*kgdb_putchar)(int);
 
-struct kgdb_sermap {
-       char *name;
-       int namelen;
-       int (*setup_fn)(struct console *, char *);
-       struct kgdb_sermap *next;
-};
-extern void kgdb_register_sermap(struct kgdb_sermap *map);
-extern struct kgdb_sermap *kgdb_porttype;
-
 /* Trap functions */
-typedef void (kgdb_debug_hook_t)(struct pt_regs *regs); 
+typedef void (kgdb_debug_hook_t)(struct pt_regs *regs);
 typedef void (kgdb_bus_error_hook_t)(void);
 extern kgdb_debug_hook_t  *kgdb_debug_hook;
 extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
 
-extern void breakpoint(void);
-
 /* Console */
-struct console;
 void kgdb_console_write(struct console *co, const char *s, unsigned count);
-void kgdb_console_init(void);
+extern int kgdb_console_setup(struct console *, char *);
 
 /* Prototypes for jmp fns */
 #define _JBLEN 9
@@ -81,11 +68,8 @@ typedef        int jmp_buf[_JBLEN];
 extern void    longjmp(jmp_buf __jmpb, int __retval);
 extern int     setjmp(jmp_buf __jmpb);
 
-/* Variadic macro to print our own message to the console */
-#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
-
 /* Forced breakpoint */
-#define BREAKPOINT()                                   \
+#define breakpoint()                                   \
 do {                                                   \
        if (kgdb_enabled)                               \
                __asm__ __volatile__("trapa   #0x3c");  \
@@ -95,7 +79,6 @@ do {                                                  \
 #if defined(CONFIG_CPU_SH4)
 #define kgdb_flush_icache_range(start, end) \
 {                                                                      \
-       extern void __flush_purge_region(void *, int);                  \
        __flush_purge_region((void*)(start), (int)(end) - (int)(start));\
        flush_icache_range((start), (end));                             \
 }
@@ -103,31 +86,6 @@ do {                                                        \
 #define kgdb_flush_icache_range(start, end)    do { } while (0)
 #endif
 
-/* Kernel assert macros */
-#ifdef CONFIG_KGDB_KERNEL_ASSERTS
-
-/* Predefined conditions */
-#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
-#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
-#define KA_VALID_KPTR(ptr)  (!(ptr) || \
-              ((void *)(ptr) >= (void *)PAGE_OFFSET &&  \
-               (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
-#define KA_VALID_PTRORERR(errptr) \
-               (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
-#define KA_HELD_GKL()  (current->lock_depth >= 0)
-
-/* The actual assert */
-#define KGDB_ASSERT(condition, message) do {                   \
-       if (!(condition) && (kgdb_enabled)) {                   \
-               KGDB_PRINTK("Assertion failed at %s:%d: %s\n",  \
-                                  __FILE__, __LINE__, message);\
-               BREAKPOINT();                                   \
-       }                                                       \
-} while (0)
-#else
-#define KGDB_ASSERT(condition, message)
-#endif
-
 /* Taken from sh-stub.c of GDB 4.18 */
 static const char hexchars[] = "0123456789abcdef";
 
@@ -142,5 +100,4 @@ static inline char lowhex(const int x)
 {
        return hexchars[x & 0xf];
 }
-
 #endif
diff --git a/include/asm-sh/lboxre2.h b/include/asm-sh/lboxre2.h
new file mode 100644 (file)
index 0000000..e6d1605
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __ASM_SH_LBOXRE2_H
+#define __ASM_SH_LBOXRE2_H
+
+/*
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
+ *
+ * NTT COMWARE L-BOX RE2 support
+ *
+ * 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.
+ *
+ */
+
+#define IRQ_CF1                9       /* CF1 */
+#define IRQ_CF0                10      /* CF0 */
+#define IRQ_INTD       11      /* INTD */
+#define IRQ_ETH1       12      /* Ether1 */
+#define IRQ_ETH0       13      /* Ether0 */
+#define IRQ_INTA       14      /* INTA */
+
+void init_lboxre2_IRQ(void);
+
+#define __IO_PREFIX    lboxre2
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_LBOXRE2_H */
index 3420244..199662b 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:
@@ -168,6 +169,8 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 #define destroy_context(mm)            do { } while (0)
 #define set_asid(asid)                 do { } while (0)
 #define get_asid()                     (0)
+#define set_TTB(pgd)                   do { } while (0)
+#define get_TTB()                      (0)
 #define activate_context(mm,cpu)       do { } while (0)
 #define switch_mm(prev,next,tsk)       do { } while (0)
 #define deactivate_mm(tsk,mm)          do { } while (0)
@@ -210,8 +213,8 @@ static inline void disable_mmu(void)
  * MMU control handlers for processors lacking memory
  * management hardware.
  */
-#define enable_mmu()   do { BUG(); } while (0)
-#define disable_mmu()  do { BUG(); } while (0)
+#define enable_mmu()   do { } while (0)
+#define disable_mmu()  do { } while (0)
 #endif
 
 #endif /* __KERNEL__ */
index ac4b467..7464de4 100644 (file)
@@ -59,6 +59,7 @@ extern void (*clear_page)(void *to);
 extern void (*copy_page)(void *to, void *from);
 
 extern unsigned long shm_align_mask;
+extern unsigned long max_low_pfn, min_low_pfn;
 
 #ifdef CONFIG_MMU
 extern void clear_page_slow(void *to);
@@ -124,17 +125,16 @@ typedef struct { unsigned long pgd; } pgd_t;
 #define PAGE_OFFSET            CONFIG_PAGE_OFFSET
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
+#define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 
-#define MAP_NR(addr)           (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
-
-#define phys_to_page(phys)     (mem_map + (((phys)-__MEMORY_START) >> PAGE_SHIFT))
-#define page_to_phys(page)     (((page - mem_map) << PAGE_SHIFT) + __MEMORY_START)
+#define phys_to_page(phys)     (pfn_to_page(phys >> PAGE_SHIFT))
+#define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
 
 /* PFN start number, because of __MEMORY_START */
 #define PFN_START              (__MEMORY_START >> PAGE_SHIFT)
 #define ARCH_PFN_OFFSET                (PFN_START)
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define pfn_valid(pfn)         (((pfn) - PFN_START) < max_mapnr)
+#define pfn_valid(pfn)         ((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
index ce13064..1012296 100644 (file)
@@ -5,7 +5,7 @@
 # ifdef CONFIG_SH_WDT
 #  define HZ           1000            /* Needed for high-res WOVF */
 # else
-#  define HZ           100
+#  define HZ           CONFIG_HZ
 # endif
 # define USER_HZ       100             /* User interfaces are in "ticks" */
 # define CLOCKS_PER_SEC        (USER_HZ)       /* frequency at which times() counts */
index 6ccc948..b1f9a9e 100644 (file)
@@ -35,7 +35,7 @@ extern struct pci_channel board_pci_channels[];
 /*
  * I/O routine helpers
  */
-#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define PCI_IO_AREA            0xFE400000
 #define PCI_IO_SIZE            0x00400000
 #else
index 3e46a7a..d42f68e 100644 (file)
@@ -44,7 +44,7 @@ enum cpu_type {
        /* SH-3 types */
        CPU_SH7705, CPU_SH7706, CPU_SH7707,
        CPU_SH7708, CPU_SH7708S, CPU_SH7708R,
-       CPU_SH7709, CPU_SH7709A, CPU_SH7710,
+       CPU_SH7709, CPU_SH7709A, CPU_SH7710, CPU_SH7712,
        CPU_SH7729, CPU_SH7300,
 
        /* SH-4 types */
index c18f648..4083b59 100644 (file)
@@ -1,17 +1,11 @@
 #ifndef __ASM_SH_RENESAS_R7780RP_H
 #define __ASM_SH_RENESAS_R7780RP_H
 
-/*
- * linux/include/asm-sh/r7780rp.h
- *
- * Copyright (C) 2000  Atom Create Engineering Co., Ltd.
- *
- * Renesas Solutions Highlander R7780RP support
- */
-
 /* Box specific addresses.  */
 #if defined(CONFIG_SH_R7780MP)
 #define PA_BCR          0xa4000000      /* FPGA */
+#define PA_SDPOW       (-1)
+
 #define PA_IRLMSK       (PA_BCR+0x0000) /* Interrupt Mask control */
 #define PA_IRLMON       (PA_BCR+0x0002) /* Interrupt Status control */
 #define PA_IRLPRI1      (PA_BCR+0x0004) /* Interrupt Priorty 1 */
 #define PA_POFF         (PA_BCR+0x0800) /* System Power Off control */
 #define PA_PMR          (PA_BCR+0x0900) /*  */
 
-#define PA_AX88796L     0xa4100400      /* AX88796L Area */
-#define PA_SC1602BSLB   0xa6000000      /* SC1602BSLB Area */
-#define PA_IDE_OFFSET   0x1f0           /* CF IDE Offset */
-#define AX88796L_IO_BASE        0x1000  /* AX88796L IO Base Address */
-
 #define IRLCNTR1        (PA_BCR + 0)    /* Interrupt Control Register1 */
 
 #define IRQ_PCISLOT1    65              /* PCI Slot #1 IRQ */
 #define IRQ_PCISLOT2    66              /* PCI Slot #2 IRQ */
 #define IRQ_PCISLOT3    67              /* PCI Slot #3 IRQ */
 #define IRQ_PCISLOT4    68              /* PCI Slot #4 IRQ */
-// #define IRQ_CFINST   0               /* CF Card Insert IRQ */
 #define IRQ_TP          2               /* Touch Panel IRQ */
 #define IRQ_SCI1        3               /* SCI1 IRQ */
 #define IRQ_SCI0        4               /* SCI0 IRQ */
 #define IRQ_ONETH       13              /* On board Ethernet IRQ */
 #define IRQ_PSW         14              /* Push Switch IRQ */
 
-#else /* R7780RP */
+#define IVDR_CK_ON     8               /* iVDR Clock ON */
+
+#elif defined(CONFIG_SH_R7780RP)
+#define PA_POFF                (-1)
 
 #define PA_BCR         0xa5000000      /* FPGA */
 #define        PA_IRLMSK       (PA_BCR+0x0000) /* Interrupt Mask control */
 #define IRQ_PSW                13              /* Push Switch IRQ */
 #define IRQ_ZIGBEE     14              /* Ziggbee IO IRQ */
 
-#endif  /* CONFIG_SH_R7780MP */
+#define IVDR_CK_ON     8               /* iVDR Clock ON */
+
+#elif defined(CONFIG_SH_R7785RP)
+#define PA_BCR         0xa4000000      /* FPGA */
+#define PA_SDPOW       (-1)
+
+#define        PA_PCISCR       (PA_BCR+0x0000)
+#define PA_IRLPRA      (PA_BCR+0x0002)
+#define        PA_IRLPRB       (PA_BCR+0x0004)
+#define        PA_IRLPRC       (PA_BCR+0x0006)
+#define        PA_IRLPRD       (PA_BCR+0x0008)
+#define IRLCNTR1       (PA_BCR+0x0010)
+#define        PA_IRLPRE       (PA_BCR+0x000a)
+#define        PA_IRLPRF       (PA_BCR+0x000c)
+#define        PA_EXIRLCR      (PA_BCR+0x000e)
+#define        PA_IRLMCR1      (PA_BCR+0x0010)
+#define        PA_IRLMCR2      (PA_BCR+0x0012)
+#define        PA_IRLSSR1      (PA_BCR+0x0014)
+#define        PA_IRLSSR2      (PA_BCR+0x0016)
+#define PA_CFTCR       (PA_BCR+0x0100)
+#define PA_CFPCR       (PA_BCR+0x0102)
+#define PA_PCICR       (PA_BCR+0x0110)
+#define PA_IVDRCTL     (PA_BCR+0x0112)
+#define PA_IVDRSR      (PA_BCR+0x0114)
+#define PA_PDRSTCR     (PA_BCR+0x0116)
+#define PA_POFF                (PA_BCR+0x0120)
+#define PA_LCDCR       (PA_BCR+0x0130)
+#define PA_TPCR                (PA_BCR+0x0140)
+#define PA_TPCKCR      (PA_BCR+0x0142)
+#define PA_TPRSTR      (PA_BCR+0x0144)
+#define PA_TPXPDR      (PA_BCR+0x0146)
+#define PA_TPYPDR      (PA_BCR+0x0148)
+#define PA_GPIOPFR     (PA_BCR+0x0150)
+#define PA_GPIODR      (PA_BCR+0x0152)
+#define PA_OBLED       (PA_BCR+0x0154)
+#define PA_SWSR                (PA_BCR+0x0156)
+#define PA_VERREG      (PA_BCR+0x0158)
+#define PA_SMCR                (PA_BCR+0x0200)
+#define PA_SMSMADR     (PA_BCR+0x0202)
+#define PA_SMMR                (PA_BCR+0x0204)
+#define PA_SMSADR1     (PA_BCR+0x0206)
+#define PA_SMSADR32    (PA_BCR+0x0244)
+#define PA_SMTRDR1     (PA_BCR+0x0246)
+#define PA_SMTRDR16    (PA_BCR+0x0264)
+#define PA_CU3MDR      (PA_BCR+0x0300)
+#define PA_CU5MDR      (PA_BCR+0x0302)
+#define PA_MMSR                (PA_BCR+0x0400)
+
+#define IVDR_CK_ON     4               /* iVDR Clock ON */
+
+#endif
+
+void make_r7780rp_irq(unsigned int irq);
+void highlander_init_irq(void);
 
 #define __IO_PREFIX    r7780rp
 #include <asm/io_generic.h>
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 a183215..bd2596c 100644 (file)
 #define BCR_ILCRG      (PA_BCR + 12)
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define IRQ_STNIC   12
+#define IRQ_STNIC      12
+#define IRQ_CFCARD     14
 #else
 #define IRQ_STNIC      10
+#define IRQ_CFCARD     7
 #endif
 
 #define __IO_PREFIX    se
diff --git a/include/asm-sh/se7722.h b/include/asm-sh/se7722.h
new file mode 100644 (file)
index 0000000..b3b31e4
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef __ASM_SH_SE7722_H
+#define __ASM_SH_SE7722_H
+
+/*
+ * linux/include/asm-sh/se7722.h
+ *
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7722 Support.
+ *
+ * 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 <asm/addrspace.h>
+
+/* Box specific addresses.  */
+#define SE_AREA0_WIDTH 4               /* Area0: 32bit */
+#define PA_ROM         0xa0000000      /* EPROM */
+#define PA_ROM_SIZE    0x00200000      /* EPROM size 2M byte */
+#define PA_FROM                0xa1000000      /* Flash-ROM */
+#define PA_FROM_SIZE   0x01000000      /* Flash-ROM size 16M byte */
+#define PA_EXT1                0xa4000000
+#define PA_EXT1_SIZE   0x04000000
+#define PA_SDRAM       0xaC000000      /* DDR-SDRAM(Area3) 64MB */
+#define PA_SDRAM_SIZE  0x04000000
+
+#define PA_EXT4                0xb0000000
+#define PA_EXT4_SIZE   0x04000000
+
+#define PA_PERIPHERAL  0xB0000000
+
+#define PA_PCIC         PA_PERIPHERAL                  /* MR-SHPC-01 PCMCIA */
+#define PA_MRSHPC       (PA_PERIPHERAL + 0x003fffe0)    /* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1   (PA_PERIPHERAL + 0x00400000)    /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2   (PA_PERIPHERAL + 0x00500000)    /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO    (PA_PERIPHERAL + 0x00600000)    /* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+
+#define PA_LED         (PA_PERIPHERAL + 0x00800000)    /* 8bit LED */
+#define PA_FPGA                (PA_PERIPHERAL + 0x01800000)    /* FPGA base address */
+
+#define PA_LAN         (PA_AREA6_IO + 0)               /* SMC LAN91C111 */
+/* GPIO */
+#define MSTPCR0         0xA4150030UL
+#define MSTPCR1         0xA4150034UL
+#define MSTPCR2         0xA4150038UL
+
+#define FPGA_IN         0xb1840000UL
+#define FPGA_OUT        0xb1840004UL
+
+#define PORT_PECR       0xA4050108UL
+#define PORT_PJCR       0xA4050110UL
+#define PORT_PSELD      0xA4050154UL
+#define PORT_PSELB      0xA4050150UL
+
+#define PORT_PSELC      0xA4050152UL
+#define PORT_PKCR       0xA4050112UL
+#define PORT_PHCR       0xA405010EUL
+#define PORT_PLCR       0xA4050114UL
+#define PORT_PMCR       0xA4050116UL
+#define PORT_PRCR       0xA405011CUL
+#define PORT_PXCR       0xA4050148UL
+#define PORT_PSELA      0xA405014EUL
+#define PORT_PYCR       0xA405014AUL
+#define PORT_PZCR       0xA405014CUL
+
+/* IRQ */
+#define IRQ0_IRQ        32
+#define IRQ1_IRQ        33
+#define INTC_ICR0       0xA4140000UL
+#define INTC_ICR1       0xA414001CUL
+
+#define INTMSK0         0xa4140044
+#define INTMSKCLR0      0xa4140064
+#define INTC_INTPRI0    0xa4140010
+
+#define IRQ01_MODE      0xb1800000
+#define IRQ01_STS       0xb1800004
+#define IRQ01_MASK      0xb1800008
+#define EXT_BIT                (0x3fc0)        /* SH IRQ1 */
+#define MRSHPC_BIT0    (0x0004)        /* SH IRQ1 */
+#define MRSHPC_BIT1    (0x0008)        /* SH IRQ1 */
+#define MRSHPC_BIT2    (0x0010)        /* SH IRQ1 */
+#define MRSHPC_BIT3    (0x0020)        /* SH IRQ1 */
+#define SMC_BIT                (0x0002)        /* SH IRQ0 */
+#define USB_BIT                (0x0001)        /* SH IRQ0 */
+
+#define MRSHPC_IRQ3            11
+#define MRSHPC_IRQ2            12
+#define MRSHPC_IRQ1            13
+#define MRSHPC_IRQ0            14
+#define SMC_IRQ                10
+#define EXT_IRQ                5
+#define USB_IRQ                6
+
+
+/* arch/sh/boards/se/7722/irq.c */
+void init_se7722_IRQ(void);
+int se7722_irq_demux(int);
+
+#define __IO_PREFIX            se7722
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_SE7722_H */
index 88cd379..02ca934 100644 (file)
@@ -65,6 +65,8 @@
 
 #define IRQ_79C973     13
 
+void init_7751se_IRQ(void);
+
 #define __IO_PREFIX    sh7751se
 #include <asm/io_generic.h>
 
diff --git a/include/asm-sh/se7780.h b/include/asm-sh/se7780.h
new file mode 100644 (file)
index 0000000..40e9b41
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef __ASM_SH_SE7780_H
+#define __ASM_SH_SE7780_H
+
+/*
+ * linux/include/asm-sh/se7780.h
+ *
+ * Copyright (C) 2006,2007  Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7780 Support.
+ *
+ * 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 <asm/addrspace.h>
+
+/* Box specific addresses.  */
+#define SE_AREA0_WIDTH 4               /* Area0: 32bit */
+#define PA_ROM         0xa0000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
+#define PA_FROM                0xa1000000      /* Flash-ROM */
+#define PA_FROM_SIZE   0x01000000      /* Flash-ROM size 16M byte */
+#define PA_EXT1                0xa4000000
+#define PA_EXT1_SIZE   0x04000000
+#define PA_SM501       PA_EXT1         /* Graphic IC (SM501) */
+#define PA_SM501_SIZE  PA_EXT1_SIZE    /* Graphic IC (SM501) */
+#define PA_SDRAM       0xa8000000      /* DDR-SDRAM(Area2/3) 128MB */
+#define PA_SDRAM_SIZE  0x08000000
+
+#define PA_EXT4                0xb0000000
+#define PA_EXT4_SIZE   0x04000000
+#define PA_EXT_FLASH   PA_EXT4         /* Expansion Flash-ROM */
+
+#define PA_PERIPHERAL  PA_AREA6_IO     /* SW6-6=ON */
+
+#define PA_LAN         (PA_PERIPHERAL + 0)             /* SMC LAN91C111 */
+#define PA_LED_DISP    (PA_PERIPHERAL + 0x02000000)    /* 8words LED Display */
+#define DISP_CHAR_RAM  (7 << 3)
+#define DISP_SEL0_ADDR (DISP_CHAR_RAM + 0)
+#define DISP_SEL1_ADDR (DISP_CHAR_RAM + 1)
+#define DISP_SEL2_ADDR (DISP_CHAR_RAM + 2)
+#define DISP_SEL3_ADDR (DISP_CHAR_RAM + 3)
+#define DISP_SEL4_ADDR (DISP_CHAR_RAM + 4)
+#define DISP_SEL5_ADDR (DISP_CHAR_RAM + 5)
+#define DISP_SEL6_ADDR (DISP_CHAR_RAM + 6)
+#define DISP_SEL7_ADDR (DISP_CHAR_RAM + 7)
+
+#define DISP_UDC_RAM   (5 << 3)
+#define PA_FPGA                (PA_PERIPHERAL + 0x03000000) /* FPGA base address */
+
+/* FPGA register address and bit */
+#define FPGA_SFTRST            (PA_FPGA + 0)   /* Soft reset register */
+#define FPGA_INTMSK1           (PA_FPGA + 2)   /* Interrupt Mask register 1 */
+#define FPGA_INTMSK2           (PA_FPGA + 4)   /* Interrupt Mask register 2 */
+#define FPGA_INTSEL1           (PA_FPGA + 6)   /* Interrupt select register 1 */
+#define FPGA_INTSEL2           (PA_FPGA + 8)   /* Interrupt select register 2 */
+#define FPGA_INTSEL3           (PA_FPGA + 10)  /* Interrupt select register 3 */
+#define FPGA_PCI_INTSEL1       (PA_FPGA + 12)  /* PCI Interrupt select register 1 */
+#define FPGA_PCI_INTSEL2       (PA_FPGA + 14)  /* PCI Interrupt select register 2 */
+#define FPGA_INTSET            (PA_FPGA + 16)  /* IRQ/IRL select register */
+#define FPGA_INTSTS1           (PA_FPGA + 18)  /* Interrupt status register 1 */
+#define FPGA_INTSTS2           (PA_FPGA + 20)  /* Interrupt status register 2 */
+#define FPGA_REQSEL            (PA_FPGA + 22)  /* REQ/GNT select register */
+#define FPGA_DBG_LED           (PA_FPGA + 32)  /* Debug LED(D-LED[8:1] */
+#define PA_LED                 FPGA_DBG_LED
+#define FPGA_IVDRID            (PA_FPGA + 36)  /* iVDR ID Register */
+#define FPGA_IVDRPW            (PA_FPGA + 38)  /* iVDR Power ON Register */
+#define FPGA_MMCID             (PA_FPGA + 40)  /* MMC ID Register */
+
+/* FPGA INTSEL position */
+/* INTSEL1 */
+#define IRQPOS_SMC91CX          (0 * 4)
+#define IRQPOS_SM501            (1 * 4)
+/* INTSEL2 */
+#define IRQPOS_EXTINT1          (0 * 4)
+#define IRQPOS_EXTINT2          (1 * 4)
+#define IRQPOS_EXTINT3          (2 * 4)
+#define IRQPOS_EXTINT4          (3 * 4)
+/* INTSEL3 */
+#define IRQPOS_PCCPW            (0 * 4)
+
+/* IDE interrupt */
+#define IRQ_IDE0                67 /* iVDR */
+
+/* SMC interrupt */
+#define SMC_IRQ                 8
+
+/* SM501 interrupt */
+#define SM501_IRQ               0
+
+/* interrupt pin */
+#define IRQPIN_EXTINT1          0 /* IRQ0 pin */
+#define IRQPIN_EXTINT2          1 /* IRQ1 pin */
+#define IRQPIN_EXTINT3          2 /* IRQ2 pin */
+#define IRQPIN_SMC91CX          3 /* IRQ3 pin */
+#define IRQPIN_EXTINT4          4 /* IRQ4 pin */
+#define IRQPIN_PCC0             5 /* IRQ5 pin */
+#define IRQPIN_PCC2             6 /* IRQ6 pin */
+#define IRQPIN_SM501            7 /* IRQ7 pin */
+#define IRQPIN_PCCPW            7 /* IRQ7 pin */
+
+/* arch/sh/boards/se/7780/irq.c */
+void init_se7780_IRQ(void);
+
+#define __IO_PREFIX            se7780
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_SE7780_H */
index 6c41a60..6d6ad26 100644 (file)
@@ -16,15 +16,13 @@ struct __old_kernel_stat {
 };
 
 struct stat {
-       unsigned short st_dev;
-       unsigned short __pad1;
-       unsigned long st_ino;
+       unsigned long  st_dev;
+       unsigned long  st_ino;
        unsigned short st_mode;
        unsigned short st_nlink;
        unsigned short st_uid;
        unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned short __pad2;
+       unsigned long  st_rdev;
        unsigned long  st_size;
        unsigned long  st_blksize;
        unsigned long  st_blocks;
@@ -38,8 +36,6 @@ struct stat {
        unsigned long  __unused5;
 };
 
-#define STAT_HAVE_NSEC 1
-
 /* This matches struct stat64 in glibc2.1, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
@@ -47,7 +43,9 @@ struct stat64 {
        unsigned long long      st_dev;
        unsigned char   __pad0[4];
 
-       unsigned long   st_ino;
+#define STAT64_HAS_BROKEN_ST_INO       1
+       unsigned long   __st_ino;
+
        unsigned int    st_mode;
        unsigned int    st_nlink;
 
@@ -71,8 +69,9 @@ struct stat64 {
        unsigned long   st_ctime;
        unsigned long   st_ctime_nsec; 
 
-       unsigned long   __unused1;
-       unsigned long   __unused2;
+       unsigned long long      st_ino;
 };
 
+#define STAT_HAVE_NSEC 1
+
 #endif /* __ASM_SH_STAT_H */
index 4a6a19f..127af30 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/irqflags.h>
 #include <linux/compiler.h>
 #include <asm/types.h>
+#include <asm/ptrace.h>
 
 /*
  *     switch_to() should switch tasks to task nr n, first
@@ -255,6 +256,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
                                    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+
 extern void *set_exception_table_vec(unsigned int vec, void *handler);
 
 static inline void *set_exception_table_evt(unsigned int evt, void *handler)
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 e199594..0b1813f 100644 (file)
@@ -32,6 +32,7 @@ struct iommu {
        unsigned long           iommu_control;
        unsigned long           iommu_tsbbase;
        unsigned long           iommu_flush;
+       unsigned long           iommu_flushinv;
        unsigned long           iommu_ctxflush;
        unsigned long           write_complete_reg;
        unsigned long           dummy_page;
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 5891ff7..5d66b85 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/quicklist.h>
 
 #include <asm/spitfire.h>
 #include <asm/cpudata.h>
 #include <asm/page.h>
 
 /* Page table allocation/freeing. */
-extern struct kmem_cache *pgtable_cache;
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
+       return quicklist_alloc(0, GFP_KERNEL, NULL);
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
-       kmem_cache_free(pgtable_cache, pgd);
+       quicklist_free(0, NULL, pgd);
 }
 
 #define pud_populate(MM, PUD, PMD)     pud_set(PUD, PMD)
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(pgtable_cache,
-                               GFP_KERNEL|__GFP_REPEAT);
+       return quicklist_alloc(0, GFP_KERNEL, NULL);
 }
 
 static inline void pmd_free(pmd_t *pmd)
 {
-       kmem_cache_free(pgtable_cache, pmd);
+       quicklist_free(0, NULL, pmd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return kmem_cache_alloc(pgtable_cache,
-                               GFP_KERNEL|__GFP_REPEAT);
+       return quicklist_alloc(0, GFP_KERNEL, NULL);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
                                         unsigned long address)
 {
-       return virt_to_page(pte_alloc_one_kernel(mm, address));
+       void *pg = quicklist_alloc(0, GFP_KERNEL, NULL);
+       return pg ? virt_to_page(pg) : NULL;
 }
                
 static inline void pte_free_kernel(pte_t *pte)
 {
-       kmem_cache_free(pgtable_cache, pte);
+       quicklist_free(0, NULL, pte);
 }
 
 static inline void pte_free(struct page *ptepage)
 {
-       pte_free_kernel(page_address(ptepage));
+       quicklist_free_page(0, NULL, ptepage);
 }
 
 
@@ -66,6 +65,9 @@ static inline void pte_free(struct page *ptepage)
 #define pmd_populate(MM,PMD,PTE_PAGE)          \
        pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
 
-#define check_pgt_cache()      do { } while (0)
+static inline void check_pgt_cache(void)
+{
+       quicklist_trim(0, NULL, 25, 16);
+}
 
 #endif /* _SPARC64_PGALLOC_H */
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 4296d31..8e310d8 100644 (file)
@@ -114,9 +114,6 @@ extern unsigned long uml_physmem;
 extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
 #define HAVE_ARCH_VALIDATE
 
-extern void arch_free_page(struct page *page, int order);
-#define HAVE_ARCH_FREE_PAGE
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
index 522aa30..e78c28c 100644 (file)
@@ -7,6 +7,7 @@
 #define __UM_TLBFLUSH_H
 
 #include <linux/mm.h>
+#include "choose-mode.h"
 
 /*
  * TLB flushing:
@@ -24,6 +25,18 @@ extern void flush_tlb_all(void);
 extern void flush_tlb_mm(struct mm_struct *mm);
 extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 
                            unsigned long end);
+extern void flush_tlb_page_skas(struct vm_area_struct *vma,
+                               unsigned long address);
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                                 unsigned long address)
+{
+       address &= PAGE_MASK;
+
+       CHOOSE_MODE(flush_tlb_range(vma, address, address + PAGE_SIZE),
+                   flush_tlb_page_skas(vma, address));
+}
+
 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void flush_tlb_kernel_vm(void);
 extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
@@ -35,14 +48,3 @@ static inline void flush_tlb_pgtables(struct mm_struct *mm,
 }
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
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..4d04e24 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,47 +75,37 @@ 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
+#define PAGE_OFFSET            __PAGE_OFFSET
 
 #ifndef __ASSEMBLY__
 
 #include <asm/bug.h>
 
+extern unsigned long __phys_addr(unsigned long);
+
 #endif /* __ASSEMBLY__ */
 
-#define PAGE_OFFSET            ((unsigned long)__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)
-/* __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); })
+#define __pa(x)                __phys_addr((unsigned long)(x))
+#define __pa_symbol(x) __phys_addr((unsigned long)(x))
 
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
 #define __boot_va(x)           __va(x)
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..da3390f 100644 (file)
@@ -1,22 +1,22 @@
 #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
@@ -31,6 +31,8 @@ extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
 extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
+#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 dd27b1c..5c6e128 100644 (file)
@@ -165,7 +165,7 @@ int sync_mapping_buffers(struct address_space *mapping);
 void unmap_underlying_metadata(struct block_device *bdev, sector_t block);
 
 void mark_buffer_async_write(struct buffer_head *bh);
-void invalidate_bdev(struct block_device *, int);
+void invalidate_bdev(struct block_device *);
 int sync_blockdev(struct block_device *bdev);
 void __wait_on_buffer(struct buffer_head *);
 wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
@@ -182,6 +182,7 @@ void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
 void __breadahead(struct block_device *, sector_t block, unsigned int size);
 struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
+void invalidate_bh_lrus(void);
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
 void FASTCALL(unlock_buffer(struct buffer_head *bh));
@@ -319,7 +320,7 @@ static inline int inode_has_buffers(struct inode *inode) { return 0; }
 static inline void invalidate_inode_buffers(struct inode *inode) {}
 static inline int remove_inode_buffers(struct inode *inode) { return 1; }
 static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }
-static inline void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) {}
+static inline void invalidate_bdev(struct block_device *bdev) {}
 
 
 #endif /* CONFIG_BLOCK */
index 9008eab..a9f7947 100644 (file)
@@ -22,6 +22,9 @@
     __asm__ ("" : "=r"(__ptr) : "0"(ptr));             \
     (typeof(ptr)) (__ptr + (off)); })
 
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a) \
+  BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
 
 #define inline         inline          __attribute__((always_inline))
 #define __inline__     __inline__      __attribute__((always_inline))
index 1698b84..ecd621f 100644 (file)
 #define __must_check           __attribute__((warn_unused_result))
 #endif
 
+/*
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
+ */
+#define uninitialized_var(x) x = x
+
 #define __always_inline                inline __attribute__((always_inline))
index 6f5cc6f..fd0cc7c 100644 (file)
@@ -16,3 +16,9 @@
 #define __must_check           __attribute__((warn_unused_result))
 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
 #define __always_inline                inline __attribute__((always_inline))
+
+/*
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
+ */
+#define uninitialized_var(x) x = x
index 1d1c3ce..b769961 100644 (file)
@@ -21,4 +21,9 @@
      __ptr = (unsigned long) (ptr);                            \
     (typeof(ptr)) (__ptr + (off)); })
 
+/* Intel ECC compiler doesn't support __builtin_types_compatible_p() */
+#define __must_be_array(a) 0
+
 #endif
+
+#define uninitialized_var(x) x
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 2a2dd18..c2735ca 100644 (file)
@@ -19,7 +19,7 @@
 
 /* Version of the device interface */
 #define DLM_DEVICE_VERSION_MAJOR 5
-#define DLM_DEVICE_VERSION_MINOR 0
+#define DLM_DEVICE_VERSION_MINOR 1
 #define DLM_DEVICE_VERSION_PATCH 0
 
 /* struct passed to the lock write */
@@ -44,6 +44,11 @@ struct dlm_lspace_params {
        char name[0];
 };
 
+struct dlm_purge_params {
+       __u32 nodeid;
+       __u32 pid;
+};
+
 struct dlm_write_request {
        __u32 version[3];
        __u8 cmd;
@@ -53,6 +58,7 @@ struct dlm_write_request {
        union  {
                struct dlm_lock_params   lock;
                struct dlm_lspace_params lspace;
+               struct dlm_purge_params  purge;
        } i;
 };
 
@@ -76,6 +82,7 @@ struct dlm_lock_result {
 #define DLM_USER_QUERY        3
 #define DLM_USER_CREATE_LOCKSPACE  4
 #define DLM_USER_REMOVE_LOCKSPACE  5
+#define DLM_USER_PURGE        6
 
 /* Arbitrary length restriction */
 #define MAX_LS_NAME_LEN 64
index 666e0a5..0311bad 100644 (file)
@@ -30,6 +30,7 @@
 #define EM_V850                87      /* NEC v850 */
 #define EM_M32R                88      /* Renesas M32R */
 #define EM_H8_300      46      /* Renesas H8/300,300H,H8S */
+#define EM_BLACKFIN     106     /* ADI Blackfin Processor */
 #define EM_FRV         0x5441  /* Fujitsu FR-V */
 #define EM_AVR32       0x18ad  /* Atmel AVR32 */
 
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 745c988..071c67a 100644 (file)
@@ -70,6 +70,18 @@ static inline int is_multicast_ether_addr(const u8 *addr)
        return (0x01 & addr[0]);
 }
 
+/**
+ * is_local_ether_addr - Determine if the Ethernet address is locally-assigned
+ * one (IEEE 802).
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a local address.
+ */
+static inline int is_local_ether_addr(const u8 *addr)
+{
+       return (0x02 & addr[0]);
+}
+
 /**
  * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast
  * @addr: Pointer to a six-byte array containing the Ethernet address
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 996f561..40b9326 100644 (file)
@@ -3,6 +3,10 @@
 
 #include <asm/fcntl.h>
 
+/* Cancel a blocking posix lock; internal use only until we expose an
+ * asynchronous lock api to userspace: */
+#define F_CANCELLK     (F_LINUX_SPECIFIC_BASE+5)
+
 #define F_SETLEASE     (F_LINUX_SPECIFIC_BASE+0)
 #define F_GETLEASE     (F_LINUX_SPECIFIC_BASE+1)
 
index 095a9c9..bc6d27c 100644 (file)
@@ -696,12 +696,13 @@ struct file_ra_state {
        unsigned long size;
        unsigned long flags;            /* ra flags RA_FLAG_xxx*/
        unsigned long cache_hit;        /* cache hit count*/
-       unsigned long prev_page;        /* Cache last read() position */
+       unsigned long prev_index;       /* Cache last read() position */
        unsigned long ahead_start;      /* Ahead window */
        unsigned long ahead_size;
        unsigned long ra_pages;         /* Maximum readahead window */
        unsigned long mmap_hit;         /* Cache hit stat for mmap accesses */
        unsigned long mmap_miss;        /* Cache miss stat for mmap accesses */
+       unsigned int prev_offset;       /* Offset where last read() ended in a page */
 };
 #define RA_FLAG_MISS 0x01      /* a cache miss occured against this file */
 #define RA_FLAG_INCACHE 0x02   /* file is already in cache */
@@ -785,6 +786,7 @@ struct file_lock_operations {
 struct lock_manager_operations {
        int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
        void (*fl_notify)(struct file_lock *);  /* unblock callback */
+       int (*fl_grant)(struct file_lock *, struct file_lock *, int);
        void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
        void (*fl_release_private)(struct file_lock *);
        void (*fl_break)(struct file_lock *);
@@ -856,11 +858,13 @@ extern void locks_init_lock(struct file_lock *);
 extern void locks_copy_lock(struct file_lock *, struct file_lock *);
 extern void locks_remove_posix(struct file *, fl_owner_t);
 extern void locks_remove_flock(struct file *);
-extern int posix_test_lock(struct file *, struct file_lock *, struct file_lock *);
-extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_lock *);
-extern int posix_lock_file(struct file *, struct file_lock *);
+extern int posix_test_lock(struct file *, struct file_lock *);
+extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
 extern int posix_lock_file_wait(struct file *, struct file_lock *);
 extern int posix_unblock_lock(struct file *, struct file_lock *);
+extern int vfs_test_lock(struct file *, struct file_lock *);
+extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
+extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
 extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
 extern int __break_lease(struct inode *inode, unsigned int flags);
 extern void lease_get_mtime(struct inode *, struct timespec *time);
@@ -1416,7 +1420,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 2a7d15b..97a36c3 100644 (file)
@@ -40,7 +40,6 @@ struct vm_area_struct;
 #define __GFP_REPEAT   ((__force gfp_t)0x400u) /* Retry the allocation.  Might fail */
 #define __GFP_NOFAIL   ((__force gfp_t)0x800u) /* Retry for ever.  Cannot fail */
 #define __GFP_NORETRY  ((__force gfp_t)0x1000u)/* Do not retry.  Might fail */
-#define __GFP_NO_GROW  ((__force gfp_t)0x2000u)/* Slab internal usage */
 #define __GFP_COMP     ((__force gfp_t)0x4000u)/* Add compound page metadata */
 #define __GFP_ZERO     ((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
@@ -53,7 +52,7 @@ struct vm_area_struct;
 /* if you forget to add the bitmask here kernel will crash, period */
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
                        __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
-                       __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
+                       __GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
                        __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE)
 
 /* This equals 0, but use constants in case they ever change */
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 3f3e7a6..b4570b6 100644 (file)
@@ -189,4 +189,10 @@ static inline void set_file_hugepages(struct file *file)
 
 #endif /* !CONFIG_HUGETLBFS */
 
+#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+                                       unsigned long len, unsigned long pgoff,
+                                       unsigned long flags);
+#endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */
+
 #endif /* _LINUX_HUGETLB_H */
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..dbbdbd1 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__
 /*
@@ -228,7 +233,7 @@ void __init parse_early_param(void);
 #define __obsolete_setup(str)                  /* nothing */
 #endif
 
-/* Data marked not to be saved by software_suspend() */
+/* Data marked not to be saved by software suspend */
 #define __nosavedata __attribute__ ((__section__ (".data.nosave")))
 
 /* This means "can be init if no module support, otherwise module load
index 1789ee9..be2bf3a 100644 (file)
@@ -677,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
@@ -989,6 +990,10 @@ struct input_dev {
 #error "EV_MAX and INPUT_DEVICE_ID_EV_MAX do not match"
 #endif
 
+#if KEY_MIN_INTERESTING != INPUT_DEVICE_ID_KEY_MIN_INTERESTING
+#error "KEY_MIN_INTERESTING and INPUT_DEVICE_ID_KEY_MIN_INTERESTING do not match"
+#endif
+
 #if KEY_MAX != INPUT_DEVICE_ID_KEY_MAX
 #error "KEY_MAX and INPUT_DEVICE_ID_KEY_MAX do not match"
 #endif
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 e2f41b0..144b615 100644 (file)
@@ -35,7 +35,8 @@ extern const char linux_proc_banner[];
 #define ALIGN(x,a)             __ALIGN_MASK(x,(typeof(x))(a)-1)
 #define __ALIGN_MASK(x,mask)   (((x)+(mask))&~(mask))
 
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
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..05707e2 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 */
@@ -119,6 +119,9 @@ struct nlm_file {
  * couldn't be granted because of a conflicting lock).
  */
 #define NLM_NEVER              (~(unsigned long) 0)
+/* timeout on non-blocking call: */
+#define NLM_TIMEOUT            (7 * HZ)
+
 struct nlm_block {
        struct kref             b_count;        /* Reference count */
        struct list_head        b_list;         /* linked list of all blocks */
@@ -130,6 +133,13 @@ struct nlm_block {
        unsigned int            b_id;           /* block id */
        unsigned char           b_granted;      /* VFS granted lock */
        struct nlm_file *       b_file;         /* file in question */
+       struct cache_req *      b_cache_req;    /* deferred request handling */
+       struct file_lock *      b_fl;           /* set for GETLK */
+       struct cache_deferred_req * b_deferred_req;
+       unsigned int            b_flags;        /* block flags */
+#define B_QUEUED               1       /* lock queued */
+#define B_GOT_CALLBACK         2       /* got lock or conflicting lock */
+#define B_TIMED_OUT            4       /* filesystem too slow to respond */
 };
 
 /*
@@ -185,8 +195,8 @@ typedef int   (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref)
 __be32           nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
                                        struct nlm_lock *, int, struct nlm_cookie *);
 __be32           nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
-__be32           nlmsvc_testlock(struct nlm_file *, struct nlm_lock *,
-                                       struct nlm_lock *);
+__be32           nlmsvc_testlock(struct svc_rqst *, struct nlm_file *,
+                       struct nlm_lock *, struct nlm_lock *, struct nlm_cookie *);
 __be32           nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
 unsigned long    nlmsvc_retry_blocked(void);
 void             nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
index 75e55dc..e10a90a 100644 (file)
@@ -2,18 +2,29 @@
 #define _LINUX_MIGRATE_H
 
 #include <linux/mm.h>
+#include <linux/mempolicy.h>
+#include <linux/pagemap.h>
 
 typedef struct page *new_page_t(struct page *, unsigned long private, int **);
 
+#ifdef CONFIG_MIGRATION
 /* Check if a vma is migratable */
 static inline int vma_migratable(struct vm_area_struct *vma)
 {
        if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
                return 0;
+       /*
+        * Migration allocates pages in the highest zone. If we cannot
+        * do so then migration (at least from node to node) is not
+        * possible.
+        */
+       if (vma->vm_file &&
+               gfp_zone(mapping_gfp_mask(vma->vm_file->f_mapping))
+                                                               < policy_zone)
+                       return 0;
        return 1;
 }
 
-#ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
 extern int putback_lru_pages(struct list_head *l);
 extern int migrate_page(struct address_space *,
@@ -28,6 +39,8 @@ extern int migrate_vmas(struct mm_struct *mm,
                const nodemask_t *from, const nodemask_t *to,
                unsigned long flags);
 #else
+static inline int vma_migratable(struct vm_area_struct *vma)
+                                       { return 0; }
 
 static inline int isolate_lru_page(struct page *p, struct list_head *list)
                                        { return -ENOSYS; }
index 326da7d..dff9ea3 100644 (file)
@@ -29,6 +29,7 @@
 
 #define TUN_MINOR           200
 #define        HPET_MINOR           228
+#define KVM_MINOR            232
 
 struct device;
 
index 60e0e4a..4670ebd 100644 (file)
@@ -267,21 +267,31 @@ static inline int get_page_unless_zero(struct page *page)
        return atomic_inc_not_zero(&page->_count);
 }
 
+static inline struct page *compound_head(struct page *page)
+{
+       if (unlikely(PageTail(page)))
+               return page->first_page;
+       return page;
+}
+
 static inline int page_count(struct page *page)
 {
-       if (unlikely(PageCompound(page)))
-               page = (struct page *)page_private(page);
-       return atomic_read(&page->_count);
+       return atomic_read(&compound_head(page)->_count);
 }
 
 static inline void get_page(struct page *page)
 {
-       if (unlikely(PageCompound(page)))
-               page = (struct page *)page_private(page);
+       page = compound_head(page);
        VM_BUG_ON(atomic_read(&page->_count) == 0);
        atomic_inc(&page->_count);
 }
 
+static inline struct page *virt_to_head_page(const void *x)
+{
+       struct page *page = virt_to_page(x);
+       return compound_head(page);
+}
+
 /*
  * Setup the page count before being freed into the page allocator for
  * the first time (boot or memory hotplug)
@@ -314,6 +324,18 @@ static inline compound_page_dtor *get_compound_page_dtor(struct page *page)
        return (compound_page_dtor *)page[1].lru.next;
 }
 
+static inline int compound_order(struct page *page)
+{
+       if (!PageHead(page))
+               return 0;
+       return (unsigned long)page[1].lru.prev;
+}
+
+static inline void set_compound_order(struct page *page, unsigned long order)
+{
+       page[1].lru.prev = (void *)order;
+}
+
 /*
  * Multiple processes may "see" the same page. E.g. for untouched
  * mappings of /dev/null, all processes see the same page full of
@@ -850,8 +872,26 @@ static inline int vma_wants_writenotify(struct vm_area_struct *vma)
 
 extern pte_t *FASTCALL(get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl));
 
+#ifdef __PAGETABLE_PUD_FOLDED
+static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd,
+                                               unsigned long address)
+{
+       return 0;
+}
+#else
 int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address);
+#endif
+
+#ifdef __PAGETABLE_PMD_FOLDED
+static inline int __pmd_alloc(struct mm_struct *mm, pud_t *pud,
+                                               unsigned long address)
+{
+       return 0;
+}
+#else
 int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address);
+#endif
+
 int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address);
 int __pte_alloc_kernel(pmd_t *pmd, unsigned long address);
 
@@ -1130,6 +1170,11 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
 #define FOLL_GET       0x04    /* do get_page on page */
 #define FOLL_ANON      0x08    /* give ZERO_PAGE if no pgtable */
 
+typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr,
+                       void *data);
+extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
+                              unsigned long size, pte_fn_t fn, void *data);
+
 #ifdef CONFIG_PROC_FS
 void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long);
 #else
index c3852fd..e30687b 100644 (file)
@@ -19,10 +19,16 @@ struct page {
        unsigned long flags;            /* Atomic flags, some possibly
                                         * updated asynchronously */
        atomic_t _count;                /* Usage count, see below. */
-       atomic_t _mapcount;             /* Count of ptes mapped in mms,
+       union {
+               atomic_t _mapcount;     /* Count of ptes mapped in mms,
                                         * to show when page is mapped
                                         * & limit reverse map searches.
                                         */
+               struct {        /* SLUB uses */
+                       short unsigned int inuse;
+                       short unsigned int offset;
+               };
+       };
        union {
            struct {
                unsigned long private;          /* Mapping-private opaque data:
@@ -43,8 +49,15 @@ struct page {
 #if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
            spinlock_t ptl;
 #endif
+           struct {                    /* SLUB uses */
+               struct page *first_page;        /* Compound pages */
+               struct kmem_cache *slab;        /* Pointer to slab */
+           };
+       };
+       union {
+               pgoff_t index;          /* Our offset within mapping. */
+               void *freelist;         /* SLUB: pointer to free object */
        };
-       pgoff_t index;                  /* Our offset within mapping. */
        struct list_head lru;           /* Pageout list, eg. active_list
                                         * protected by zone->lru_lock !
                                         */
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 ee9e314..2f1544e 100644 (file)
@@ -784,6 +784,18 @@ void sparse_init(void);
 void memory_present(int nid, unsigned long start, unsigned long end);
 unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
 
+/*
+ * If it is possible to have holes within a MAX_ORDER_NR_PAGES, then we
+ * need to check pfn validility within that MAX_ORDER_NR_PAGES block.
+ * pfn_valid_within() should be used in this case; we optimise this away
+ * when we have no holes within a MAX_ORDER_NR_PAGES block.
+ */
+#ifdef CONFIG_HOLES_IN_ZONE
+#define pfn_valid_within(pfn) pfn_valid(pfn)
+#else
+#define pfn_valid_within(pfn) (1)
+#endif
+
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MMZONE_H */
index e96b2de..af04a55 100644 (file)
@@ -262,6 +262,7 @@ struct i2c_device_id {
 
 /* Input */
 #define INPUT_DEVICE_ID_EV_MAX         0x1f
+#define INPUT_DEVICE_ID_KEY_MIN_INTERESTING    0x71
 #define INPUT_DEVICE_ID_KEY_MAX                0x1ff
 #define INPUT_DEVICE_ID_REL_MAX                0x0f
 #define INPUT_DEVICE_ID_ABS_MAX                0x3f
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 9632659..ae2d79f 100644 (file)
@@ -6,6 +6,7 @@
 #define PAGE_FLAGS_H
 
 #include <linux/types.h>
+#include <linux/mm_types.h>
 
 /*
  * Various page->flags bits:
 #define PG_private             11      /* If pagecache, has fs-private data */
 
 #define PG_writeback           12      /* Page is under writeback */
-#define PG_nosave              13      /* Used for system suspend/resume */
 #define PG_compound            14      /* Part of a compound page */
 #define PG_swapcache           15      /* Swap page: swp_entry_t in private */
 
 #define PG_mappedtodisk                16      /* Has blocks allocated on-disk */
 #define PG_reclaim             17      /* To be reclaimed asap */
-#define PG_nosave_free         18      /* Used for system suspend/resume */
 #define PG_buddy               19      /* Page is free, on buddy lists */
 
 /* PG_owner_priv_1 users should have descriptive aliases */
@@ -214,16 +213,6 @@ static inline void SetPageUptodate(struct page *page)
                ret;                                                    \
        })
 
-#define PageNosave(page)       test_bit(PG_nosave, &(page)->flags)
-#define SetPageNosave(page)    set_bit(PG_nosave, &(page)->flags)
-#define TestSetPageNosave(page)        test_and_set_bit(PG_nosave, &(page)->flags)
-#define ClearPageNosave(page)          clear_bit(PG_nosave, &(page)->flags)
-#define TestClearPageNosave(page)      test_and_clear_bit(PG_nosave, &(page)->flags)
-
-#define PageNosaveFree(page)   test_bit(PG_nosave_free, &(page)->flags)
-#define SetPageNosaveFree(page)        set_bit(PG_nosave_free, &(page)->flags)
-#define ClearPageNosaveFree(page)              clear_bit(PG_nosave_free, &(page)->flags)
-
 #define PageBuddy(page)                test_bit(PG_buddy, &(page)->flags)
 #define __SetPageBuddy(page)   __set_bit(PG_buddy, &(page)->flags)
 #define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags)
@@ -241,6 +230,34 @@ static inline void SetPageUptodate(struct page *page)
 #define __SetPageCompound(page)        __set_bit(PG_compound, &(page)->flags)
 #define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags)
 
+/*
+ * PG_reclaim is used in combination with PG_compound to mark the
+ * head and tail of a compound page
+ *
+ * PG_compound & PG_reclaim    => Tail page
+ * PG_compound & ~PG_reclaim   => Head page
+ */
+
+#define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
+
+#define PageTail(page) ((page->flags & PG_head_tail_mask) \
+                               == PG_head_tail_mask)
+
+static inline void __SetPageTail(struct page *page)
+{
+       page->flags |= PG_head_tail_mask;
+}
+
+static inline void __ClearPageTail(struct page *page)
+{
+       page->flags &= ~PG_head_tail_mask;
+}
+
+#define PageHead(page) ((page->flags & PG_head_tail_mask) \
+                               == (1L << PG_compound))
+#define __SetPageHead(page)    __SetPageCompound(page)
+#define __ClearPageHead(page)  __ClearPageCompound(page)
+
 #ifdef CONFIG_SWAP
 #define PageSwapCache(page)    test_bit(PG_swapcache, &(page)->flags)
 #define SetPageSwapCache(page) set_bit(PG_swapcache, &(page)->flags)
index 7a8dcb8..b4def5e 100644 (file)
@@ -95,12 +95,23 @@ static inline struct page *grab_cache_page(struct address_space *mapping, unsign
 
 extern struct page * grab_cache_page_nowait(struct address_space *mapping,
                                unsigned long index);
+extern struct page * read_cache_page_async(struct address_space *mapping,
+                               unsigned long index, filler_t *filler,
+                               void *data);
 extern struct page * read_cache_page(struct address_space *mapping,
                                unsigned long index, filler_t *filler,
                                void *data);
 extern int read_cache_pages(struct address_space *mapping,
                struct list_head *pages, filler_t *filler, void *data);
 
+static inline struct page *read_mapping_page_async(
+                                               struct address_space *mapping,
+                                            unsigned long index, void *data)
+{
+       filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+       return read_cache_page_async(mapping, index, filler, data);
+}
+
 static inline struct page *read_mapping_page(struct address_space *mapping,
                                             unsigned long index, void *data)
 {
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..95f518b 100644 (file)
@@ -18,6 +18,9 @@
 #define        RED_INACTIVE    0x5A2CF071UL    /* when obj is inactive */
 #define        RED_ACTIVE      0x170FC2A5UL    /* when obj is active */
 
+#define SLUB_RED_INACTIVE      0xbb
+#define SLUB_RED_ACTIVE                0xcc
+
 /* ...and for poisoning */
 #define        POISON_INUSE    0x5a    /* for use-uninitialised poisoning */
 #define POISON_FREE    0x6b    /* for use-after-free poisoning */
@@ -26,9 +29,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
index be4652a..f4f7a63 100644 (file)
@@ -104,6 +104,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 unsigned long task_vsize(struct mm_struct *);
 int task_statm(struct mm_struct *, int *, int *, int *, int *);
 char *task_mem(struct mm_struct *, char *);
+void clear_refs_smap(struct mm_struct *mm);
 
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
                                                struct proc_dir_entry *parent);
diff --git a/include/linux/quicklist.h b/include/linux/quicklist.h
new file mode 100644 (file)
index 0000000..9371c61
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef LINUX_QUICKLIST_H
+#define LINUX_QUICKLIST_H
+/*
+ * Fast allocations and disposal of pages. Pages must be in the condition
+ * as needed after allocation when they are freed. Per cpu lists of pages
+ * are kept that only contain node local pages.
+ *
+ * (C) 2007, SGI. Christoph Lameter <clameter@sgi.com>
+ */
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/percpu.h>
+
+#ifdef CONFIG_QUICKLIST
+
+struct quicklist {
+       void *page;
+       int nr_pages;
+};
+
+DECLARE_PER_CPU(struct quicklist, quicklist)[CONFIG_NR_QUICK];
+
+/*
+ * The two key functions quicklist_alloc and quicklist_free are inline so
+ * that they may be custom compiled for the platform.
+ * Specifying a NULL ctor can remove constructor support. Specifying
+ * a constant quicklist allows the determination of the exact address
+ * in the per cpu area.
+ *
+ * The fast patch in quicklist_alloc touched only a per cpu cacheline and
+ * the first cacheline of the page itself. There is minmal overhead involved.
+ */
+static inline void *quicklist_alloc(int nr, gfp_t flags, void (*ctor)(void *))
+{
+       struct quicklist *q;
+       void **p = NULL;
+
+       q =&get_cpu_var(quicklist)[nr];
+       p = q->page;
+       if (likely(p)) {
+               q->page = p[0];
+               p[0] = NULL;
+               q->nr_pages--;
+       }
+       put_cpu_var(quicklist);
+       if (likely(p))
+               return p;
+
+       p = (void *)__get_free_page(flags | __GFP_ZERO);
+       if (ctor && p)
+               ctor(p);
+       return p;
+}
+
+static inline void __quicklist_free(int nr, void (*dtor)(void *), void *p,
+       struct page *page)
+{
+       struct quicklist *q;
+       int nid = page_to_nid(page);
+
+       if (unlikely(nid != numa_node_id())) {
+               if (dtor)
+                       dtor(p);
+               __free_page(page);
+               return;
+       }
+
+       q = &get_cpu_var(quicklist)[nr];
+       *(void **)p = q->page;
+       q->page = p;
+       q->nr_pages++;
+       put_cpu_var(quicklist);
+}
+
+static inline void quicklist_free(int nr, void (*dtor)(void *), void *pp)
+{
+       __quicklist_free(nr, dtor, pp, virt_to_page(pp));
+}
+
+static inline void quicklist_free_page(int nr, void (*dtor)(void *),
+                                                       struct page *page)
+{
+       __quicklist_free(nr, dtor, page_address(page), page);
+}
+
+void quicklist_trim(int nr, void (*dtor)(void *),
+       unsigned long min_pages, unsigned long max_free);
+
+unsigned long quicklist_total_size(void);
+
+#endif
+
+#endif /* LINUX_QUICKLIST_H */
+
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 */
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
new file mode 100644 (file)
index 0000000..7c1ffba
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef __RFKILL_H
+#define __RFKILL_H
+
+/*
+ * Copyright (C) 2006 Ivo van Doorn
+ * 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 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/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+
+/**
+ * enum rfkill_type - type of rfkill switch.
+ * RFKILL_TYPE_WLAN: switch is no a Wireless network devices.
+ * RFKILL_TYPE_BlUETOOTH: switch is on a bluetooth device.
+ * RFKILL_TYPE_IRDA: switch is on an infrared devices.
+ */
+enum rfkill_type {
+       RFKILL_TYPE_WLAN = 0,
+       RFKILL_TYPE_BLUETOOTH = 1,
+       RFKILL_TYPE_IRDA = 2,
+       RFKILL_TYPE_MAX = 3,
+};
+
+enum rfkill_state {
+       RFKILL_STATE_OFF        = 0,
+       RFKILL_STATE_ON         = 1,
+};
+
+/**
+ * struct rfkill - rfkill control structure.
+ * @name: Name of the switch.
+ * @type: Radio type which the button controls, the value stored
+ *     here should be a value from enum rfkill_type.
+ * @state: State of the switch (on/off).
+ * @user_claim: Set when the switch is controlled exlusively by userspace.
+ * @mutex: Guards switch state transitions
+ * @data: Pointer to the RF button drivers private data which will be
+ *     passed along when toggling radio state.
+ * @toggle_radio(): Mandatory handler to control state of the radio.
+ * @dev: Device structure integrating the switch into device tree.
+ * @node: Used to place switch into list of all switches known to the
+ *     the system.
+ *
+ * This structure represents a RF switch located on a network device.
+ */
+struct rfkill {
+       char *name;
+       enum rfkill_type type;
+
+       enum rfkill_state state;
+       bool user_claim;
+
+       struct mutex mutex;
+
+       void *data;
+       int (*toggle_radio)(void *data, enum rfkill_state state);
+
+       struct device dev;
+       struct list_head node;
+};
+#define to_rfkill(d)   container_of(d, struct rfkill, dev)
+
+struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type);
+void rfkill_free(struct rfkill *rfkill);
+int rfkill_register(struct rfkill *rfkill);
+void rfkill_unregister(struct rfkill *rfkill);
+
+void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state);
+
+#endif /* RFKILL_H */
index 586aaba..aa2653a 100644 (file)
@@ -39,7 +39,8 @@
 #define PORT_RSA       13
 #define PORT_NS16550A  14
 #define PORT_XSCALE    15
-#define PORT_MAX_8250  15      /* max port ID */
+#define PORT_RM9000    16      /* PMC-Sierra RM9xxx internal UART */
+#define PORT_MAX_8250  16      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
 /* Xilinx uartlite */
 #define PORT_UARTLITE  74
 
+/* Blackfin bf5xx */
+#define PORT_BFIN      75
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
@@ -230,6 +234,8 @@ struct uart_port {
 #define UPIO_MEM32             (3)
 #define UPIO_AU                        (4)                     /* Au1x00 type IO */
 #define UPIO_TSI               (5)                     /* Tsi108/109 type IO */
+#define UPIO_DWAPB             (6)                     /* DesignWare APB UART */
+#define UPIO_RM9000            (7)                     /* RM9000 type IO */
 
        unsigned int            read_status_mask;       /* driver specific */
        unsigned int            ignore_status_mask;     /* driver specific */
@@ -260,6 +266,7 @@ struct uart_port {
 #define UPF_CONS_FLOW          ((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ          ((__force upf_t) (1 << 24))
 #define UPF_BOOT_AUTOCONF      ((__force upf_t) (1 << 28))
+#define UPF_FIXED_PORT         ((__force upf_t) (1 << 29))
 #define UPF_DEAD               ((__force upf_t) (1 << 30))
 #define UPF_IOREMAP            ((__force upf_t) (1 << 31))
 
@@ -276,6 +283,7 @@ struct uart_port {
        struct device           *dev;                   /* parent device */
        unsigned char           hub6;                   /* this should be in the 8250 driver */
        unsigned char           unused[3];
+       void                    *private_data;          /* generic platform data pointer */
 };
 
 /*
index 3c8a6aa..1c5ed7d 100644 (file)
@@ -38,6 +38,8 @@
 #define UART_IIR_RDI           0x04 /* Receiver data interrupt */
 #define UART_IIR_RLSI          0x06 /* Receiver line status interrupt */
 
+#define UART_IIR_BUSY          0x07 /* DesignWare APB Busy Detect */
+
 #define UART_FCR       2       /* Out: FIFO Control Register */
 #define UART_FCR_ENABLE_FIFO   0x01 /* Enable the FIFO */
 #define UART_FCR_CLEAR_RCVR    0x02 /* Clear the RCVR FIFO */
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 1ef822e..71829ef 100644 (file)
@@ -21,28 +21,25 @@ typedef struct kmem_cache kmem_cache_t __deprecated;
  * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
  */
 #define SLAB_DEBUG_FREE                0x00000100UL    /* DEBUG: Perform (expensive) checks on free */
-#define SLAB_DEBUG_INITIAL     0x00000200UL    /* DEBUG: Call constructor (as verifier) */
 #define SLAB_RED_ZONE          0x00000400UL    /* DEBUG: Red zone objs in a cache */
 #define SLAB_POISON            0x00000800UL    /* DEBUG: Poison objects */
 #define SLAB_HWCACHE_ALIGN     0x00002000UL    /* Align objs on cache lines */
 #define SLAB_CACHE_DMA         0x00004000UL    /* Use GFP_DMA memory */
-#define SLAB_MUST_HWCACHE_ALIGN        0x00008000UL    /* Force alignment even if debuggin is active */
 #define SLAB_STORE_USER                0x00010000UL    /* DEBUG: Store the last owner for bug hunting */
 #define SLAB_RECLAIM_ACCOUNT   0x00020000UL    /* Objects are reclaimable */
 #define SLAB_PANIC             0x00040000UL    /* Panic if kmem_cache_create() fails */
 #define SLAB_DESTROY_BY_RCU    0x00080000UL    /* Defer freeing slabs to RCU */
 #define SLAB_MEM_SPREAD                0x00100000UL    /* Spread some memory over cpuset */
+#define SLAB_TRACE             0x00200000UL    /* Trace allocations and frees */
 
 /* Flags passed to a constructor functions */
 #define SLAB_CTOR_CONSTRUCTOR  0x001UL         /* If not set, then deconstructor */
-#define SLAB_CTOR_ATOMIC       0x002UL         /* Tell constructor it can't sleep */
-#define SLAB_CTOR_VERIFY       0x004UL         /* Tell constructor it's a verify call */
 
 /*
  * struct kmem_cache related prototypes
  */
 void __init kmem_cache_init(void);
-extern int slab_is_available(void);
+int slab_is_available(void);
 
 struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
                        unsigned long,
@@ -57,6 +54,18 @@ unsigned int kmem_cache_size(struct kmem_cache *);
 const char *kmem_cache_name(struct kmem_cache *);
 int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
 
+/*
+ * Please use this macro to create slab caches. Simply specify the
+ * name of the structure and maybe some flags that are listed above.
+ *
+ * The alignment of the struct determines object alignment. If you
+ * f.e. add ____cacheline_aligned_in_smp to the struct declaration
+ * then the objects will be properly aligned in SMP configurations.
+ */
+#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
+               sizeof(struct __struct), __alignof__(struct __struct),\
+               (__flags), NULL, NULL)
+
 #ifdef CONFIG_NUMA
 extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 #else
@@ -72,8 +81,9 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
  */
 void *__kmalloc(size_t, gfp_t);
 void *__kzalloc(size_t, gfp_t);
+void * __must_check krealloc(const void *, size_t, gfp_t);
 void kfree(const void *);
-unsigned int ksize(const void *);
+size_t ksize(const void *);
 
 /**
  * kcalloc - allocate memory for an array. The memory is set to zero.
@@ -94,9 +104,14 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
  * the appropriate general cache at compile time.
  */
 
-#ifdef CONFIG_SLAB
+#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
+#ifdef CONFIG_SLUB
+#include <linux/slub_def.h>
+#else
 #include <linux/slab_def.h>
+#endif /* !CONFIG_SLUB */
 #else
+
 /*
  * Fallback definitions for an allocator not wanting to provide
  * its own optimized kmalloc definitions (like SLOB).
@@ -183,7 +198,7 @@ static inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
  * allocator where we care about the real place the memory allocation
  * request comes from.
  */
-#ifdef CONFIG_DEBUG_SLAB
+#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB)
 extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
 #define kmalloc_track_caller(size, flags) \
        __kmalloc_track_caller(size, flags, __builtin_return_address(0))
@@ -201,7 +216,7 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
  * standard allocator where we care about the real place the memory
  * allocation request comes from.
  */
-#ifdef CONFIG_DEBUG_SLAB
+#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB)
 extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
 #define kmalloc_node_track_caller(size, flags, node) \
        __kmalloc_node_track_caller(size, flags, node, \
@@ -218,6 +233,9 @@ extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
 
 #endif /* DEBUG_SLAB */
 
+extern const struct seq_operations slabinfo_op;
+ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SLAB_H */
 
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
new file mode 100644 (file)
index 0000000..ea27065
--- /dev/null
@@ -0,0 +1,206 @@
+#ifndef _LINUX_SLUB_DEF_H
+#define _LINUX_SLUB_DEF_H
+
+/*
+ * SLUB : A Slab allocator without object queues.
+ *
+ * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com>
+ */
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/workqueue.h>
+#include <linux/kobject.h>
+
+struct kmem_cache_node {
+       spinlock_t list_lock;   /* Protect partial list and nr_partial */
+       unsigned long nr_partial;
+       atomic_long_t nr_slabs;
+       struct list_head partial;
+       struct list_head full;
+};
+
+/*
+ * Slab cache management.
+ */
+struct kmem_cache {
+       /* Used for retriving partial slabs etc */
+       unsigned long flags;
+       int size;               /* The size of an object including meta data */
+       int objsize;            /* The size of an object without meta data */
+       int offset;             /* Free pointer offset. */
+       unsigned int order;
+
+       /*
+        * Avoid an extra cache line for UP, SMP and for the node local to
+        * struct kmem_cache.
+        */
+       struct kmem_cache_node local_node;
+
+       /* Allocation and freeing of slabs */
+       int objects;            /* Number of objects in slab */
+       int refcount;           /* Refcount for slab cache destroy */
+       void (*ctor)(void *, struct kmem_cache *, unsigned long);
+       void (*dtor)(void *, struct kmem_cache *, unsigned long);
+       int inuse;              /* Offset to metadata */
+       int align;              /* Alignment */
+       const char *name;       /* Name (only for display!) */
+       struct list_head list;  /* List of slab caches */
+       struct kobject kobj;    /* For sysfs */
+
+#ifdef CONFIG_NUMA
+       int defrag_ratio;
+       struct kmem_cache_node *node[MAX_NUMNODES];
+#endif
+       struct page *cpu_slab[NR_CPUS];
+};
+
+/*
+ * Kmalloc subsystem.
+ */
+#define KMALLOC_SHIFT_LOW 3
+
+#ifdef CONFIG_LARGE_ALLOCS
+#define KMALLOC_SHIFT_HIGH 25
+#else
+#if !defined(CONFIG_MMU) || NR_CPUS > 512 || MAX_NUMNODES > 256
+#define KMALLOC_SHIFT_HIGH 20
+#else
+#define KMALLOC_SHIFT_HIGH 18
+#endif
+#endif
+
+/*
+ * We keep the general caches in an array of slab caches that are used for
+ * 2^x bytes of allocations.
+ */
+extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+
+/*
+ * Sorry that the following has to be that ugly but some versions of GCC
+ * have trouble with constant propagation and loops.
+ */
+static inline int kmalloc_index(int size)
+{
+       /*
+        * We should return 0 if size == 0 but we use the smallest object
+        * here for SLAB legacy reasons.
+        */
+       WARN_ON_ONCE(size == 0);
+
+       if (size > 64 && size <= 96)
+               return 1;
+       if (size > 128 && size <= 192)
+               return 2;
+       if (size <=          8) return 3;
+       if (size <=         16) return 4;
+       if (size <=         32) return 5;
+       if (size <=         64) return 6;
+       if (size <=        128) return 7;
+       if (size <=        256) return 8;
+       if (size <=        512) return 9;
+       if (size <=       1024) return 10;
+       if (size <=   2 * 1024) return 11;
+       if (size <=   4 * 1024) return 12;
+       if (size <=   8 * 1024) return 13;
+       if (size <=  16 * 1024) return 14;
+       if (size <=  32 * 1024) return 15;
+       if (size <=  64 * 1024) return 16;
+       if (size <= 128 * 1024) return 17;
+       if (size <= 256 * 1024) return 18;
+#if KMALLOC_SHIFT_HIGH > 18
+       if (size <=  512 * 1024) return 19;
+       if (size <= 1024 * 1024) return 20;
+#endif
+#if KMALLOC_SHIFT_HIGH > 20
+       if (size <=  2 * 1024 * 1024) return 21;
+       if (size <=  4 * 1024 * 1024) return 22;
+       if (size <=  8 * 1024 * 1024) return 23;
+       if (size <= 16 * 1024 * 1024) return 24;
+       if (size <= 32 * 1024 * 1024) return 25;
+#endif
+       return -1;
+
+/*
+ * What we really wanted to do and cannot do because of compiler issues is:
+ *     int i;
+ *     for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+ *             if (size <= (1 << i))
+ *                     return i;
+ */
+}
+
+/*
+ * Find the slab cache for a given combination of allocation flags and size.
+ *
+ * This ought to end up with a global pointer to the right cache
+ * in kmalloc_caches.
+ */
+static inline struct kmem_cache *kmalloc_slab(size_t size)
+{
+       int index = kmalloc_index(size);
+
+       if (index == 0)
+               return NULL;
+
+       if (index < 0) {
+               /*
+                * Generate a link failure. Would be great if we could
+                * do something to stop the compile here.
+                */
+               extern void __kmalloc_size_too_large(void);
+               __kmalloc_size_too_large();
+       }
+       return &kmalloc_caches[index];
+}
+
+#ifdef CONFIG_ZONE_DMA
+#define SLUB_DMA __GFP_DMA
+#else
+/* Disable DMA functionality */
+#define SLUB_DMA 0
+#endif
+
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+       if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
+               struct kmem_cache *s = kmalloc_slab(size);
+
+               if (!s)
+                       return NULL;
+
+               return kmem_cache_alloc(s, flags);
+       } else
+               return __kmalloc(size, flags);
+}
+
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+       if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
+               struct kmem_cache *s = kmalloc_slab(size);
+
+               if (!s)
+                       return NULL;
+
+               return kmem_cache_zalloc(s, flags);
+       } else
+               return __kzalloc(size, flags);
+}
+
+#ifdef CONFIG_NUMA
+extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+       if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
+               struct kmem_cache *s = kmalloc_slab(size);
+
+               if (!s)
+                       return NULL;
+
+               return kmem_cache_alloc_node(s, flags, node);
+       } else
+               return __kmalloc_node(size, flags, node);
+}
+#endif
+
+#endif /* _LINUX_SLUB_DEF_H */
diff --git a/include/linux/spi/ad7877.h b/include/linux/spi/ad7877.h
new file mode 100644 (file)
index 0000000..cdbed81
--- /dev/null
@@ -0,0 +1,24 @@
+/* linux/spi/ad7877.h */
+
+/* Touchscreen characteristics vary between boards and models.  The
+ * platform_data for the device's "struct device" holds this information.
+ *
+ * It's OK if the min/max values are zero.
+ */
+struct ad7877_platform_data {
+       u16     model;                  /* 7877 */
+       u16     vref_delay_usecs;       /* 0 for external vref; etc */
+       u16     x_plate_ohms;
+       u16     y_plate_ohms;
+
+       u16     x_min, x_max;
+       u16     y_min, y_max;
+       u16     pressure_min, pressure_max;
+
+       u8      stopacq_polarity;       /* 1 = Active HIGH, 0 = Active LOW */
+       u8      first_conversion_delay; /* 0 = 0.5us, 1 = 128us, 2 = 1ms, 3 = 8ms */
+       u8      acquisition_time;       /* 0 = 2us, 1 = 4us, 2 = 8us, 3 = 16us */
+       u8      averaging;              /* 0 = 1, 1 = 4, 2 = 8, 3 = 16 */
+       u8      pen_down_acc_interval;  /* 0 = covert once, 1 = every 0.5 ms,
+                                          2 = ever 1 ms,   3 = every 8 ms,*/
+};
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 bf99bd4..96868be 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/notifier.h>
 #include <linux/init.h>
 #include <linux/pm.h>
+#include <linux/mm.h>
 
 /* struct pbe is used for creating lists of pages that should be restored
  * atomically during the resume from disk, because the page frames they have
@@ -23,36 +24,32 @@ struct pbe {
 extern void drain_local_pages(void);
 extern void mark_free_pages(struct zone *zone);
 
-#ifdef CONFIG_PM
-/* kernel/power/swsusp.c */
-extern int software_suspend(void);
-
-#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
+#if defined(CONFIG_PM) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
 extern int pm_prepare_console(void);
 extern void pm_restore_console(void);
 #else
 static inline int pm_prepare_console(void) { return 0; }
 static inline void pm_restore_console(void) {}
-#endif /* defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) */
+#endif
+
+#if defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND)
+/* kernel/power/snapshot.c */
+extern void __init register_nosave_region(unsigned long, unsigned long);
+extern int swsusp_page_is_forbidden(struct page *);
+extern void swsusp_set_page_free(struct page *);
+extern void swsusp_unset_page_free(struct page *);
+extern unsigned long get_safe_page(gfp_t gfp_mask);
 #else
-static inline int software_suspend(void)
-{
-       printk("Warning: fake suspend called\n");
-       return -ENOSYS;
-}
-#endif /* CONFIG_PM */
+static inline void register_nosave_region(unsigned long b, unsigned long e) {}
+static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
+static inline void swsusp_set_page_free(struct page *p) {}
+static inline void swsusp_unset_page_free(struct page *p) {}
+#endif /* defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND) */
 
 void save_processor_state(void);
 void restore_processor_state(void);
 struct saved_context;
 void __save_processor_state(struct saved_context *ctxt);
 void __restore_processor_state(struct saved_context *ctxt);
-unsigned long get_safe_page(gfp_t gfp_mask);
-
-/*
- * XXX: We try to keep some more pages free so that I/O operations succeed
- * without paging. Might this be more?
- */
-#define PAGES_FOR_IO   1024
 
 #endif /* _LINUX_SWSUSP_H */
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
diff --git a/include/linux/usb_sl811.h b/include/linux/usb_sl811.h
new file mode 100644 (file)
index 0000000..4f2d012
--- /dev/null
@@ -0,0 +1,26 @@
+
+/*
+ * board initialization should put one of these into dev->platform_data
+ * and place the sl811hs onto platform_bus named "sl811-hcd".
+ */
+
+struct sl811_platform_data {
+       unsigned        can_wakeup:1;
+
+       /* given port_power, msec/2 after power on till power good */
+       u8              potpg;
+
+       /* mA/2 power supplied on this port (max = default = 250) */
+       u8              power;
+
+       /* sl811 relies on an external source of VBUS current */
+       void            (*port_power)(struct device *dev, int is_on);
+
+       /* pulse sl811 nRST (probably with a GPIO) */
+       void            (*reset)(struct device *dev);
+
+       // some boards need something like these:
+       // int          (*check_overcurrent)(struct device *dev);
+       // void         (*clock_enable)(struct device *dev, int is_on);
+};
+
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 8c339f5..90ef552 100644 (file)
@@ -108,6 +108,11 @@ typedef struct dev_node_t {
 struct pcmcia_socket;
 struct config_t;
 
+struct pcmcia_dynids {
+       spinlock_t              lock;
+       struct list_head        list;
+};
+
 struct pcmcia_driver {
        int (*probe)            (struct pcmcia_device *dev);
        void (*remove)          (struct pcmcia_device *dev);
@@ -118,6 +123,7 @@ struct pcmcia_driver {
        struct module           *owner;
        struct pcmcia_device_id *id_table;
        struct device_driver    drv;
+       struct pcmcia_dynids    dynids;
 };
 
 /* driver registration */
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 765589f..5342ac6 100644 (file)
@@ -431,9 +431,11 @@ struct ib_wc {
        u8                      port_num;       /* valid only for DR SMPs on switches */
 };
 
-enum ib_cq_notify {
-       IB_CQ_SOLICITED,
-       IB_CQ_NEXT_COMP
+enum ib_cq_notify_flags {
+       IB_CQ_SOLICITED                 = 1 << 0,
+       IB_CQ_NEXT_COMP                 = 1 << 1,
+       IB_CQ_SOLICITED_MASK            = IB_CQ_SOLICITED | IB_CQ_NEXT_COMP,
+       IB_CQ_REPORT_MISSED_EVENTS      = 1 << 2,
 };
 
 enum ib_srq_attr_mask {
@@ -912,6 +914,8 @@ struct ib_device {
 
        u32                           flags;
 
+       int                           num_comp_vectors;
+
        struct iw_cm_verbs           *iwcm;
 
        int                        (*query_device)(struct ib_device *device,
@@ -978,6 +982,7 @@ struct ib_device {
                                                struct ib_recv_wr *recv_wr,
                                                struct ib_recv_wr **bad_recv_wr);
        struct ib_cq *             (*create_cq)(struct ib_device *device, int cqe,
+                                               int comp_vector,
                                                struct ib_ucontext *context,
                                                struct ib_udata *udata);
        int                        (*destroy_cq)(struct ib_cq *cq);
@@ -987,7 +992,7 @@ struct ib_device {
                                              struct ib_wc *wc);
        int                        (*peek_cq)(struct ib_cq *cq, int wc_cnt);
        int                        (*req_notify_cq)(struct ib_cq *cq,
-                                                   enum ib_cq_notify cq_notify);
+                                                   enum ib_cq_notify_flags flags);
        int                        (*req_ncomp_notif)(struct ib_cq *cq,
                                                      int wc_cnt);
        struct ib_mr *             (*get_dma_mr)(struct ib_pd *pd,
@@ -1358,13 +1363,15 @@ static inline int ib_post_recv(struct ib_qp *qp,
  * @cq_context: Context associated with the CQ returned to the user via
  *   the associated completion and event handlers.
  * @cqe: The minimum size of the CQ.
+ * @comp_vector - Completion vector used to signal completion events.
+ *     Must be >= 0 and < context->num_comp_vectors.
  *
  * Users can examine the cq structure to determine the actual CQ size.
  */
 struct ib_cq *ib_create_cq(struct ib_device *device,
                           ib_comp_handler comp_handler,
                           void (*event_handler)(struct ib_event *, void *),
-                          void *cq_context, int cqe);
+                          void *cq_context, int cqe, int comp_vector);
 
 /**
  * ib_resize_cq - Modifies the capacity of the CQ.
@@ -1414,14 +1421,34 @@ int ib_peek_cq(struct ib_cq *cq, int wc_cnt);
 /**
  * ib_req_notify_cq - Request completion notification on a CQ.
  * @cq: The CQ to generate an event for.
- * @cq_notify: If set to %IB_CQ_SOLICITED, completion notification will
- *   occur on the next solicited event. If set to %IB_CQ_NEXT_COMP,
- *   notification will occur on the next completion.
+ * @flags:
+ *   Must contain exactly one of %IB_CQ_SOLICITED or %IB_CQ_NEXT_COMP
+ *   to request an event on the next solicited event or next work
+ *   completion at any type, respectively. %IB_CQ_REPORT_MISSED_EVENTS
+ *   may also be |ed in to request a hint about missed events, as
+ *   described below.
+ *
+ * Return Value:
+ *    < 0 means an error occurred while requesting notification
+ *   == 0 means notification was requested successfully, and if
+ *        IB_CQ_REPORT_MISSED_EVENTS was passed in, then no events
+ *        were missed and it is safe to wait for another event.  In
+ *        this case is it guaranteed that any work completions added
+ *        to the CQ since the last CQ poll will trigger a completion
+ *        notification event.
+ *    > 0 is only returned if IB_CQ_REPORT_MISSED_EVENTS was passed
+ *        in.  It means that the consumer must poll the CQ again to
+ *        make sure it is empty to avoid missing an event because of a
+ *        race between requesting notification and an entry being
+ *        added to the CQ.  This return value means it is possible
+ *        (but not guaranteed) that a work completion has been added
+ *        to the CQ since the last poll without triggering a
+ *        completion notification event.
  */
 static inline int ib_req_notify_cq(struct ib_cq *cq,
-                                  enum ib_cq_notify cq_notify)
+                                  enum ib_cq_notify_flags flags)
 {
-       return cq->device->req_notify_cq(cq, cq_notify);
+       return cq->device->req_notify_cq(cq, flags);
 }
 
 /**
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 b170aa1..ebe04f5 100644 (file)
@@ -80,16 +80,20 @@ config LOCALVERSION_AUTO
        default y
        help
          This will try to automatically determine if the current tree is a
-         release tree by looking for git tags that
-         belong to the current top of tree revision.
+         release tree by looking for git tags that belong to the current
+         top of tree revision.
 
          A string of the format -gxxxxxxxx will be added to the localversion
-         if a git based tree is found.  The string generated by this will be
+         if a git-based tree is found.  The string generated by this will be
          appended after any matching localversion* files, and after the value
-         set in CONFIG_LOCALVERSION
+         set in CONFIG_LOCALVERSION.
 
-         Note: This requires Perl, and a git repository, but not necessarily
-         the git or cogito tools to be installed.
+         (The actual string used here is the first eight characters produced
+         by running the command:
+
+           $ git rev-parse --verify HEAD
+
+         which is done within the script "scripts/setlocalversion".)
 
 config SWAP
        bool "Support for paging of anonymous memory (swap)"
@@ -352,7 +356,7 @@ menuconfig EMBEDDED
 
 config UID16
        bool "Enable 16-bit UID system calls" if EMBEDDED
-       depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION)
+       depends on ARM || BFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION)
        default y
        help
          This enables the legacy 16-bit UID syscall wrappers.
@@ -474,15 +478,6 @@ config SHMEM
          option replaces shmem and tmpfs with the much simpler ramfs code,
          which may be appropriate on small systems without swap.
 
-config SLAB
-       default y
-       bool "Use full SLAB allocator" if (EMBEDDED && !SMP && !SPARSEMEM)
-       help
-         Disabling this replaces the advanced SLAB allocator and
-         kmalloc support with the drastically simpler SLOB allocator.
-         SLOB is more space efficient but does not scale well and is
-         more susceptible to fragmentation.
-
 config VM_EVENT_COUNTERS
        default y
        bool "Enable VM event counters for /proc/vmstat" if EMBEDDED
@@ -492,6 +487,46 @@ config VM_EVENT_COUNTERS
          on EMBEDDED systems.  /proc/vmstat will only show page counts
          if VM event counters are disabled.
 
+choice
+       prompt "Choose SLAB allocator"
+       default SLAB
+       help
+          This option allows to select a slab allocator.
+
+config SLAB
+       bool "SLAB"
+       help
+         The regular slab allocator that is established and known to work
+         well in all environments. It organizes chache hot objects in
+         per cpu and per node queues. SLAB is the default choice for
+         slab allocator.
+
+config SLUB
+       depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+       bool "SLUB (Unqueued Allocator)"
+       help
+          SLUB is a slab allocator that minimizes cache line usage
+          instead of managing queues of cached objects (SLAB approach).
+          Per cpu caching is realized using slabs of objects instead
+          of queues of objects. SLUB can use memory efficiently
+          way and has enhanced diagnostics.
+
+config SLOB
+#
+#      SLOB cannot support SMP because SLAB_DESTROY_BY_RCU does not work
+#      properly.
+#
+       depends on EMBEDDED && !SMP && !SPARSEMEM
+       bool "SLOB (Simple Allocator)"
+       help
+          SLOB replaces the SLAB allocator with a drastically simpler
+          allocator.  SLOB is more space efficient that SLAB but does not
+          scale well (single lock for all operations) and is more susceptible
+          to fragmentation. SLOB it is a great choice to reduce
+          memory usage and code size for embedded systems.
+
+endchoice
+
 endmenu                # General setup
 
 config RT_MUTEXES
@@ -507,10 +542,6 @@ config BASE_SMALL
        default 0 if BASE_FULL
        default 1 if !BASE_FULL
 
-config SLOB
-       default !SLAB
-       bool
-
 menu "Loadable module support"
 
 config MODULES
index 2cfd7cb..b222ce9 100644 (file)
@@ -55,11 +55,12 @@ static void __init handle_initrd(void)
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
        sys_chroot(".");
 
-       current->flags |= PF_NOFREEZE;
        pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
        if (pid > 0) {
-               while (pid != sys_wait4(-1, NULL, 0, NULL))
+               while (pid != sys_wait4(-1, NULL, 0, NULL)) {
+                       try_to_freeze();
                        yield();
+               }
        }
 
        /* move initrd to rootfs' /old */
index a92989e..0e22f40 100644 (file)
@@ -82,7 +82,7 @@
 #warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
 #endif
 
-static int init(void *);
+static int kernel_init(void *);
 
 extern void init_IRQ(void);
 extern void fork_init(unsigned long);
@@ -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;
@@ -388,11 +384,6 @@ static void __init setup_per_cpu_areas(void)
 static void __init smp_init(void)
 {
        unsigned int cpu;
-       unsigned highest = 0;
-
-       for_each_cpu_mask(cpu, cpu_possible_map)
-               highest = cpu;
-       nr_cpu_ids = highest + 1;
 
        /* FIXME: This should be done in userspace --RR */
        for_each_present_cpu(cpu) {
@@ -435,7 +426,7 @@ static void __init setup_command_line(char *command_line)
 static void noinline rest_init(void)
        __releases(kernel_lock)
 {
-       kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
+       kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
        unlock_kernel();
 
@@ -772,7 +763,7 @@ static int noinline init_post(void)
        panic("No init found.  Try passing init= option to kernel.");
 }
 
-static int __init init(void * unused)
+static int __init kernel_init(void * unused)
 {
        lock_kernel();
        /*
index 554ac36..d17821d 100644 (file)
@@ -215,8 +215,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags
 {
        struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-               SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&p->vfs_inode);
 }
 
index f382b0f..d240349 100644 (file)
@@ -2351,6 +2351,8 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
  * z's node is in our tasks mems_allowed, yes.  If it's not a
  * __GFP_HARDWALL request and this zone's nodes is in the nearest
  * mem_exclusive cpuset ancestor to this tasks cpuset, yes.
+ * If the task has been OOM killed and has access to memory reserves
+ * as specified by the TIF_MEMDIE flag, yes.
  * Otherwise, no.
  *
  * If __GFP_HARDWALL is set, cpuset_zone_allowed_softwall()
@@ -2368,7 +2370,8 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
  * calls get to this routine, we should just shut up and say 'yes'.
  *
  * GFP_USER allocations are marked with the __GFP_HARDWALL bit,
- * and do not allow allocations outside the current tasks cpuset.
+ * and do not allow allocations outside the current tasks cpuset
+ * unless the task has been OOM killed as is marked TIF_MEMDIE.
  * GFP_KERNEL allocations are not so marked, so can escape to the
  * nearest enclosing mem_exclusive ancestor cpuset.
  *
@@ -2392,6 +2395,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
  * affect that:
  *     in_interrupt - any node ok (current task context irrelevant)
  *     GFP_ATOMIC   - any node ok
+ *     TIF_MEMDIE   - any node ok
  *     GFP_KERNEL   - any node in enclosing mem_exclusive cpuset ok
  *     GFP_USER     - only nodes in current tasks mems allowed ok.
  *
@@ -2413,6 +2417,12 @@ int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
        might_sleep_if(!(gfp_mask & __GFP_HARDWALL));
        if (node_isset(node, current->mems_allowed))
                return 1;
+       /*
+        * Allow tasks that have access to memory reserves because they have
+        * been OOM killed to get memory anywhere.
+        */
+       if (unlikely(test_thread_flag(TIF_MEMDIE)))
+               return 1;
        if (gfp_mask & __GFP_HARDWALL)  /* If hardwall request, stop here */
                return 0;
 
@@ -2438,7 +2448,9 @@ int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
  *
  * If we're in interrupt, yes, we can always allocate.
  * If __GFP_THISNODE is set, yes, we can always allocate.  If zone
- * z's node is in our tasks mems_allowed, yes.   Otherwise, no.
+ * z's node is in our tasks mems_allowed, yes.   If the task has been
+ * OOM killed and has access to memory reserves as specified by the
+ * TIF_MEMDIE flag, yes.  Otherwise, no.
  *
  * The __GFP_THISNODE placement logic is really handled elsewhere,
  * by forcibly using a zonelist starting at a specified node, and by
@@ -2462,6 +2474,12 @@ int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
        node = zone_to_nid(z);
        if (node_isset(node, current->mems_allowed))
                return 1;
+        /*
+         * Allow tasks that have access to memory reserves because they have
+         * been OOM killed to get memory anywhere.
+         */
+        if (unlikely(test_thread_flag(TIF_MEMDIE)))
+                return 1;
        return 0;
 }
 
index 766d591..c0148ae 100644 (file)
@@ -31,11 +31,7 @@ __setup("nodelayacct", delayacct_setup_disable);
 
 void delayacct_init(void)
 {
-       delayacct_cache = kmem_cache_create("delayacct_cache",
-                                       sizeof(struct task_delay_info),
-                                       0,
-                                       SLAB_PANIC,
-                                       NULL, NULL);
+       delayacct_cache = KMEM_CACHE(task_delay_info, SLAB_PANIC);
        delayacct_tsk_init(&init_task);
 }
 
index b55ed4c..9236924 100644 (file)
@@ -1033,6 +1033,8 @@ asmlinkage void sys_exit_group(int error_code)
 
 static int eligible_child(pid_t pid, int options, struct task_struct *p)
 {
+       int err;
+
        if (pid > 0) {
                if (p->pid != pid)
                        return 0;
@@ -1066,8 +1068,9 @@ static int eligible_child(pid_t pid, int options, struct task_struct *p)
        if (delay_group_leader(p))
                return 2;
 
-       if (security_task_wait(p))
-               return 0;
+       err = security_task_wait(p);
+       if (err)
+               return err;
 
        return 1;
 }
@@ -1449,6 +1452,7 @@ static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
        DECLARE_WAITQUEUE(wait, current);
        struct task_struct *tsk;
        int flag, retval;
+       int allowed, denied;
 
        add_wait_queue(&current->signal->wait_chldexit,&wait);
 repeat:
@@ -1457,6 +1461,7 @@ repeat:
         * match our criteria, even if we are not able to reap it yet.
         */
        flag = 0;
+       allowed = denied = 0;
        current->state = TASK_INTERRUPTIBLE;
        read_lock(&tasklist_lock);
        tsk = current;
@@ -1472,6 +1477,12 @@ repeat:
                        if (!ret)
                                continue;
 
+                       if (unlikely(ret < 0)) {
+                               denied = ret;
+                               continue;
+                       }
+                       allowed = 1;
+
                        switch (p->state) {
                        case TASK_TRACED:
                                /*
@@ -1570,6 +1581,8 @@ check_continued:
                goto repeat;
        }
        retval = -ECHILD;
+       if (unlikely(denied) && !allowed)
+               retval = denied;
 end:
        current->state = TASK_RUNNING;
        remove_wait_queue(&current->signal->wait_chldexit,&wait);
index 6af959c..b7d169d 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);
@@ -1423,8 +1425,7 @@ static void sighand_ctor(void *data, struct kmem_cache *cachep, unsigned long fl
 {
        struct sighand_struct *sighand = data;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-                                       SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                spin_lock_init(&sighand->siglock);
 }
 
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 78f2aee..9c80bc2 100644 (file)
@@ -412,7 +412,5 @@ void __init pidmap_init(void)
        set_bit(0, init_pid_ns.pidmap[0].page);
        atomic_dec(&init_pid_ns.pidmap[0].nr_free);
 
-       pid_cachep = kmem_cache_create("pid", sizeof(struct pid),
-                                       __alignof__(struct pid),
-                                       SLAB_PANIC, NULL, NULL);
+       pid_cachep = KMEM_CACHE(pid, SLAB_PANIC);
 }
index 51a4dd0..8777217 100644 (file)
@@ -78,17 +78,22 @@ config PM_SYSFS_DEPRECATED
          are likely to be bus or driver specific.
 
 config SOFTWARE_SUSPEND
-       bool "Software Suspend"
+       bool "Software Suspend (Hibernation)"
        depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
        ---help---
-         Enable the suspend to disk (STD) functionality.
+         Enable the suspend to disk (STD) functionality, which is usually
+         called "hibernation" in user interfaces.  STD checkpoints the
+         system and powers it off; and restores that checkpoint on reboot.
 
          You can suspend your machine with 'echo disk > /sys/power/state'.
          Alternatively, you can use the additional userland tools available
          from <http://suspend.sf.net>.
 
          In principle it does not require ACPI or APM, although for example
-         ACPI will be used if available.
+         ACPI will be used for the final steps when it is available.  One
+         of the reasons to use software suspend is that the firmware hooks
+         for suspend states like suspend-to-RAM (STR) often don't work very
+         well with Linux.
 
          It creates an image which is saved in your active swap. Upon the next
          boot, pass the 'resume=/dev/swappartition' argument to the kernel to
index 02e4fb6..0633137 100644 (file)
@@ -130,15 +130,25 @@ int pm_suspend_disk(void)
 {
        int error;
 
+       /* The snapshot device should not be opened while we're running */
+       if (!atomic_add_unless(&snapshot_device_available, -1, 0))
+               return -EBUSY;
+
+       /* Allocate memory management structures */
+       error = create_basic_memory_bitmaps();
+       if (error)
+               goto Exit;
+
        error = prepare_processes();
        if (error)
-               return error;
+               goto Finish;
 
        if (pm_disk_mode == PM_DISK_TESTPROC) {
                printk("swsusp debug: Waiting for 5 seconds.\n");
                mdelay(5000);
                goto Thaw;
        }
+
        /* Free memory before shutting down devices. */
        error = swsusp_shrink_memory();
        if (error)
@@ -196,6 +206,10 @@ int pm_suspend_disk(void)
        resume_console();
  Thaw:
        unprepare_processes();
+ Finish:
+       free_basic_memory_bitmaps();
+ Exit:
+       atomic_inc(&snapshot_device_available);
        return error;
 }
 
@@ -239,13 +253,21 @@ static int software_resume(void)
        }
 
        pr_debug("PM: Checking swsusp image.\n");
-
        error = swsusp_check();
        if (error)
-               goto Done;
+               goto Unlock;
 
-       pr_debug("PM: Preparing processes for restore.\n");
+       /* The snapshot device should not be opened while we're running */
+       if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
+               error = -EBUSY;
+               goto Unlock;
+       }
 
+       error = create_basic_memory_bitmaps();
+       if (error)
+               goto Finish;
+
+       pr_debug("PM: Preparing processes for restore.\n");
        error = prepare_processes();
        if (error) {
                swsusp_close();
@@ -280,7 +302,11 @@ static int software_resume(void)
        printk(KERN_ERR "PM: Restore failed, recovering.\n");
        unprepare_processes();
  Done:
+       free_basic_memory_bitmaps();
+ Finish:
+       atomic_inc(&snapshot_device_available);
        /* For success case, the suspend path will release the lock */
+ Unlock:
        mutex_unlock(&pm_mutex);
        pr_debug("PM: Resume from disk failed.\n");
        return 0;
@@ -322,13 +348,40 @@ 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]);
+       int i;
+       char *start = buf;
+
+       for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) {
+               if (!pm_disk_modes[i])
+                       continue;
+               switch (i) {
+               case PM_DISK_SHUTDOWN:
+               case PM_DISK_REBOOT:
+               case PM_DISK_TEST:
+               case PM_DISK_TESTPROC:
+                       break;
+               default:
+                       if (pm_ops && pm_ops->enter &&
+                           (i == pm_ops->pm_disk_mode))
+                               break;
+                       /* not a valid mode, continue with loop */
+                       continue;
+               }
+               if (i == pm_disk_mode)
+                       buf += sprintf(buf, "[%s]", pm_disk_modes[i]);
+               else
+                       buf += sprintf(buf, "%s", pm_disk_modes[i]);
+               if (i+1 != PM_DISK_MAX)
+                       buf += sprintf(buf, " ");
+       }
+       buf += sprintf(buf, "\n");
+       return buf-start;
 }
 
 
-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 +426,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 +458,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 +492,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..f6dda68 100644 (file)
@@ -184,17 +184,21 @@ static void suspend_finish(suspend_state_t state)
 static const char * const pm_states[PM_SUSPEND_MAX] = {
        [PM_SUSPEND_STANDBY]    = "standby",
        [PM_SUSPEND_MEM]        = "mem",
-#ifdef CONFIG_SOFTWARE_SUSPEND
        [PM_SUSPEND_DISK]       = "disk",
-#endif
 };
 
 static inline int valid_state(suspend_state_t state)
 {
        /* Suspend-to-disk does not really need low-level support.
-        * It can work with reboot if needed. */
+        * It can work with shutdown/reboot if needed. If it isn't
+        * configured, then it cannot be supported.
+        */
        if (state == PM_SUSPEND_DISK)
+#ifdef CONFIG_SOFTWARE_SUSPEND
                return 1;
+#else
+               return 0;
+#endif
 
        /* all other states need lowlevel support and need to be
         * valid to the lowlevel implementation, no valid callback
@@ -244,15 +248,6 @@ static int enter_state(suspend_state_t state)
        return error;
 }
 
-/*
- * This is main interface to the outside world. It needs to be
- * called from process context.
- */
-int software_suspend(void)
-{
-       return enter_state(PM_SUSPEND_DISK);
-}
-
 
 /**
  *     pm_suspend - Externally visible function for suspending system.
@@ -285,7 +280,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 +293,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 +320,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 +360,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..34b4354 100644 (file)
@@ -14,8 +14,18 @@ struct swsusp_info {
 
 
 #ifdef CONFIG_SOFTWARE_SUSPEND
-extern int pm_suspend_disk(void);
+/*
+ * Keep some memory free so that I/O operations can succeed without paging
+ * [Might this be more than 4 MB?]
+ */
+#define PAGES_FOR_IO   ((4096 * 1024) >> PAGE_SHIFT)
+/*
+ * Keep 1 MB of memory free so that device drivers can allocate some pages in
+ * their .suspend() routines without breaking the suspend to disk.
+ */
+#define SPARE_PAGES    ((1024 * 1024) >> PAGE_SHIFT)
 
+extern int pm_suspend_disk(void);
 #else
 static inline int pm_suspend_disk(void)
 {
@@ -23,6 +33,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 +47,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;
@@ -49,6 +58,8 @@ extern sector_t swsusp_resume_block;
 extern asmlinkage int swsusp_arch_suspend(void);
 extern asmlinkage int swsusp_arch_resume(void);
 
+extern int create_basic_memory_bitmaps(void);
+extern void free_basic_memory_bitmaps(void);
 extern unsigned int count_data_pages(void);
 
 /**
@@ -139,30 +150,12 @@ struct resume_swap_area {
 #define PMOPS_ENTER    2
 #define PMOPS_FINISH   3
 
-/**
- *     The bitmap is used for tracing allocated swap pages
- *
- *     The entire bitmap consists of a number of bitmap_page
- *     structures linked with the help of the .next member.
- *     Thus each page can be allocated individually, so we only
- *     need to make 0-order memory allocations to create
- *     the bitmap.
- */
-
-#define BITMAP_PAGE_SIZE       (PAGE_SIZE - sizeof(void *))
-#define BITMAP_PAGE_CHUNKS     (BITMAP_PAGE_SIZE / sizeof(long))
-#define BITS_PER_CHUNK         (sizeof(long) * 8)
-#define BITMAP_PAGE_BITS       (BITMAP_PAGE_CHUNKS * BITS_PER_CHUNK)
-
-struct bitmap_page {
-       unsigned long           chunks[BITMAP_PAGE_CHUNKS];
-       struct bitmap_page      *next;
-};
+/* If unset, the snapshot device cannot be open. */
+extern atomic_t snapshot_device_available;
 
-extern void free_bitmap(struct bitmap_page *bitmap);
-extern struct bitmap_page *alloc_bitmap(unsigned int nr_bits);
-extern sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap);
-extern void free_all_swap_pages(int swap, struct bitmap_page *bitmap);
+extern sector_t alloc_swapdev_block(int swap);
+extern void free_all_swap_pages(int swap);
+extern int swsusp_swap_in_use(void);
 
 extern int swsusp_check(void);
 extern int swsusp_shrink_memory(void);
index 6d566bf..0eb5c42 100644 (file)
@@ -47,8 +47,10 @@ void refrigerator(void)
        recalc_sigpending(); /* We sent fake signal, clean it up */
        spin_unlock_irq(&current->sighand->siglock);
 
-       while (frozen(current)) {
-               current->state = TASK_UNINTERRUPTIBLE;
+       for (;;) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (!frozen(current))
+                       break;
                schedule();
        }
        pr_debug("%s left refrigerator\n", current->comm);
index fc53ad0..128da11 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/pm.h>
 #include <linux/device.h>
+#include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/syscalls.h>
 #include <linux/console.h>
 
 #include "power.h"
 
+static int swsusp_page_is_free(struct page *);
+static void swsusp_set_page_forbidden(struct page *);
+static void swsusp_unset_page_forbidden(struct page *);
+
 /* List of PBEs needed for restoring the pages that were allocated before
  * the suspend and included in the suspend image, but have also been
  * allocated by the "resume" kernel, so their contents cannot be written
@@ -67,15 +72,15 @@ static void *get_image_page(gfp_t gfp_mask, int safe_needed)
 
        res = (void *)get_zeroed_page(gfp_mask);
        if (safe_needed)
-               while (res && PageNosaveFree(virt_to_page(res))) {
+               while (res && swsusp_page_is_free(virt_to_page(res))) {
                        /* The page is unsafe, mark it for swsusp_free() */
-                       SetPageNosave(virt_to_page(res));
+                       swsusp_set_page_forbidden(virt_to_page(res));
                        allocated_unsafe_pages++;
                        res = (void *)get_zeroed_page(gfp_mask);
                }
        if (res) {
-               SetPageNosave(virt_to_page(res));
-               SetPageNosaveFree(virt_to_page(res));
+               swsusp_set_page_forbidden(virt_to_page(res));
+               swsusp_set_page_free(virt_to_page(res));
        }
        return res;
 }
@@ -91,8 +96,8 @@ static struct page *alloc_image_page(gfp_t gfp_mask)
 
        page = alloc_page(gfp_mask);
        if (page) {
-               SetPageNosave(page);
-               SetPageNosaveFree(page);
+               swsusp_set_page_forbidden(page);
+               swsusp_set_page_free(page);
        }
        return page;
 }
@@ -110,9 +115,9 @@ static inline void free_image_page(void *addr, int clear_nosave_free)
 
        page = virt_to_page(addr);
 
-       ClearPageNosave(page);
+       swsusp_unset_page_forbidden(page);
        if (clear_nosave_free)
-               ClearPageNosaveFree(page);
+               swsusp_unset_page_free(page);
 
        __free_page(page);
 }
@@ -224,11 +229,6 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
  *     of type unsigned long each).  It also contains the pfns that
  *     correspond to the start and end of the represented memory area and
  *     the number of bit chunks in the block.
- *
- *     NOTE: Memory bitmaps are used for two types of operations only:
- *     "set a bit" and "find the next bit set".  Moreover, the searching
- *     is always carried out after all of the "set a bit" operations
- *     on given bitmap.
  */
 
 #define BM_END_OF_MAP  (~0UL)
@@ -443,15 +443,13 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
 }
 
 /**
- *     memory_bm_set_bit - set the bit in the bitmap @bm that corresponds
+ *     memory_bm_find_bit - find the bit in the bitmap @bm that corresponds
  *     to given pfn.  The cur_zone_bm member of @bm and the cur_block member
  *     of @bm->cur_zone_bm are updated.
- *
- *     If the bit cannot be set, the function returns -EINVAL .
  */
 
-static int
-memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
+static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
+                               void **addr, unsigned int *bit_nr)
 {
        struct zone_bitmap *zone_bm;
        struct bm_block *bb;
@@ -463,8 +461,8 @@ memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
                /* We don't assume that the zones are sorted by pfns */
                while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) {
                        zone_bm = zone_bm->next;
-                       if (unlikely(!zone_bm))
-                               return -EINVAL;
+
+                       BUG_ON(!zone_bm);
                }
                bm->cur.zone_bm = zone_bm;
        }
@@ -475,13 +473,40 @@ memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
 
        while (pfn >= bb->end_pfn) {
                bb = bb->next;
-               if (unlikely(!bb))
-                       return -EINVAL;
+
+               BUG_ON(!bb);
        }
        zone_bm->cur_block = bb;
        pfn -= bb->start_pfn;
-       set_bit(pfn % BM_BITS_PER_CHUNK, bb->data + pfn / BM_BITS_PER_CHUNK);
-       return 0;
+       *bit_nr = pfn % BM_BITS_PER_CHUNK;
+       *addr = bb->data + pfn / BM_BITS_PER_CHUNK;
+}
+
+static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
+{
+       void *addr;
+       unsigned int bit;
+
+       memory_bm_find_bit(bm, pfn, &addr, &bit);
+       set_bit(bit, addr);
+}
+
+static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
+{
+       void *addr;
+       unsigned int bit;
+
+       memory_bm_find_bit(bm, pfn, &addr, &bit);
+       clear_bit(bit, addr);
+}
+
+static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
+{
+       void *addr;
+       unsigned int bit;
+
+       memory_bm_find_bit(bm, pfn, &addr, &bit);
+       return test_bit(bit, addr);
 }
 
 /* Two auxiliary functions for memory_bm_next_pfn */
@@ -563,6 +588,199 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
        return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit;
 }
 
+/**
+ *     This structure represents a range of page frames the contents of which
+ *     should not be saved during the suspend.
+ */
+
+struct nosave_region {
+       struct list_head list;
+       unsigned long start_pfn;
+       unsigned long end_pfn;
+};
+
+static LIST_HEAD(nosave_regions);
+
+/**
+ *     register_nosave_region - register a range of page frames the contents
+ *     of which should not be saved during the suspend (to be used in the early
+ *     initialization code)
+ */
+
+void __init
+register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+{
+       struct nosave_region *region;
+
+       if (start_pfn >= end_pfn)
+               return;
+
+       if (!list_empty(&nosave_regions)) {
+               /* Try to extend the previous region (they should be sorted) */
+               region = list_entry(nosave_regions.prev,
+                                       struct nosave_region, list);
+               if (region->end_pfn == start_pfn) {
+                       region->end_pfn = end_pfn;
+                       goto Report;
+               }
+       }
+       /* This allocation cannot fail */
+       region = alloc_bootmem_low(sizeof(struct nosave_region));
+       region->start_pfn = start_pfn;
+       region->end_pfn = end_pfn;
+       list_add_tail(&region->list, &nosave_regions);
+ Report:
+       printk("swsusp: Registered nosave memory region: %016lx - %016lx\n",
+               start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
+}
+
+/*
+ * Set bits in this map correspond to the page frames the contents of which
+ * should not be saved during the suspend.
+ */
+static struct memory_bitmap *forbidden_pages_map;
+
+/* Set bits in this map correspond to free page frames. */
+static struct memory_bitmap *free_pages_map;
+
+/*
+ * Each page frame allocated for creating the image is marked by setting the
+ * corresponding bits in forbidden_pages_map and free_pages_map simultaneously
+ */
+
+void swsusp_set_page_free(struct page *page)
+{
+       if (free_pages_map)
+               memory_bm_set_bit(free_pages_map, page_to_pfn(page));
+}
+
+static int swsusp_page_is_free(struct page *page)
+{
+       return free_pages_map ?
+               memory_bm_test_bit(free_pages_map, page_to_pfn(page)) : 0;
+}
+
+void swsusp_unset_page_free(struct page *page)
+{
+       if (free_pages_map)
+               memory_bm_clear_bit(free_pages_map, page_to_pfn(page));
+}
+
+static void swsusp_set_page_forbidden(struct page *page)
+{
+       if (forbidden_pages_map)
+               memory_bm_set_bit(forbidden_pages_map, page_to_pfn(page));
+}
+
+int swsusp_page_is_forbidden(struct page *page)
+{
+       return forbidden_pages_map ?
+               memory_bm_test_bit(forbidden_pages_map, page_to_pfn(page)) : 0;
+}
+
+static void swsusp_unset_page_forbidden(struct page *page)
+{
+       if (forbidden_pages_map)
+               memory_bm_clear_bit(forbidden_pages_map, page_to_pfn(page));
+}
+
+/**
+ *     mark_nosave_pages - set bits corresponding to the page frames the
+ *     contents of which should not be saved in a given bitmap.
+ */
+
+static void mark_nosave_pages(struct memory_bitmap *bm)
+{
+       struct nosave_region *region;
+
+       if (list_empty(&nosave_regions))
+               return;
+
+       list_for_each_entry(region, &nosave_regions, list) {
+               unsigned long pfn;
+
+               printk("swsusp: Marking nosave pages: %016lx - %016lx\n",
+                               region->start_pfn << PAGE_SHIFT,
+                               region->end_pfn << PAGE_SHIFT);
+
+               for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
+                       memory_bm_set_bit(bm, pfn);
+       }
+}
+
+/**
+ *     create_basic_memory_bitmaps - create bitmaps needed for marking page
+ *     frames that should not be saved and free page frames.  The pointers
+ *     forbidden_pages_map and free_pages_map are only modified if everything
+ *     goes well, because we don't want the bits to be used before both bitmaps
+ *     are set up.
+ */
+
+int create_basic_memory_bitmaps(void)
+{
+       struct memory_bitmap *bm1, *bm2;
+       int error = 0;
+
+       BUG_ON(forbidden_pages_map || free_pages_map);
+
+       bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
+       if (!bm1)
+               return -ENOMEM;
+
+       error = memory_bm_create(bm1, GFP_KERNEL, PG_ANY);
+       if (error)
+               goto Free_first_object;
+
+       bm2 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
+       if (!bm2)
+               goto Free_first_bitmap;
+
+       error = memory_bm_create(bm2, GFP_KERNEL, PG_ANY);
+       if (error)
+               goto Free_second_object;
+
+       forbidden_pages_map = bm1;
+       free_pages_map = bm2;
+       mark_nosave_pages(forbidden_pages_map);
+
+       printk("swsusp: Basic memory bitmaps created\n");
+
+       return 0;
+
+ Free_second_object:
+       kfree(bm2);
+ Free_first_bitmap:
+       memory_bm_free(bm1, PG_UNSAFE_CLEAR);
+ Free_first_object:
+       kfree(bm1);
+       return -ENOMEM;
+}
+
+/**
+ *     free_basic_memory_bitmaps - free memory bitmaps allocated by
+ *     create_basic_memory_bitmaps().  The auxiliary pointers are necessary
+ *     so that the bitmaps themselves are not referred to while they are being
+ *     freed.
+ */
+
+void free_basic_memory_bitmaps(void)
+{
+       struct memory_bitmap *bm1, *bm2;
+
+       BUG_ON(!(forbidden_pages_map && free_pages_map));
+
+       bm1 = forbidden_pages_map;
+       bm2 = free_pages_map;
+       forbidden_pages_map = NULL;
+       free_pages_map = NULL;
+       memory_bm_free(bm1, PG_UNSAFE_CLEAR);
+       kfree(bm1);
+       memory_bm_free(bm2, PG_UNSAFE_CLEAR);
+       kfree(bm2);
+
+       printk("swsusp: Basic memory bitmaps freed\n");
+}
+
 /**
  *     snapshot_additional_pages - estimate the number of additional pages
  *     be needed for setting up the suspend image data structures for given
@@ -615,7 +833,8 @@ static struct page *saveable_highmem_page(unsigned long pfn)
 
        BUG_ON(!PageHighMem(page));
 
-       if (PageNosave(page) || PageReserved(page) || PageNosaveFree(page))
+       if (swsusp_page_is_forbidden(page) ||  swsusp_page_is_free(page) ||
+           PageReserved(page))
                return NULL;
 
        return page;
@@ -650,17 +869,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.
@@ -681,7 +889,7 @@ static struct page *saveable_page(unsigned long pfn)
 
        BUG_ON(PageHighMem(page));
 
-       if (PageNosave(page) || PageNosaveFree(page))
+       if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
                return NULL;
 
        if (PageReserved(page) && pfn_is_nosave(pfn))
@@ -821,9 +1029,10 @@ void swsusp_free(void)
                        if (pfn_valid(pfn)) {
                                struct page *page = pfn_to_page(pfn);
 
-                               if (PageNosave(page) && PageNosaveFree(page)) {
-                                       ClearPageNosave(page);
-                                       ClearPageNosaveFree(page);
+                               if (swsusp_page_is_forbidden(page) &&
+                                   swsusp_page_is_free(page)) {
+                                       swsusp_unset_page_forbidden(page);
+                                       swsusp_unset_page_free(page);
                                        __free_page(page);
                                }
                        }
@@ -1146,7 +1355,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
                max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
                        if (pfn_valid(pfn))
-                               ClearPageNosaveFree(pfn_to_page(pfn));
+                               swsusp_unset_page_free(pfn_to_page(pfn));
        }
 
        /* Mark pages that correspond to the "original" pfns as "unsafe" */
@@ -1155,7 +1364,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
                pfn = memory_bm_next_pfn(bm);
                if (likely(pfn != BM_END_OF_MAP)) {
                        if (likely(pfn_valid(pfn)))
-                               SetPageNosaveFree(pfn_to_page(pfn));
+                               swsusp_set_page_free(pfn_to_page(pfn));
                        else
                                return -EFAULT;
                }
@@ -1321,14 +1530,14 @@ prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p)
                struct page *page;
 
                page = alloc_page(__GFP_HIGHMEM);
-               if (!PageNosaveFree(page)) {
+               if (!swsusp_page_is_free(page)) {
                        /* The page is "safe", set its bit the bitmap */
                        memory_bm_set_bit(bm, page_to_pfn(page));
                        safe_highmem_pages++;
                }
                /* Mark the page as allocated */
-               SetPageNosave(page);
-               SetPageNosaveFree(page);
+               swsusp_set_page_forbidden(page);
+               swsusp_set_page_free(page);
        }
        memory_bm_position_reset(bm);
        safe_highmem_bm = bm;
@@ -1360,7 +1569,7 @@ get_highmem_page_buffer(struct page *page, struct chain_allocator *ca)
        struct highmem_pbe *pbe;
        void *kaddr;
 
-       if (PageNosave(page) && PageNosaveFree(page)) {
+       if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page)) {
                /* We have allocated the "original" page frame and we can
                 * use it directly to store the loaded page.
                 */
@@ -1522,14 +1731,14 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
                        error = -ENOMEM;
                        goto Free;
                }
-               if (!PageNosaveFree(virt_to_page(lp))) {
+               if (!swsusp_page_is_free(virt_to_page(lp))) {
                        /* The page is "safe", add it to the list */
                        lp->next = safe_pages_list;
                        safe_pages_list = lp;
                }
                /* Mark the page as allocated */
-               SetPageNosave(virt_to_page(lp));
-               SetPageNosaveFree(virt_to_page(lp));
+               swsusp_set_page_forbidden(virt_to_page(lp));
+               swsusp_set_page_free(virt_to_page(lp));
                nr_pages--;
        }
        /* Free the reserved safe pages so that chain_alloc() can use them */
@@ -1558,7 +1767,7 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
        if (PageHighMem(page))
                return get_highmem_page_buffer(page, ca);
 
-       if (PageNosave(page) && PageNosaveFree(page))
+       if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page))
                /* We have allocated the "original" page frame and we can
                 * use it directly to store the loaded page.
                 */
index 3581f8f..e83ed99 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;
@@ -241,7 +243,6 @@ struct swap_map_page {
 struct swap_map_handle {
        struct swap_map_page *cur;
        sector_t cur_swap;
-       struct bitmap_page *bitmap;
        unsigned int k;
 };
 
@@ -250,9 +251,6 @@ static void release_swap_writer(struct swap_map_handle *handle)
        if (handle->cur)
                free_page((unsigned long)handle->cur);
        handle->cur = NULL;
-       if (handle->bitmap)
-               free_bitmap(handle->bitmap);
-       handle->bitmap = NULL;
 }
 
 static int get_swap_writer(struct swap_map_handle *handle)
@@ -260,12 +258,7 @@ static int get_swap_writer(struct swap_map_handle *handle)
        handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
        if (!handle->cur)
                return -ENOMEM;
-       handle->bitmap = alloc_bitmap(count_swap_pages(root_swap, 0));
-       if (!handle->bitmap) {
-               release_swap_writer(handle);
-               return -ENOMEM;
-       }
-       handle->cur_swap = alloc_swapdev_block(root_swap, handle->bitmap);
+       handle->cur_swap = alloc_swapdev_block(root_swap);
        if (!handle->cur_swap) {
                release_swap_writer(handle);
                return -ENOSPC;
@@ -282,7 +275,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
 
        if (!handle->cur)
                return -EINVAL;
-       offset = alloc_swapdev_block(root_swap, handle->bitmap);
+       offset = alloc_swapdev_block(root_swap);
        error = write_page(buf, offset, bio_chain);
        if (error)
                return error;
@@ -291,7 +284,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
                error = wait_on_bio_chain(bio_chain);
                if (error)
                        goto out;
-               offset = alloc_swapdev_block(root_swap, handle->bitmap);
+               offset = alloc_swapdev_block(root_swap);
                if (!offset)
                        return -ENOSPC;
                handle->cur->next_swap = offset;
@@ -428,7 +421,8 @@ int swsusp_write(void)
                }
        }
        if (error)
-               free_all_swap_pages(root_swap, handle.bitmap);
+               free_all_swap_pages(root_swap);
+
        release_swap_writer(&handle);
  out:
        swsusp_close();
@@ -564,7 +558,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 +585,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 +626,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 1753708..5da304c 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/syscalls.h>
 #include <linux/highmem.h>
 #include <linux/time.h>
+#include <linux/rbtree.h>
 
 #include "power.h"
 
@@ -74,72 +75,69 @@ static inline unsigned int count_highmem_pages(void) { return 0; }
 /**
  *     The following functions are used for tracing the allocated
  *     swap pages, so that they can be freed in case of an error.
- *
- *     The functions operate on a linked bitmap structure defined
- *     in power.h
  */
 
-void free_bitmap(struct bitmap_page *bitmap)
-{
-       struct bitmap_page *bp;
+struct swsusp_extent {
+       struct rb_node node;
+       unsigned long start;
+       unsigned long end;
+};
 
-       while (bitmap) {
-               bp = bitmap->next;
-               free_page((unsigned long)bitmap);
-               bitmap = bp;
-       }
-}
+static struct rb_root swsusp_extents = RB_ROOT;
 
-struct bitmap_page *alloc_bitmap(unsigned int nr_bits)
+static int swsusp_extents_insert(unsigned long swap_offset)
 {
-       struct bitmap_page *bitmap, *bp;
-       unsigned int n;
-
-       if (!nr_bits)
-               return NULL;
-
-       bitmap = (struct bitmap_page *)get_zeroed_page(GFP_KERNEL);
-       bp = bitmap;
-       for (n = BITMAP_PAGE_BITS; n < nr_bits; n += BITMAP_PAGE_BITS) {
-               bp->next = (struct bitmap_page *)get_zeroed_page(GFP_KERNEL);
-               bp = bp->next;
-               if (!bp) {
-                       free_bitmap(bitmap);
-                       return NULL;
+       struct rb_node **new = &(swsusp_extents.rb_node);
+       struct rb_node *parent = NULL;
+       struct swsusp_extent *ext;
+
+       /* Figure out where to put the new node */
+       while (*new) {
+               ext = container_of(*new, struct swsusp_extent, node);
+               parent = *new;
+               if (swap_offset < ext->start) {
+                       /* Try to merge */
+                       if (swap_offset == ext->start - 1) {
+                               ext->start--;
+                               return 0;
+                       }
+                       new = &((*new)->rb_left);
+               } else if (swap_offset > ext->end) {
+                       /* Try to merge */
+                       if (swap_offset == ext->end + 1) {
+                               ext->end++;
+                               return 0;
+                       }
+                       new = &((*new)->rb_right);
+               } else {
+                       /* It already is in the tree */
+                       return -EINVAL;
                }
        }
-       return bitmap;
-}
-
-static int bitmap_set(struct bitmap_page *bitmap, unsigned long bit)
-{
-       unsigned int n;
-
-       n = BITMAP_PAGE_BITS;
-       while (bitmap && n <= bit) {
-               n += BITMAP_PAGE_BITS;
-               bitmap = bitmap->next;
-       }
-       if (!bitmap)
-               return -EINVAL;
-       n -= BITMAP_PAGE_BITS;
-       bit -= n;
-       n = 0;
-       while (bit >= BITS_PER_CHUNK) {
-               bit -= BITS_PER_CHUNK;
-               n++;
-       }
-       bitmap->chunks[n] |= (1UL << bit);
+       /* Add the new node and rebalance the tree. */
+       ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL);
+       if (!ext)
+               return -ENOMEM;
+
+       ext->start = swap_offset;
+       ext->end = swap_offset;
+       rb_link_node(&ext->node, parent, new);
+       rb_insert_color(&ext->node, &swsusp_extents);
        return 0;
 }
 
-sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap)
+/**
+ *     alloc_swapdev_block - allocate a swap page and register that it has
+ *     been allocated, so that it can be freed in case of an error.
+ */
+
+sector_t alloc_swapdev_block(int swap)
 {
        unsigned long offset;
 
        offset = swp_offset(get_swap_page_of_type(swap));
        if (offset) {
-               if (bitmap_set(bitmap, offset))
+               if (swsusp_extents_insert(offset))
                        swap_free(swp_entry(swap, offset));
                else
                        return swapdev_block(swap, offset);
@@ -147,23 +145,34 @@ sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap)
        return 0;
 }
 
-void free_all_swap_pages(int swap, struct bitmap_page *bitmap)
+/**
+ *     free_all_swap_pages - free swap pages allocated for saving image data.
+ *     It also frees the extents used to register which swap entres had been
+ *     allocated.
+ */
+
+void free_all_swap_pages(int swap)
 {
-       unsigned int bit, n;
-       unsigned long test;
-
-       bit = 0;
-       while (bitmap) {
-               for (n = 0; n < BITMAP_PAGE_CHUNKS; n++)
-                       for (test = 1UL; test; test <<= 1) {
-                               if (bitmap->chunks[n] & test)
-                                       swap_free(swp_entry(swap, bit));
-                               bit++;
-                       }
-               bitmap = bitmap->next;
+       struct rb_node *node;
+
+       while ((node = swsusp_extents.rb_node)) {
+               struct swsusp_extent *ext;
+               unsigned long offset;
+
+               ext = container_of(node, struct swsusp_extent, node);
+               rb_erase(node, &swsusp_extents);
+               for (offset = ext->start; offset <= ext->end; offset++)
+                       swap_free(swp_entry(swap, offset));
+
+               kfree(ext);
        }
 }
 
+int swsusp_swap_in_use(void)
+{
+       return (swsusp_extents.rb_node != NULL);
+}
+
 /**
  *     swsusp_show_speed - print the time elapsed between two events represented by
  *     @start and @stop
@@ -224,7 +233,7 @@ int swsusp_shrink_memory(void)
                long size, highmem_size;
 
                highmem_size = count_highmem_pages();
-               size = count_data_pages() + PAGES_FOR_IO;
+               size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES;
                tmp = size;
                size += highmem_size;
                for_each_zone (zone)
index 7cf6713..040560d 100644 (file)
 static struct snapshot_data {
        struct snapshot_handle handle;
        int swap;
-       struct bitmap_page *bitmap;
        int mode;
        char frozen;
        char ready;
        char platform_suspend;
 } snapshot_state;
 
-static atomic_t device_available = ATOMIC_INIT(1);
+atomic_t snapshot_device_available = ATOMIC_INIT(1);
 
 static int snapshot_open(struct inode *inode, struct file *filp)
 {
        struct snapshot_data *data;
 
-       if (!atomic_add_unless(&device_available, -1, 0))
+       if (!atomic_add_unless(&snapshot_device_available, -1, 0))
                return -EBUSY;
 
-       if ((filp->f_flags & O_ACCMODE) == O_RDWR)
+       if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
+               atomic_inc(&snapshot_device_available);
                return -ENOSYS;
-
+       }
+       if(create_basic_memory_bitmaps()) {
+               atomic_inc(&snapshot_device_available);
+               return -ENOMEM;
+       }
        nonseekable_open(inode, filp);
        data = &snapshot_state;
        filp->private_data = data;
@@ -64,7 +68,6 @@ static int snapshot_open(struct inode *inode, struct file *filp)
                data->swap = -1;
                data->mode = O_WRONLY;
        }
-       data->bitmap = NULL;
        data->frozen = 0;
        data->ready = 0;
        data->platform_suspend = 0;
@@ -77,16 +80,15 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        struct snapshot_data *data;
 
        swsusp_free();
+       free_basic_memory_bitmaps();
        data = filp->private_data;
-       free_all_swap_pages(data->swap, data->bitmap);
-       free_bitmap(data->bitmap);
+       free_all_swap_pages(data->swap);
        if (data->frozen) {
                mutex_lock(&pm_mutex);
                thaw_processes();
-               enable_nonboot_cpus();
                mutex_unlock(&pm_mutex);
        }
-       atomic_inc(&device_available);
+       atomic_inc(&snapshot_device_available);
        return 0;
 }
 
@@ -294,14 +296,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        error = -ENODEV;
                        break;
                }
-               if (!data->bitmap) {
-                       data->bitmap = alloc_bitmap(count_swap_pages(data->swap, 0));
-                       if (!data->bitmap) {
-                               error = -ENOMEM;
-                               break;
-                       }
-               }
-               offset = alloc_swapdev_block(data->swap, data->bitmap);
+               offset = alloc_swapdev_block(data->swap);
                if (offset) {
                        offset <<= PAGE_SHIFT;
                        error = put_user(offset, (sector_t __user *)arg);
@@ -315,13 +310,11 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        error = -ENODEV;
                        break;
                }
-               free_all_swap_pages(data->swap, data->bitmap);
-               free_bitmap(data->bitmap);
-               data->bitmap = NULL;
+               free_all_swap_pages(data->swap);
                break;
 
        case SNAPSHOT_SET_SWAP_FILE:
-               if (!data->bitmap) {
+               if (!swsusp_swap_in_use()) {
                        /*
                         * User space encodes device types as two-byte values,
                         * so we need to recode them
@@ -420,7 +413,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                break;
 
        case SNAPSHOT_SET_SWAP_AREA:
-               if (data->bitmap) {
+               if (swsusp_swap_in_use()) {
                        error = -EPERM;
                } else {
                        struct resume_swap_area swap_area;
index 960d7c5..0227f16 100644 (file)
@@ -5244,6 +5244,11 @@ int __init migration_init(void)
 #endif
 
 #ifdef CONFIG_SMP
+
+/* Number of possible processor ids */
+int nr_cpu_ids __read_mostly = NR_CPUS;
+EXPORT_SYMBOL(nr_cpu_ids);
+
 #undef SCHED_DOMAIN_DEBUG
 #ifdef SCHED_DOMAIN_DEBUG
 static void sched_domain_debug(struct sched_domain *sd, int cpu)
@@ -6726,6 +6731,7 @@ int in_sched_functions(unsigned long addr)
 void __init sched_init(void)
 {
        int i, j, k;
+       int highest_cpu = 0;
 
        for_each_possible_cpu(i) {
                struct prio_array *array;
@@ -6760,11 +6766,13 @@ void __init sched_init(void)
                        // delimiter for bitsearch
                        __set_bit(MAX_PRIO, array->bitmap);
                }
+               highest_cpu = i;
        }
 
        set_load_weight(&init_task);
 
 #ifdef CONFIG_SMP
+       nr_cpu_ids = highest_cpu + 1;
        open_softirq(SCHED_SOFTIRQ, run_rebalance_domains, NULL);
 #endif
 
index 3670225..2b4087d 100644 (file)
@@ -2636,9 +2636,5 @@ __attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
 
 void __init signals_init(void)
 {
-       sigqueue_cachep =
-               kmem_cache_create("sigqueue",
-                                 sizeof(struct sigqueue),
-                                 __alignof__(struct sigqueue),
-                                 SLAB_PANIC, NULL, NULL);
+       sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
 }
index 123b165..fe1f3ab 100644 (file)
@@ -881,7 +881,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
 #ifdef CONFIG_SOFTWARE_SUSPEND
        case LINUX_REBOOT_CMD_SW_SUSPEND:
                {
-                       int ret = software_suspend();
+                       int ret = pm_suspend(PM_SUSPEND_DISK);
                        unlock_kernel();
                        return ret;
                }
index ad7d239..906cae7 100644 (file)
@@ -524,9 +524,7 @@ void __init taskstats_init_early(void)
 {
        unsigned int i;
 
-       taskstats_cache = kmem_cache_create("taskstats_cache",
-                                               sizeof(struct taskstats),
-                                               0, SLAB_PANIC, NULL, NULL);
+       taskstats_cache = KMEM_CACHE(taskstats, SLAB_PANIC);
        for_each_possible_cpu(i) {
                INIT_LIST_HEAD(&(per_cpu(listener_array, i).list));
                init_rwsem(&(per_cpu(listener_array, i).sem));
index 3842499..96d6e8c 100644 (file)
@@ -111,4 +111,9 @@ config HAS_IOPORT
        depends on HAS_IOMEM && !NO_IOPORT
        default y
 
+config HAS_DMA
+       boolean
+       depends on !NO_DMA
+       default y
+
 endmenu
index 79afd00..9a28779 100644 (file)
@@ -320,7 +320,7 @@ config DEBUG_HIGHMEM
 config DEBUG_BUGVERBOSE
        bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
        depends on BUG
-       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG
+       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG || BFIN
        default !EMBEDDED
        help
          Say Y here to make BUG() panics output the file name and line number
@@ -333,6 +333,9 @@ config DEBUG_INFO
        help
           If you say Y here the resulting kernel image will include
          debugging info resulting in a larger kernel image.
+         This adds debug symbols to the kernel and modules (gcc -g), and
+         is needed if you intend to use kernel crashdump or binary object
+         tools like crash, kgdb, LKCD, gdb, etc on the kernel.
          Say Y here only if you plan to debug the kernel.
 
          If unsure, say N.
@@ -357,7 +360,7 @@ config DEBUG_LIST
 
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
-       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH)
+       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH || BFIN)
        default y if DEBUG_INFO && UML
        help
          If you say Y here the resulting kernel image will be slightly larger
index 1ea2c18..bb4f76d 100644 (file)
@@ -15,9 +15,6 @@ int __next_cpu(int n, const cpumask_t *srcp)
 }
 EXPORT_SYMBOL(__next_cpu);
 
-int nr_cpu_ids;
-EXPORT_SYMBOL(nr_cpu_ids);
-
 int __any_online_cpu(const cpumask_t *mask)
 {
        int cpu;
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 fceb97c..7e1e311 100644 (file)
@@ -743,12 +743,14 @@ int zlib_inflate(z_streamp strm, int flush)
 
     strm->data_type = state->bits + (state->last ? 64 : 0) +
                       (state->mode == TYPE ? 128 : 0);
-    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
-        ret = Z_BUF_ERROR;
 
     if (flush == Z_PACKET_FLUSH && ret == Z_OK &&
-            (strm->avail_out != 0 || strm->avail_in == 0))
+            strm->avail_out != 0 && strm->avail_in == 0)
                return zlib_inflateSyncPacket(strm);
+
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+
     return ret;
 }
 
index 7942b33..1ac718f 100644 (file)
@@ -163,3 +163,8 @@ config ZONE_DMA_FLAG
        default "0" if !ZONE_DMA
        default "1"
 
+config NR_QUICK
+       int
+       depends on QUICKLIST
+       default "1"
+
index f3c077e..a9148ea 100644 (file)
@@ -25,7 +25,10 @@ obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_SLAB) += slab.o
+obj-$(CONFIG_SLUB) += slub.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
 obj-$(CONFIG_SMP) += allocpercpu.o
+obj-$(CONFIG_QUICKLIST) += quicklist.o
+
index 5dfc093..5631d6b 100644 (file)
@@ -868,6 +868,7 @@ void do_generic_mapping_read(struct address_space *mapping,
        unsigned long last_index;
        unsigned long next_index;
        unsigned long prev_index;
+       unsigned int prev_offset;
        loff_t isize;
        struct page *cached_page;
        int error;
@@ -876,7 +877,8 @@ void do_generic_mapping_read(struct address_space *mapping,
        cached_page = NULL;
        index = *ppos >> PAGE_CACHE_SHIFT;
        next_index = index;
-       prev_index = ra.prev_page;
+       prev_index = ra.prev_index;
+       prev_offset = ra.prev_offset;
        last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
        offset = *ppos & ~PAGE_CACHE_MASK;
 
@@ -924,10 +926,10 @@ page_ok:
                        flush_dcache_page(page);
 
                /*
-                * When (part of) the same page is read multiple times
-                * in succession, only mark it as accessed the first time.
+                * When a sequential read accesses a page several times,
+                * only mark it as accessed the first time.
                 */
-               if (prev_index != index)
+               if (prev_index != index || offset != prev_offset)
                        mark_page_accessed(page);
                prev_index = index;
 
@@ -945,6 +947,8 @@ page_ok:
                offset += ret;
                index += offset >> PAGE_CACHE_SHIFT;
                offset &= ~PAGE_CACHE_MASK;
+               prev_offset = offset;
+               ra.prev_offset = offset;
 
                page_cache_release(page);
                if (ret == nr && desc->count)
@@ -1446,30 +1450,6 @@ page_not_uptodate:
                majmin = VM_FAULT_MAJOR;
                count_vm_event(PGMAJFAULT);
        }
-       lock_page(page);
-
-       /* Did it get unhashed while we waited for it? */
-       if (!page->mapping) {
-               unlock_page(page);
-               page_cache_release(page);
-               goto retry_all;
-       }
-
-       /* Did somebody else get it up-to-date? */
-       if (PageUptodate(page)) {
-               unlock_page(page);
-               goto success;
-       }
-
-       error = mapping->a_ops->readpage(file, page);
-       if (!error) {
-               wait_on_page_locked(page);
-               if (PageUptodate(page))
-                       goto success;
-       } else if (error == AOP_TRUNCATED_PAGE) {
-               page_cache_release(page);
-               goto retry_find;
-       }
 
        /*
         * Umm, take care of errors if the page isn't up-to-date.
@@ -1726,7 +1706,7 @@ int generic_file_readonly_mmap(struct file * file, struct vm_area_struct * vma)
 EXPORT_SYMBOL(generic_file_mmap);
 EXPORT_SYMBOL(generic_file_readonly_mmap);
 
-static inline struct page *__read_cache_page(struct address_space *mapping,
+static struct page *__read_cache_page(struct address_space *mapping,
                                unsigned long index,
                                int (*filler)(void *,struct page*),
                                void *data)
@@ -1763,17 +1743,11 @@ repeat:
        return page;
 }
 
-/**
- * read_cache_page - read into page cache, fill it if needed
- * @mapping:   the page's address_space
- * @index:     the page index
- * @filler:    function to perform the read
- * @data:      destination for read data
- *
- * Read into the page cache. If a page already exists,
- * and PageUptodate() is not set, try to fill the page.
+/*
+ * Same as read_cache_page, but don't wait for page to become unlocked
+ * after submitting it to the filler.
  */
-struct page *read_cache_page(struct address_space *mapping,
+struct page *read_cache_page_async(struct address_space *mapping,
                                unsigned long index,
                                int (*filler)(void *,struct page*),
                                void *data)
@@ -1804,6 +1778,39 @@ retry:
                page_cache_release(page);
                page = ERR_PTR(err);
        }
+ out:
+       mark_page_accessed(page);
+       return page;
+}
+EXPORT_SYMBOL(read_cache_page_async);
+
+/**
+ * read_cache_page - read into page cache, fill it if needed
+ * @mapping:   the page's address_space
+ * @index:     the page index
+ * @filler:    function to perform the read
+ * @data:      destination for read data
+ *
+ * Read into the page cache. If a page already exists, and PageUptodate() is
+ * not set, try to fill the page then wait for it to become unlocked.
+ *
+ * If the page does not get brought uptodate, return -EIO.
+ */
+struct page *read_cache_page(struct address_space *mapping,
+                               unsigned long index,
+                               int (*filler)(void *,struct page*),
+                               void *data)
+{
+       struct page *page;
+
+       page = read_cache_page_async(mapping, index, filler, data);
+       if (IS_ERR(page))
+               goto out;
+       wait_on_page_locked(page);
+       if (!PageUptodate(page)) {
+               page_cache_release(page);
+               page = ERR_PTR(-EIO);
+       }
  out:
        return page;
 }
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 d527b80..a3110c0 100644 (file)
@@ -24,7 +24,7 @@ static inline void set_page_count(struct page *page, int v)
  */
 static inline void set_page_refcounted(struct page *page)
 {
-       VM_BUG_ON(PageCompound(page) && page_private(page) != (unsigned long)page);
+       VM_BUG_ON(PageCompound(page) && PageTail(page));
        VM_BUG_ON(atomic_read(&page->_count));
        set_page_count(page, 1);
 }
index 603c525..e75096b 100644 (file)
 #include <linux/mempolicy.h>
 #include <linux/hugetlb.h>
 
+/*
+ * Any behaviour which results in changes to the vma->vm_flags needs to
+ * take mmap_sem for writing. Others, which simply traverse vmas, need
+ * to only take it for reading.
+ */
+static int madvise_need_mmap_write(int behavior)
+{
+       switch (behavior) {
+       case MADV_REMOVE:
+       case MADV_WILLNEED:
+       case MADV_DONTNEED:
+               return 0;
+       default:
+               /* be safe, default to 1. list exceptions explicitly */
+               return 1;
+       }
+}
+
 /*
  * We can potentially split a vm area into separate
  * areas, each area with its own behavior.
@@ -183,9 +201,9 @@ static long madvise_remove(struct vm_area_struct *vma,
                        + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
 
        /* vmtruncate_range needs to take i_mutex and i_alloc_sem */
-       up_write(&current->mm->mmap_sem);
+       up_read(&current->mm->mmap_sem);
        error = vmtruncate_range(mapping->host, offset, endoff);
-       down_write(&current->mm->mmap_sem);
+       down_read(&current->mm->mmap_sem);
        return error;
 }
 
@@ -270,7 +288,10 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
        int error = -EINVAL;
        size_t len;
 
-       down_write(&current->mm->mmap_sem);
+       if (madvise_need_mmap_write(behavior))
+               down_write(&current->mm->mmap_sem);
+       else
+               down_read(&current->mm->mmap_sem);
 
        if (start & ~PAGE_MASK)
                goto out;
@@ -332,6 +353,10 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
                        vma = find_vma(current->mm, start);
        }
 out:
-       up_write(&current->mm->mmap_sem);
+       if (madvise_need_mmap_write(behavior))
+               up_write(&current->mm->mmap_sem);
+       else
+               up_read(&current->mm->mmap_sem);
+
        return error;
 }
index e7066e7..1d647ab 100644 (file)
@@ -1448,6 +1448,100 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
 }
 EXPORT_SYMBOL(remap_pfn_range);
 
+static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
+                                    unsigned long addr, unsigned long end,
+                                    pte_fn_t fn, void *data)
+{
+       pte_t *pte;
+       int err;
+       struct page *pmd_page;
+       spinlock_t *uninitialized_var(ptl);
+
+       pte = (mm == &init_mm) ?
+               pte_alloc_kernel(pmd, addr) :
+               pte_alloc_map_lock(mm, pmd, addr, &ptl);
+       if (!pte)
+               return -ENOMEM;
+
+       BUG_ON(pmd_huge(*pmd));
+
+       pmd_page = pmd_page(*pmd);
+
+       do {
+               err = fn(pte, pmd_page, addr, data);
+               if (err)
+                       break;
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+
+       if (mm != &init_mm)
+               pte_unmap_unlock(pte-1, ptl);
+       return err;
+}
+
+static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
+                                    unsigned long addr, unsigned long end,
+                                    pte_fn_t fn, void *data)
+{
+       pmd_t *pmd;
+       unsigned long next;
+       int err;
+
+       pmd = pmd_alloc(mm, pud, addr);
+       if (!pmd)
+               return -ENOMEM;
+       do {
+               next = pmd_addr_end(addr, end);
+               err = apply_to_pte_range(mm, pmd, addr, next, fn, data);
+               if (err)
+                       break;
+       } while (pmd++, addr = next, addr != end);
+       return err;
+}
+
+static int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd,
+                                    unsigned long addr, unsigned long end,
+                                    pte_fn_t fn, void *data)
+{
+       pud_t *pud;
+       unsigned long next;
+       int err;
+
+       pud = pud_alloc(mm, pgd, addr);
+       if (!pud)
+               return -ENOMEM;
+       do {
+               next = pud_addr_end(addr, end);
+               err = apply_to_pmd_range(mm, pud, addr, next, fn, data);
+               if (err)
+                       break;
+       } while (pud++, addr = next, addr != end);
+       return err;
+}
+
+/*
+ * Scan a region of virtual memory, filling in page tables as necessary
+ * and calling a provided function on each leaf page table.
+ */
+int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
+                       unsigned long size, pte_fn_t fn, void *data)
+{
+       pgd_t *pgd;
+       unsigned long next;
+       unsigned long end = addr + size;
+       int err;
+
+       BUG_ON(addr >= end);
+       pgd = pgd_offset(mm, addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               err = apply_to_pud_range(mm, pgd, addr, next, fn, data);
+               if (err)
+                       break;
+       } while (pgd++, addr = next, addr != end);
+       return err;
+}
+EXPORT_SYMBOL_GPL(apply_to_page_range);
+
 /*
  * handle_pte_fault chooses page fault handler according to an entry
  * which was read non-atomically.  Before making any commitment, on
@@ -2539,12 +2633,6 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
        spin_unlock(&mm->page_table_lock);
        return 0;
 }
-#else
-/* Workaround for gcc 2.96 */
-int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
-{
-       return 0;
-}
 #endif /* __PAGETABLE_PUD_FOLDED */
 
 #ifndef __PAGETABLE_PMD_FOLDED
@@ -2573,12 +2661,6 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
        spin_unlock(&mm->page_table_lock);
        return 0;
 }
-#else
-/* Workaround for gcc 2.96 */
-int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
-{
-       return 0;
-}
 #endif /* __PAGETABLE_PMD_FOLDED */
 
 int make_pages_present(unsigned long addr, unsigned long end)
index 84f997d..52646d6 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)
@@ -1199,6 +1200,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       if (flags & MAP_FIXED)
+               return addr;
+
        if (addr) {
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
@@ -1272,6 +1276,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        if (len > TASK_SIZE)
                return -ENOMEM;
 
+       if (flags & MAP_FIXED)
+               return addr;
+
        /* requesting a specific address */
        if (addr) {
                addr = PAGE_ALIGN(addr);
@@ -1360,38 +1367,21 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
                unsigned long pgoff, unsigned long flags)
 {
        unsigned long ret;
-
-       if (!(flags & MAP_FIXED)) {
-               unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
-
-               get_area = current->mm->get_unmapped_area;
-               if (file && file->f_op && file->f_op->get_unmapped_area)
-                       get_area = file->f_op->get_unmapped_area;
-               addr = get_area(file, addr, len, pgoff, flags);
-               if (IS_ERR_VALUE(addr))
-                       return addr;
-       }
+       unsigned long (*get_area)(struct file *, unsigned long,
+                                 unsigned long, unsigned long, unsigned long);
+
+       get_area = current->mm->get_unmapped_area;
+       if (file && file->f_op && file->f_op->get_unmapped_area)
+               get_area = file->f_op->get_unmapped_area;
+       addr = get_area(file, addr, len, pgoff, flags);
+       if (IS_ERR_VALUE(addr))
+               return addr;
 
        if (addr > TASK_SIZE - len)
                return -ENOMEM;
        if (addr & ~PAGE_MASK)
                return -EINVAL;
-       if (file && is_file_hugepages(file))  {
-               /*
-                * Check if the given range is hugepage aligned, and
-                * can be made suitable for hugepages.
-                */
-               ret = prepare_hugepage_range(addr, len, pgoff);
-       } else {
-               /*
-                * Ensure that a normal request is not falling in a
-                * reserved hugepage range.  For some archs like IA-64,
-                * there is a separate region for hugepages.
-                */
-               ret = is_hugepage_only_range(current->mm, addr, len);
-       }
-       if (ret)
-               return -EINVAL;
+
        return addr;
 }
 
@@ -1979,6 +1969,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 3791edf..a700141 100644 (file)
@@ -147,9 +147,11 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
         * Adjust the score by oomkilladj.
         */
        if (p->oomkilladj) {
-               if (p->oomkilladj > 0)
+               if (p->oomkilladj > 0) {
+                       if (!points)
+                               points = 1;
                        points <<= p->oomkilladj;
-               else
+               else
                        points >>= -(p->oomkilladj);
        }
 
@@ -397,6 +399,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
        struct task_struct *p;
        unsigned long points = 0;
        unsigned long freed = 0;
+       int constraint;
 
        blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
        if (freed > 0)
@@ -411,14 +414,18 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
                show_mem();
        }
 
-       cpuset_lock();
-       read_lock(&tasklist_lock);
+       if (sysctl_panic_on_oom == 2)
+               panic("out of memory. Compulsory panic_on_oom is selected.\n");
 
        /*
         * Check if there were limitations on the allocation (only relevant for
         * NUMA) that may require different handling.
         */
-       switch (constrained_alloc(zonelist, gfp_mask)) {
+       constraint = constrained_alloc(zonelist, gfp_mask);
+       cpuset_lock();
+       read_lock(&tasklist_lock);
+
+       switch (constraint) {
        case CONSTRAINT_MEMORY_POLICY:
                oom_kill_process(current, points,
                                "No available memory (MPOL_BIND)");
index a794945..029dfad 100644 (file)
@@ -119,6 +119,44 @@ static void background_writeout(unsigned long _min_pages);
  * We make sure that the background writeout level is below the adjusted
  * clamping level.
  */
+
+static unsigned long highmem_dirtyable_memory(unsigned long total)
+{
+#ifdef CONFIG_HIGHMEM
+       int node;
+       unsigned long x = 0;
+
+       for_each_online_node(node) {
+               struct zone *z =
+                       &NODE_DATA(node)->node_zones[ZONE_HIGHMEM];
+
+               x += zone_page_state(z, NR_FREE_PAGES)
+                       + zone_page_state(z, NR_INACTIVE)
+                       + zone_page_state(z, NR_ACTIVE);
+       }
+       /*
+        * Make sure that the number of highmem pages is never larger
+        * than the number of the total dirtyable memory. This can only
+        * occur in very strange VM situations but we want to make sure
+        * that this does not occur.
+        */
+       return min(x, total);
+#else
+       return 0;
+#endif
+}
+
+static unsigned long determine_dirtyable_memory(void)
+{
+       unsigned long x;
+
+       x = global_page_state(NR_FREE_PAGES)
+               + global_page_state(NR_INACTIVE)
+               + global_page_state(NR_ACTIVE);
+       x -= highmem_dirtyable_memory(x);
+       return x + 1;   /* Ensure that we never return 0 */
+}
+
 static void
 get_dirty_limits(long *pbackground, long *pdirty,
                                        struct address_space *mapping)
@@ -128,20 +166,12 @@ get_dirty_limits(long *pbackground, long *pdirty,
        int unmapped_ratio;
        long background;
        long dirty;
-       unsigned long available_memory = vm_total_pages;
+       unsigned long available_memory = determine_dirtyable_memory();
        struct task_struct *tsk;
 
-#ifdef CONFIG_HIGHMEM
-       /*
-        * We always exclude high memory from our count.
-        */
-       available_memory -= totalhigh_pages;
-#endif
-
-
        unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) +
                                global_page_state(NR_ANON_PAGES)) * 100) /
-                                       vm_total_pages;
+                                       available_memory;
 
        dirty_ratio = vm_dirty_ratio;
        if (dirty_ratio > unmapped_ratio / 2)
index 353ce90..5916431 100644 (file)
@@ -156,10 +156,8 @@ static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 
 static int page_is_consistent(struct zone *zone, struct page *page)
 {
-#ifdef CONFIG_HOLES_IN_ZONE
-       if (!pfn_valid(page_to_pfn(page)))
+       if (!pfn_valid_within(page_to_pfn(page)))
                return 0;
-#endif
        if (zone != page_zone(page))
                return 0;
 
@@ -227,7 +225,7 @@ static void bad_page(struct page *page)
 
 static void free_compound_page(struct page *page)
 {
-       __free_pages_ok(page, (unsigned long)page[1].lru.prev);
+       __free_pages_ok(page, compound_order(page));
 }
 
 static void prep_compound_page(struct page *page, unsigned long order)
@@ -236,12 +234,13 @@ static void prep_compound_page(struct page *page, unsigned long order)
        int nr_pages = 1 << order;
 
        set_compound_page_dtor(page, free_compound_page);
-       page[1].lru.prev = (void *)order;
-       for (i = 0; i < nr_pages; i++) {
+       set_compound_order(page, order);
+       __SetPageHead(page);
+       for (i = 1; i < nr_pages; i++) {
                struct page *p = page + i;
 
-               __SetPageCompound(p);
-               set_page_private(p, (unsigned long)page);
+               __SetPageTail(p);
+               p->first_page = page;
        }
 }
 
@@ -250,16 +249,19 @@ static void destroy_compound_page(struct page *page, unsigned long order)
        int i;
        int nr_pages = 1 << order;
 
-       if (unlikely((unsigned long)page[1].lru.prev != order))
+       if (unlikely(compound_order(page) != order))
                bad_page(page);
 
-       for (i = 0; i < nr_pages; i++) {
+       if (unlikely(!PageHead(page)))
+                       bad_page(page);
+       __ClearPageHead(page);
+       for (i = 1; i < nr_pages; i++) {
                struct page *p = page + i;
 
-               if (unlikely(!PageCompound(p) |
-                               (page_private(p) != (unsigned long)page)))
+               if (unlikely(!PageTail(p) |
+                               (p->first_page != page)))
                        bad_page(page);
-               __ClearPageCompound(p);
+               __ClearPageTail(p);
        }
 }
 
@@ -346,10 +348,8 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
 static inline int page_is_buddy(struct page *page, struct page *buddy,
                                                                int order)
 {
-#ifdef CONFIG_HOLES_IN_ZONE
-       if (!pfn_valid(page_to_pfn(buddy)))
+       if (!pfn_valid_within(page_to_pfn(buddy)))
                return 0;
-#endif
 
        if (page_zone_id(page) != page_zone_id(buddy))
                return 0;
@@ -433,13 +433,18 @@ static inline int free_pages_check(struct page *page)
                        1 << PG_private |
                        1 << PG_locked  |
                        1 << PG_active  |
-                       1 << PG_reclaim |
                        1 << PG_slab    |
                        1 << PG_swapcache |
                        1 << PG_writeback |
                        1 << PG_reserved |
                        1 << PG_buddy ))))
                bad_page(page);
+       /*
+        * PageReclaim == PageTail. It is only an error
+        * for PageReclaim to be set if PageCompound is clear.
+        */
+       if (unlikely(!PageCompound(page) && PageReclaim(page)))
+               bad_page(page);
        if (PageDirty(page))
                __ClearPageDirty(page);
        /*
@@ -665,7 +670,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
 }
 
 #if MAX_NUMNODES > 1
-int nr_node_ids __read_mostly;
+int nr_node_ids __read_mostly = MAX_NUMNODES;
 EXPORT_SYMBOL(nr_node_ids);
 
 /*
@@ -770,8 +775,8 @@ void mark_free_pages(struct zone *zone)
                if (pfn_valid(pfn)) {
                        struct page *page = pfn_to_page(pfn);
 
-                       if (!PageNosave(page))
-                               ClearPageNosaveFree(page);
+                       if (!swsusp_page_is_forbidden(page))
+                               swsusp_unset_page_free(page);
                }
 
        for (order = MAX_ORDER - 1; order >= 0; --order)
@@ -780,7 +785,7 @@ void mark_free_pages(struct zone *zone)
 
                        pfn = page_to_pfn(list_entry(curr, struct page, lru));
                        for (i = 0; i < (1UL << order); i++)
-                               SetPageNosaveFree(pfn_to_page(pfn + i));
+                               swsusp_set_page_free(pfn_to_page(pfn + i));
                }
 
        spin_unlock_irqrestore(&zone->lock, flags);
@@ -3203,7 +3208,8 @@ int min_free_kbytes_sysctl_handler(ctl_table *table, int write,
        struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
 {
        proc_dointvec(table, write, file, buffer, length, ppos);
-       setup_per_zone_pages_min();
+       if (write)
+               setup_per_zone_pages_min();
        return 0;
 }
 
diff --git a/mm/quicklist.c b/mm/quicklist.c
new file mode 100644 (file)
index 0000000..ae8189c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Quicklist support.
+ *
+ * Quicklists are light weight lists of pages that have a defined state
+ * on alloc and free. Pages must be in the quicklist specific defined state
+ * (zero by default) when the page is freed. It seems that the initial idea
+ * for such lists first came from Dave Miller and then various other people
+ * improved on it.
+ *
+ * Copyright (C) 2007 SGI,
+ *     Christoph Lameter <clameter@sgi.com>
+ *             Generalized, added support for multiple lists and
+ *             constructors / destructors.
+ */
+#include <linux/kernel.h>
+
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/quicklist.h>
+
+DEFINE_PER_CPU(struct quicklist, quicklist)[CONFIG_NR_QUICK];
+
+#define FRACTION_OF_NODE_MEM   16
+
+static unsigned long max_pages(unsigned long min_pages)
+{
+       unsigned long node_free_pages, max;
+
+       node_free_pages = node_page_state(numa_node_id(),
+                       NR_FREE_PAGES);
+       max = node_free_pages / FRACTION_OF_NODE_MEM;
+       return max(max, min_pages);
+}
+
+static long min_pages_to_free(struct quicklist *q,
+       unsigned long min_pages, long max_free)
+{
+       long pages_to_free;
+
+       pages_to_free = q->nr_pages - max_pages(min_pages);
+
+       return min(pages_to_free, max_free);
+}
+
+/*
+ * Trim down the number of pages in the quicklist
+ */
+void quicklist_trim(int nr, void (*dtor)(void *),
+       unsigned long min_pages, unsigned long max_free)
+{
+       long pages_to_free;
+       struct quicklist *q;
+
+       q = &get_cpu_var(quicklist)[nr];
+       if (q->nr_pages > min_pages) {
+               pages_to_free = min_pages_to_free(q, min_pages, max_free);
+
+               while (pages_to_free > 0) {
+                       /*
+                        * We pass a gfp_t of 0 to quicklist_alloc here
+                        * because we will never call into the page allocator.
+                        */
+                       void *p = quicklist_alloc(nr, 0, NULL);
+
+                       if (dtor)
+                               dtor(p);
+                       free_page((unsigned long)p);
+                       pages_to_free--;
+               }
+       }
+       put_cpu_var(quicklist);
+}
+
+unsigned long quicklist_total_size(void)
+{
+       unsigned long count = 0;
+       int cpu;
+       struct quicklist *ql, *q;
+
+       for_each_online_cpu(cpu) {
+               ql = per_cpu(quicklist, cpu);
+               for (q = ql; q < ql + CONFIG_NR_QUICK; q++)
+                       count += q->nr_pages;
+       }
+       return count;
+}
+
index 93d9ee6..9861e88 100644 (file)
@@ -37,7 +37,7 @@ void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
 {
        ra->ra_pages = mapping->backing_dev_info->ra_pages;
-       ra->prev_page = -1;
+       ra->prev_index = -1;
 }
 EXPORT_SYMBOL_GPL(file_ra_state_init);
 
@@ -202,17 +202,19 @@ out:
  * size:       Number of pages in that read
  *              Together, these form the "current window".
  *              Together, start and size represent the `readahead window'.
- * prev_page:   The page which the readahead algorithm most-recently inspected.
+ * prev_index:  The page which the readahead algorithm most-recently inspected.
  *              It is mainly used to detect sequential file reading.
  *              If page_cache_readahead sees that it is again being called for
  *              a page which it just looked at, it can return immediately without
  *              making any state changes.
+ * offset:      Offset in the prev_index where the last read ended - used for
+ *              detection of sequential file reading.
  * ahead_start,
  * ahead_size:  Together, these form the "ahead window".
  * ra_pages:   The externally controlled max readahead for this fd.
  *
  * When readahead is in the off state (size == 0), readahead is disabled.
- * In this state, prev_page is used to detect the resumption of sequential I/O.
+ * In this state, prev_index is used to detect the resumption of sequential I/O.
  *
  * The readahead code manages two windows - the "current" and the "ahead"
  * windows.  The intent is that while the application is walking the pages
@@ -415,7 +417,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp,
        ra->ahead_size = get_next_ra_size(ra);
        ra->ahead_start = ra->start + ra->size;
 
-       block = force || (ra->prev_page >= ra->ahead_start);
+       block = force || (ra->prev_index >= ra->ahead_start);
        ret = blockable_page_cache_readahead(mapping, filp,
                        ra->ahead_start, ra->ahead_size, ra, block);
 
@@ -467,12 +469,13 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
         * We avoid doing extra work and bogusly perturbing the readahead
         * window expansion logic.
         */
-       if (offset == ra->prev_page && --req_size)
+       if (offset == ra->prev_index && --req_size)
                ++offset;
 
-       /* Note that prev_page == -1 if it is a first read */
-       sequential = (offset == ra->prev_page + 1);
-       ra->prev_page = offset;
+       /* Note that prev_index == -1 if it is a first read */
+       sequential = (offset == ra->prev_index + 1);
+       ra->prev_index = offset;
+       ra->prev_offset = 0;
 
        max = get_max_readahead(ra);
        newsize = min(req_size, max);
@@ -481,7 +484,7 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
        if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE))
                goto out;
 
-       ra->prev_page += newsize - 1;
+       ra->prev_index += newsize - 1;
 
        /*
         * Special case - first read at start of file. We'll assume it's
@@ -537,18 +540,18 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
         * we get called back on the first page of the ahead window which
         * will allow us to submit more IO.
         */
-       if (ra->prev_page >= ra->ahead_start) {
+       if (ra->prev_index >= ra->ahead_start) {
                ra->start = ra->ahead_start;
                ra->size = ra->ahead_size;
                make_ahead_window(mapping, filp, ra, 0);
 recheck:
-               /* prev_page shouldn't overrun the ahead window */
-               ra->prev_page = min(ra->prev_page,
+               /* prev_index shouldn't overrun the ahead window */
+               ra->prev_index = min(ra->prev_index,
                        ra->ahead_start + ra->ahead_size - 1);
        }
 
 out:
-       return ra->prev_page + 1;
+       return ra->prev_index + 1;
 }
 EXPORT_SYMBOL_GPL(page_cache_readahead);
 
index 59da5b7..75a32be 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -162,8 +162,7 @@ void anon_vma_unlink(struct vm_area_struct *vma)
 static void anon_vma_ctor(void *data, struct kmem_cache *cachep,
                          unsigned long flags)
 {
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-                                               SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                struct anon_vma *anon_vma = data;
 
                spin_lock_init(&anon_vma->lock);
index b2a35eb..f01e8de 100644 (file)
@@ -2358,8 +2358,7 @@ static void init_once(void *foo, struct kmem_cache *cachep,
 {
        struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&p->vfs_inode);
 #ifdef CONFIG_TMPFS_POSIX_ACL
                p->i_acl = NULL;
index 4cbac24..5920a41 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
 #include       <asm/page.h>
 
 /*
- * DEBUG       - 1 for kmem_cache_create() to honour; SLAB_DEBUG_INITIAL,
- *               SLAB_RED_ZONE & SLAB_POISON.
+ * DEBUG       - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
  *               0 for faster, smaller code (especially in the critical paths).
  *
  * STATS       - 1 to collect stats for /proc/slabinfo.
 
 /* Legal flag mask for kmem_cache_create(). */
 #if DEBUG
-# define CREATE_MASK   (SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
+# define CREATE_MASK   (SLAB_RED_ZONE | \
                         SLAB_POISON | SLAB_HWCACHE_ALIGN | \
                         SLAB_CACHE_DMA | \
-                        SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \
+                        SLAB_STORE_USER | \
                         SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
                         SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD)
 #else
 # define CREATE_MASK   (SLAB_HWCACHE_ALIGN | \
-                        SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \
+                        SLAB_CACHE_DMA | \
                         SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
                         SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD)
 #endif
@@ -389,7 +388,6 @@ struct kmem_cache {
        unsigned int buffer_size;
        u32 reciprocal_buffer_size;
 /* 3) touched by every alloc & free from the backend */
-       struct kmem_list3 *nodelists[MAX_NUMNODES];
 
        unsigned int flags;             /* constant flags */
        unsigned int num;               /* # of objs per slab */
@@ -444,6 +442,17 @@ struct kmem_cache {
        int obj_offset;
        int obj_size;
 #endif
+       /*
+        * We put nodelists[] at the end of kmem_cache, because we want to size
+        * this array to nr_node_ids slots instead of MAX_NUMNODES
+        * (see kmem_cache_init())
+        * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
+        * is statically defined, so we reserve the max number of nodes.
+        */
+       struct kmem_list3 *nodelists[MAX_NUMNODES];
+       /*
+        * Do not add fields after nodelists[]
+        */
 };
 
 #define CFLGS_OFF_SLAB         (0x80000000UL)
@@ -592,8 +601,7 @@ static inline void page_set_cache(struct page *page, struct kmem_cache *cache)
 
 static inline struct kmem_cache *page_get_cache(struct page *page)
 {
-       if (unlikely(PageCompound(page)))
-               page = (struct page *)page_private(page);
+       page = compound_head(page);
        BUG_ON(!PageSlab(page));
        return (struct kmem_cache *)page->lru.next;
 }
@@ -605,21 +613,19 @@ static inline void page_set_slab(struct page *page, struct slab *slab)
 
 static inline struct slab *page_get_slab(struct page *page)
 {
-       if (unlikely(PageCompound(page)))
-               page = (struct page *)page_private(page);
        BUG_ON(!PageSlab(page));
        return (struct slab *)page->lru.prev;
 }
 
 static inline struct kmem_cache *virt_to_cache(const void *obj)
 {
-       struct page *page = virt_to_page(obj);
+       struct page *page = virt_to_head_page(obj);
        return page_get_cache(page);
 }
 
 static inline struct slab *virt_to_slab(const void *obj)
 {
-       struct page *page = virt_to_page(obj);
+       struct page *page = virt_to_head_page(obj);
        return page_get_slab(page);
 }
 
@@ -678,9 +684,6 @@ static struct kmem_cache cache_cache = {
        .shared = 1,
        .buffer_size = sizeof(struct kmem_cache),
        .name = "kmem_cache",
-#if DEBUG
-       .obj_size = sizeof(struct kmem_cache),
-#endif
 };
 
 #define BAD_ALIEN_MAGIC 0x01020304ul
@@ -1146,7 +1149,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];
@@ -1223,19 +1226,20 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                 */
                list_for_each_entry(cachep, &cache_chain, next) {
                        struct array_cache *nc;
-                       struct array_cache *shared;
+                       struct array_cache *shared = NULL;
                        struct array_cache **alien = NULL;
 
                        nc = alloc_arraycache(node, cachep->limit,
                                                cachep->batchcount);
                        if (!nc)
                                goto bad;
-                       shared = alloc_arraycache(node,
+                       if (cachep->shared) {
+                               shared = alloc_arraycache(node,
                                        cachep->shared * cachep->batchcount,
                                        0xbaadf00d);
-                       if (!shared)
-                               goto bad;
-
+                               if (!shared)
+                                       goto bad;
+                       }
                        if (use_alien_caches) {
                                 alien = alloc_alien_cache(node, cachep->limit);
                                 if (!alien)
@@ -1317,8 +1321,8 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
 
                        shared = l3->shared;
                        if (shared) {
-                               free_block(cachep, l3->shared->entry,
-                                          l3->shared->avail, node);
+                               free_block(cachep, shared->entry,
+                                          shared->avail, node);
                                l3->shared = NULL;
                        }
 
@@ -1394,6 +1398,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)
@@ -1436,6 +1443,15 @@ void __init kmem_cache_init(void)
        cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
        cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];
 
+       /*
+        * struct kmem_cache size depends on nr_node_ids, which
+        * can be less than MAX_NUMNODES.
+        */
+       cache_cache.buffer_size = offsetof(struct kmem_cache, nodelists) +
+                                nr_node_ids * sizeof(struct kmem_list3 *);
+#if DEBUG
+       cache_cache.obj_size = cache_cache.buffer_size;
+#endif
        cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
                                        cache_line_size());
        cache_cache.reciprocal_buffer_size =
@@ -1929,7 +1945,7 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
  * For setting up all the kmem_list3s for cache whose buffer_size is same as
  * size of kmem_list3.
  */
-static void set_up_list3s(struct kmem_cache *cachep, int index)
+static void __init set_up_list3s(struct kmem_cache *cachep, int index)
 {
        int node;
 
@@ -2151,13 +2167,15 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                 */
                res = probe_kernel_address(pc->name, tmp);
                if (res) {
-                       printk("SLAB: cache with size %d has lost its name\n",
+                       printk(KERN_ERR
+                              "SLAB: cache with size %d has lost its name\n",
                               pc->buffer_size);
                        continue;
                }
 
                if (!strcmp(pc->name, name)) {
-                       printk("kmem_cache_create: duplicate cache %s\n", name);
+                       printk(KERN_ERR
+                              "kmem_cache_create: duplicate cache %s\n", name);
                        dump_stack();
                        goto oops;
                }
@@ -2165,12 +2183,6 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 
 #if DEBUG
        WARN_ON(strchr(name, ' '));     /* It confuses parsers */
-       if ((flags & SLAB_DEBUG_INITIAL) && !ctor) {
-               /* No constructor, but inital state check requested */
-               printk(KERN_ERR "%s: No con, but init state check "
-                      "requested - %s\n", __FUNCTION__, name);
-               flags &= ~SLAB_DEBUG_INITIAL;
-       }
 #if FORCED_DEBUG
        /*
         * Enable redzoning and last user accounting, except for caches with
@@ -2294,7 +2306,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        left_over = calculate_slab_order(cachep, size, align, flags);
 
        if (!cachep->num) {
-               printk("kmem_cache_create: couldn't create cache %s.\n", name);
+               printk(KERN_ERR
+                      "kmem_cache_create: couldn't create cache %s.\n", name);
                kmem_cache_free(&cache_cache, cachep);
                cachep = NULL;
                goto oops;
@@ -2733,19 +2746,10 @@ static int cache_grow(struct kmem_cache *cachep,
         * Be lazy and only check for valid flags here,  keeping it out of the
         * critical path in kmem_cache_alloc().
         */
-       BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK | __GFP_NO_GROW));
-       if (flags & __GFP_NO_GROW)
-               return 0;
+       BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
 
        ctor_flags = SLAB_CTOR_CONSTRUCTOR;
        local_flags = (flags & GFP_LEVEL_MASK);
-       if (!(local_flags & __GFP_WAIT))
-               /*
-                * Not allowed to sleep.  Need to tell a constructor about
-                * this - it might need to know...
-                */
-               ctor_flags |= SLAB_CTOR_ATOMIC;
-
        /* Take the l3 list lock to change the colour_next on this node */
        check_irq_off();
        l3 = cachep->nodelists[nodeid];
@@ -2858,7 +2862,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
 
        objp -= obj_offset(cachep);
        kfree_debugcheck(objp);
-       page = virt_to_page(objp);
+       page = virt_to_head_page(objp);
 
        slabp = page_get_slab(page);
 
@@ -2875,15 +2879,6 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
        BUG_ON(objnr >= cachep->num);
        BUG_ON(objp != index_to_obj(cachep, slabp, objnr));
 
-       if (cachep->flags & SLAB_DEBUG_INITIAL) {
-               /*
-                * Need to call the slab's constructor so the caller can
-                * perform a verify of its state (debugging).  Called without
-                * the cache-lock held.
-                */
-               cachep->ctor(objp + obj_offset(cachep),
-                            cachep, SLAB_CTOR_CONSTRUCTOR | SLAB_CTOR_VERIFY);
-       }
        if (cachep->flags & SLAB_POISON && cachep->dtor) {
                /* we want to cache poison the object,
                 * call the destruction callback
@@ -2987,6 +2982,14 @@ retry:
                slabp = list_entry(entry, struct slab, list);
                check_slabp(cachep, slabp);
                check_spinlock_acquired(cachep);
+
+               /*
+                * The slab was either on partial or free list so
+                * there must be at least one object available for
+                * allocation.
+                */
+               BUG_ON(slabp->inuse < 0 || slabp->inuse >= cachep->num);
+
                while (slabp->inuse < cachep->num && batchcount--) {
                        STATS_INC_ALLOCED(cachep);
                        STATS_INC_ACTIVE(cachep);
@@ -3074,20 +3077,14 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
                struct slab *slabp;
                unsigned objnr;
 
-               slabp = page_get_slab(virt_to_page(objp));
+               slabp = page_get_slab(virt_to_head_page(objp));
                objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
                slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE;
        }
 #endif
        objp += obj_offset(cachep);
-       if (cachep->ctor && cachep->flags & SLAB_POISON) {
-               unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR;
-
-               if (!(flags & __GFP_WAIT))
-                       ctor_flags |= SLAB_CTOR_ATOMIC;
-
-               cachep->ctor(objp, cachep, ctor_flags);
-       }
+       if (cachep->ctor && cachep->flags & SLAB_POISON)
+               cachep->ctor(objp, cachep, SLAB_CTOR_CONSTRUCTOR);
 #if ARCH_SLAB_MINALIGN
        if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) {
                printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
@@ -3142,7 +3139,7 @@ static int __init failslab_debugfs(void)
        struct dentry *dir;
        int err;
 
-               err = init_fault_attr_dentries(&failslab.attr, "failslab");
+       err = init_fault_attr_dentries(&failslab.attr, "failslab");
        if (err)
                return err;
        dir = failslab.attr.dentries.dir;
@@ -3180,9 +3177,6 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 
        check_irq_off();
 
-       if (should_failslab(cachep, flags))
-               return NULL;
-
        ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
                STATS_INC_ALLOCHIT(cachep);
@@ -3256,7 +3250,7 @@ retry:
                                        flags | GFP_THISNODE, nid);
        }
 
-       if (!obj && !(flags & __GFP_NO_GROW)) {
+       if (!obj) {
                /*
                 * This allocation will be performed within the constraints
                 * of the current cpuset / memory policy requirements.
@@ -3374,6 +3368,9 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
        unsigned long save_flags;
        void *ptr;
 
+       if (should_failslab(cachep, flags))
+               return NULL;
+
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
 
@@ -3444,6 +3441,9 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
        unsigned long save_flags;
        void *objp;
 
+       if (should_failslab(cachep, flags))
+               return NULL;
+
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
        objp = __do_cache_alloc(cachep, flags);
@@ -3563,7 +3563,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)) {
@@ -3736,6 +3736,53 @@ void *__kmalloc(size_t size, gfp_t flags)
 EXPORT_SYMBOL(__kmalloc);
 #endif
 
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ *
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+       struct kmem_cache *cache, *new_cache;
+       void *ret;
+
+       if (unlikely(!p))
+               return kmalloc_track_caller(new_size, flags);
+
+       if (unlikely(!new_size)) {
+               kfree(p);
+               return NULL;
+       }
+
+       cache = virt_to_cache(p);
+       new_cache = __find_general_cachep(new_size, flags);
+
+       /*
+        * If new size fits in the current cache, bail out.
+        */
+       if (likely(cache == new_cache))
+               return (void *)p;
+
+       /*
+        * We are on the slow-path here so do not use __cache_alloc
+        * because it bloats kernel text.
+        */
+       ret = kmalloc_track_caller(new_size, flags);
+       if (ret) {
+               memcpy(ret, p, min(new_size, ksize(p)));
+               kfree(p);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(krealloc);
+
 /**
  * kmem_cache_free - Deallocate an object
  * @cachep: The cache the allocation was from.
@@ -3812,12 +3859,15 @@ static int alloc_kmemlist(struct kmem_cache *cachep)
                                 goto fail;
                 }
 
-               new_shared = alloc_arraycache(node,
+               new_shared = NULL;
+               if (cachep->shared) {
+                       new_shared = alloc_arraycache(node,
                                cachep->shared*cachep->batchcount,
                                        0xbaadf00d);
-               if (!new_shared) {
-                       free_alien_cache(new_alien);
-                       goto fail;
+                       if (!new_shared) {
+                               free_alien_cache(new_alien);
+                               goto fail;
+                       }
                }
 
                l3 = cachep->nodelists[node];
@@ -3975,10 +4025,8 @@ static int enable_cpucache(struct kmem_cache *cachep)
         * to a larger limit. Thus disabled by default.
         */
        shared = 0;
-#ifdef CONFIG_SMP
-       if (cachep->buffer_size <= PAGE_SIZE)
+       if (cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1)
                shared = 8;
-#endif
 
 #if DEBUG
        /*
@@ -4478,7 +4526,7 @@ const struct seq_operations slabstats_op = {
  * allocated with either kmalloc() or kmem_cache_alloc(). The object
  * must not be freed during the duration of the call.
  */
-unsigned int ksize(const void *objp)
+size_t ksize(const void *objp)
 {
        if (unlikely(objp == NULL))
                return 0;
index 5adc29c..c6933bc 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -21,7 +21,7 @@
  *
  * SLAB is emulated on top of SLOB by simply calling constructors and
  * destructors for every SLAB allocation. Objects are returned with
- * the 8-byte alignment unless the SLAB_MUST_HWCACHE_ALIGN flag is
+ * the 8-byte alignment unless the SLAB_HWCACHE_ALIGN flag is
  * set, in which case the low-level allocator will fragment blocks to
  * create the proper alignment. Again, objects of page-size or greater
  * are allocated by calling __get_free_pages. As SLAB objects know
@@ -150,15 +150,6 @@ static void slob_free(void *block, int size)
        spin_unlock_irqrestore(&slob_lock, flags);
 }
 
-static int FASTCALL(find_order(int size));
-static int fastcall find_order(int size)
-{
-       int order = 0;
-       for ( ; size > 4096 ; size >>=1)
-               order++;
-       return order;
-}
-
 void *__kmalloc(size_t size, gfp_t gfp)
 {
        slob_t *m;
@@ -174,7 +165,7 @@ void *__kmalloc(size_t size, gfp_t gfp)
        if (!bb)
                return 0;
 
-       bb->order = find_order(size);
+       bb->order = get_order(size);
        bb->pages = (void *)__get_free_pages(gfp, bb->order);
 
        if (bb->pages) {
@@ -190,6 +181,39 @@ void *__kmalloc(size_t size, gfp_t gfp)
 }
 EXPORT_SYMBOL(__kmalloc);
 
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ *
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+       void *ret;
+
+       if (unlikely(!p))
+               return kmalloc_track_caller(new_size, flags);
+
+       if (unlikely(!new_size)) {
+               kfree(p);
+               return NULL;
+       }
+
+       ret = kmalloc_track_caller(new_size, flags);
+       if (ret) {
+               memcpy(ret, p, min(new_size, ksize(p)));
+               kfree(p);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(krealloc);
+
 void kfree(const void *block)
 {
        bigblock_t *bb, **last = &bigblocks;
@@ -219,7 +243,7 @@ void kfree(const void *block)
 
 EXPORT_SYMBOL(kfree);
 
-unsigned int ksize(const void *block)
+size_t ksize(const void *block)
 {
        bigblock_t *bb;
        unsigned long flags;
@@ -262,10 +286,11 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
                c->ctor = ctor;
                c->dtor = dtor;
                /* ignore alignment unless it's forced */
-               c->align = (flags & SLAB_MUST_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+               c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
                if (c->align < align)
                        c->align = align;
-       }
+       } else if (flags & SLAB_PANIC)
+               panic("Cannot create slab cache %s\n", name);
 
        return c;
 }
@@ -284,7 +309,7 @@ void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)
        if (c->size < PAGE_SIZE)
                b = slob_alloc(c->size, flags, c->align);
        else
-               b = (void *)__get_free_pages(flags, find_order(c->size));
+               b = (void *)__get_free_pages(flags, get_order(c->size));
 
        if (c->ctor)
                c->ctor(b, c, SLAB_CTOR_CONSTRUCTOR);
@@ -311,7 +336,7 @@ void kmem_cache_free(struct kmem_cache *c, void *b)
        if (c->size < PAGE_SIZE)
                slob_free(b, c->size);
        else
-               free_pages((unsigned long)b, find_order(c->size));
+               free_pages((unsigned long)b, get_order(c->size));
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
diff --git a/mm/slub.c b/mm/slub.c
new file mode 100644 (file)
index 0000000..5db3da5
--- /dev/null
+++ b/mm/slub.c
@@ -0,0 +1,3520 @@
+/*
+ * SLUB: A slab allocator that limits cache line use instead of queuing
+ * objects in per cpu and per node lists.
+ *
+ * The allocator synchronizes using per slab locks and only
+ * uses a centralized lock to manage a pool of partial slabs.
+ *
+ * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/bit_spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/cpuset.h>
+#include <linux/mempolicy.h>
+#include <linux/ctype.h>
+#include <linux/kallsyms.h>
+
+/*
+ * Lock order:
+ *   1. slab_lock(page)
+ *   2. slab->list_lock
+ *
+ *   The slab_lock protects operations on the object of a particular
+ *   slab and its metadata in the page struct. If the slab lock
+ *   has been taken then no allocations nor frees can be performed
+ *   on the objects in the slab nor can the slab be added or removed
+ *   from the partial or full lists since this would mean modifying
+ *   the page_struct of the slab.
+ *
+ *   The list_lock protects the partial and full list on each node and
+ *   the partial slab counter. If taken then no new slabs may be added or
+ *   removed from the lists nor make the number of partial slabs be modified.
+ *   (Note that the total number of slabs is an atomic value that may be
+ *   modified without taking the list lock).
+ *
+ *   The list_lock is a centralized lock and thus we avoid taking it as
+ *   much as possible. As long as SLUB does not have to handle partial
+ *   slabs, operations can continue without any centralized lock. F.e.
+ *   allocating a long series of objects that fill up slabs does not require
+ *   the list lock.
+ *
+ *   The lock order is sometimes inverted when we are trying to get a slab
+ *   off a list. We take the list_lock and then look for a page on the list
+ *   to use. While we do that objects in the slabs may be freed. We can
+ *   only operate on the slab if we have also taken the slab_lock. So we use
+ *   a slab_trylock() on the slab. If trylock was successful then no frees
+ *   can occur anymore and we can use the slab for allocations etc. If the
+ *   slab_trylock() does not succeed then frees are in progress in the slab and
+ *   we must stay away from it for a while since we may cause a bouncing
+ *   cacheline if we try to acquire the lock. So go onto the next slab.
+ *   If all pages are busy then we may allocate a new slab instead of reusing
+ *   a partial slab. A new slab has noone operating on it and thus there is
+ *   no danger of cacheline contention.
+ *
+ *   Interrupts are disabled during allocation and deallocation in order to
+ *   make the slab allocator safe to use in the context of an irq. In addition
+ *   interrupts are disabled to ensure that the processor does not change
+ *   while handling per_cpu slabs, due to kernel preemption.
+ *
+ * SLUB assigns one slab for allocation to each processor.
+ * Allocations only occur from these slabs called cpu slabs.
+ *
+ * Slabs with free elements are kept on a partial list.
+ * There is no list for full slabs. If an object in a full slab is
+ * freed then the slab will show up again on the partial lists.
+ * Otherwise there is no need to track full slabs unless we have to
+ * track full slabs for debugging purposes.
+ *
+ * Slabs are freed when they become empty. Teardown and setup is
+ * minimal so we rely on the page allocators per cpu caches for
+ * fast frees and allocs.
+ *
+ * Overloading of page flags that are otherwise used for LRU management.
+ *
+ * PageActive          The slab is used as a cpu cache. Allocations
+ *                     may be performed from the slab. The slab is not
+ *                     on any slab list and cannot be moved onto one.
+ *
+ * PageError           Slab requires special handling due to debug
+ *                     options set. This moves slab handling out of
+ *                     the fast path.
+ */
+
+/*
+ * Issues still to be resolved:
+ *
+ * - The per cpu array is updated for each new slab and and is a remote
+ *   cacheline for most nodes. This could become a bouncing cacheline given
+ *   enough frequent updates. There are 16 pointers in a cacheline.so at
+ *   max 16 cpus could compete. Likely okay.
+ *
+ * - Support PAGE_ALLOC_DEBUG. Should be easy to do.
+ *
+ * - Variable sizing of the per node arrays
+ */
+
+/* Enable to test recovery from slab corruption on boot */
+#undef SLUB_RESILIENCY_TEST
+
+#if PAGE_SHIFT <= 12
+
+/*
+ * Small page size. Make sure that we do not fragment memory
+ */
+#define DEFAULT_MAX_ORDER 1
+#define DEFAULT_MIN_OBJECTS 4
+
+#else
+
+/*
+ * Large page machines are customarily able to handle larger
+ * page orders.
+ */
+#define DEFAULT_MAX_ORDER 2
+#define DEFAULT_MIN_OBJECTS 8
+
+#endif
+
+/*
+ * Mininum number of partial slabs. These will be left on the partial
+ * lists even if they are empty. kmem_cache_shrink may reclaim them.
+ */
+#define MIN_PARTIAL 2
+
+/*
+ * Maximum number of desirable partial slabs.
+ * The existence of more partial slabs makes kmem_cache_shrink
+ * sort the partial list by the number of objects in the.
+ */
+#define MAX_PARTIAL 10
+
+#define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \
+                               SLAB_POISON | SLAB_STORE_USER)
+/*
+ * Set of flags that will prevent slab merging
+ */
+#define SLUB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
+               SLAB_TRACE | SLAB_DESTROY_BY_RCU)
+
+#define SLUB_MERGE_SAME (SLAB_DEBUG_FREE | SLAB_RECLAIM_ACCOUNT | \
+               SLAB_CACHE_DMA)
+
+#ifndef ARCH_KMALLOC_MINALIGN
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
+#endif
+
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+#endif
+
+/* Internal SLUB flags */
+#define __OBJECT_POISON 0x80000000     /* Poison object */
+
+static int kmem_size = sizeof(struct kmem_cache);
+
+#ifdef CONFIG_SMP
+static struct notifier_block slab_notifier;
+#endif
+
+static enum {
+       DOWN,           /* No slab functionality available */
+       PARTIAL,        /* kmem_cache_open() works but kmalloc does not */
+       UP,             /* Everything works */
+       SYSFS           /* Sysfs up */
+} slab_state = DOWN;
+
+/* A list of all slab caches on the system */
+static DECLARE_RWSEM(slub_lock);
+LIST_HEAD(slab_caches);
+
+#ifdef CONFIG_SYSFS
+static int sysfs_slab_add(struct kmem_cache *);
+static int sysfs_slab_alias(struct kmem_cache *, const char *);
+static void sysfs_slab_remove(struct kmem_cache *);
+#else
+static int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+static int sysfs_slab_alias(struct kmem_cache *s, const char *p) { return 0; }
+static void sysfs_slab_remove(struct kmem_cache *s) {}
+#endif
+
+/********************************************************************
+ *                     Core slab cache functions
+ *******************************************************************/
+
+int slab_is_available(void)
+{
+       return slab_state >= UP;
+}
+
+static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node)
+{
+#ifdef CONFIG_NUMA
+       return s->node[node];
+#else
+       return &s->local_node;
+#endif
+}
+
+/*
+ * Object debugging
+ */
+static void print_section(char *text, u8 *addr, unsigned int length)
+{
+       int i, offset;
+       int newline = 1;
+       char ascii[17];
+
+       ascii[16] = 0;
+
+       for (i = 0; i < length; i++) {
+               if (newline) {
+                       printk(KERN_ERR "%10s 0x%p: ", text, addr + i);
+                       newline = 0;
+               }
+               printk(" %02x", addr[i]);
+               offset = i % 16;
+               ascii[offset] = isgraph(addr[i]) ? addr[i] : '.';
+               if (offset == 15) {
+                       printk(" %s\n",ascii);
+                       newline = 1;
+               }
+       }
+       if (!newline) {
+               i %= 16;
+               while (i < 16) {
+                       printk("   ");
+                       ascii[i] = ' ';
+                       i++;
+               }
+               printk(" %s\n", ascii);
+       }
+}
+
+/*
+ * Slow version of get and set free pointer.
+ *
+ * This requires touching the cache lines of kmem_cache.
+ * The offset can also be obtained from the page. In that
+ * case it is in the cacheline that we already need to touch.
+ */
+static void *get_freepointer(struct kmem_cache *s, void *object)
+{
+       return *(void **)(object + s->offset);
+}
+
+static void set_freepointer(struct kmem_cache *s, void *object, void *fp)
+{
+       *(void **)(object + s->offset) = fp;
+}
+
+/*
+ * Tracking user of a slab.
+ */
+struct track {
+       void *addr;             /* Called from address */
+       int cpu;                /* Was running on cpu */
+       int pid;                /* Pid context */
+       unsigned long when;     /* When did the operation occur */
+};
+
+enum track_item { TRACK_ALLOC, TRACK_FREE };
+
+static struct track *get_track(struct kmem_cache *s, void *object,
+       enum track_item alloc)
+{
+       struct track *p;
+
+       if (s->offset)
+               p = object + s->offset + sizeof(void *);
+       else
+               p = object + s->inuse;
+
+       return p + alloc;
+}
+
+static void set_track(struct kmem_cache *s, void *object,
+                               enum track_item alloc, void *addr)
+{
+       struct track *p;
+
+       if (s->offset)
+               p = object + s->offset + sizeof(void *);
+       else
+               p = object + s->inuse;
+
+       p += alloc;
+       if (addr) {
+               p->addr = addr;
+               p->cpu = smp_processor_id();
+               p->pid = current ? current->pid : -1;
+               p->when = jiffies;
+       } else
+               memset(p, 0, sizeof(struct track));
+}
+
+static void init_tracking(struct kmem_cache *s, void *object)
+{
+       if (s->flags & SLAB_STORE_USER) {
+               set_track(s, object, TRACK_FREE, NULL);
+               set_track(s, object, TRACK_ALLOC, NULL);
+       }
+}
+
+static void print_track(const char *s, struct track *t)
+{
+       if (!t->addr)
+               return;
+
+       printk(KERN_ERR "%s: ", s);
+       __print_symbol("%s", (unsigned long)t->addr);
+       printk(" jiffies_ago=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+}
+
+static void print_trailer(struct kmem_cache *s, u8 *p)
+{
+       unsigned int off;       /* Offset of last byte */
+
+       if (s->flags & SLAB_RED_ZONE)
+               print_section("Redzone", p + s->objsize,
+                       s->inuse - s->objsize);
+
+       printk(KERN_ERR "FreePointer 0x%p -> 0x%p\n",
+                       p + s->offset,
+                       get_freepointer(s, p));
+
+       if (s->offset)
+               off = s->offset + sizeof(void *);
+       else
+               off = s->inuse;
+
+       if (s->flags & SLAB_STORE_USER) {
+               print_track("Last alloc", get_track(s, p, TRACK_ALLOC));
+               print_track("Last free ", get_track(s, p, TRACK_FREE));
+               off += 2 * sizeof(struct track);
+       }
+
+       if (off != s->size)
+               /* Beginning of the filler is the free pointer */
+               print_section("Filler", p + off, s->size - off);
+}
+
+static void object_err(struct kmem_cache *s, struct page *page,
+                       u8 *object, char *reason)
+{
+       u8 *addr = page_address(page);
+
+       printk(KERN_ERR "*** SLUB %s: %s@0x%p slab 0x%p\n",
+                       s->name, reason, object, page);
+       printk(KERN_ERR "    offset=%tu flags=0x%04lx inuse=%u freelist=0x%p\n",
+               object - addr, page->flags, page->inuse, page->freelist);
+       if (object > addr + 16)
+               print_section("Bytes b4", object - 16, 16);
+       print_section("Object", object, min(s->objsize, 128));
+       print_trailer(s, object);
+       dump_stack();
+}
+
+static void slab_err(struct kmem_cache *s, struct page *page, char *reason, ...)
+{
+       va_list args;
+       char buf[100];
+
+       va_start(args, reason);
+       vsnprintf(buf, sizeof(buf), reason, args);
+       va_end(args);
+       printk(KERN_ERR "*** SLUB %s: %s in slab @0x%p\n", s->name, buf,
+               page);
+       dump_stack();
+}
+
+static void init_object(struct kmem_cache *s, void *object, int active)
+{
+       u8 *p = object;
+
+       if (s->flags & __OBJECT_POISON) {
+               memset(p, POISON_FREE, s->objsize - 1);
+               p[s->objsize -1] = POISON_END;
+       }
+
+       if (s->flags & SLAB_RED_ZONE)
+               memset(p + s->objsize,
+                       active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE,
+                       s->inuse - s->objsize);
+}
+
+static int check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+{
+       while (bytes) {
+               if (*start != (u8)value)
+                       return 0;
+               start++;
+               bytes--;
+       }
+       return 1;
+}
+
+
+static int check_valid_pointer(struct kmem_cache *s, struct page *page,
+                                        void *object)
+{
+       void *base;
+
+       if (!object)
+               return 1;
+
+       base = page_address(page);
+       if (object < base || object >= base + s->objects * s->size ||
+               (object - base) % s->size) {
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * Object layout:
+ *
+ * object address
+ *     Bytes of the object to be managed.
+ *     If the freepointer may overlay the object then the free
+ *     pointer is the first word of the object.
+ *     Poisoning uses 0x6b (POISON_FREE) and the last byte is
+ *     0xa5 (POISON_END)
+ *
+ * object + s->objsize
+ *     Padding to reach word boundary. This is also used for Redzoning.
+ *     Padding is extended to word size if Redzoning is enabled
+ *     and objsize == inuse.
+ *     We fill with 0xbb (RED_INACTIVE) for inactive objects and with
+ *     0xcc (RED_ACTIVE) for objects in use.
+ *
+ * object + s->inuse
+ *     A. Free pointer (if we cannot overwrite object on free)
+ *     B. Tracking data for SLAB_STORE_USER
+ *     C. Padding to reach required alignment boundary
+ *             Padding is done using 0x5a (POISON_INUSE)
+ *
+ * object + s->size
+ *
+ * If slabcaches are merged then the objsize and inuse boundaries are to
+ * be ignored. And therefore no slab options that rely on these boundaries
+ * may be used with merged slabcaches.
+ */
+
+static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
+                                               void *from, void *to)
+{
+       printk(KERN_ERR "@@@ SLUB %s: Restoring %s (0x%x) from 0x%p-0x%p\n",
+               s->name, message, data, from, to - 1);
+       memset(from, data, to - from);
+}
+
+static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
+{
+       unsigned long off = s->inuse;   /* The end of info */
+
+       if (s->offset)
+               /* Freepointer is placed after the object. */
+               off += sizeof(void *);
+
+       if (s->flags & SLAB_STORE_USER)
+               /* We also have user information there */
+               off += 2 * sizeof(struct track);
+
+       if (s->size == off)
+               return 1;
+
+       if (check_bytes(p + off, POISON_INUSE, s->size - off))
+               return 1;
+
+       object_err(s, page, p, "Object padding check fails");
+
+       /*
+        * Restore padding
+        */
+       restore_bytes(s, "object padding", POISON_INUSE, p + off, p + s->size);
+       return 0;
+}
+
+static int slab_pad_check(struct kmem_cache *s, struct page *page)
+{
+       u8 *p;
+       int length, remainder;
+
+       if (!(s->flags & SLAB_POISON))
+               return 1;
+
+       p = page_address(page);
+       length = s->objects * s->size;
+       remainder = (PAGE_SIZE << s->order) - length;
+       if (!remainder)
+               return 1;
+
+       if (!check_bytes(p + length, POISON_INUSE, remainder)) {
+               slab_err(s, page, "Padding check failed");
+               restore_bytes(s, "slab padding", POISON_INUSE, p + length,
+                       p + length + remainder);
+               return 0;
+       }
+       return 1;
+}
+
+static int check_object(struct kmem_cache *s, struct page *page,
+                                       void *object, int active)
+{
+       u8 *p = object;
+       u8 *endobject = object + s->objsize;
+
+       if (s->flags & SLAB_RED_ZONE) {
+               unsigned int red =
+                       active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE;
+
+               if (!check_bytes(endobject, red, s->inuse - s->objsize)) {
+                       object_err(s, page, object,
+                       active ? "Redzone Active" : "Redzone Inactive");
+                       restore_bytes(s, "redzone", red,
+                               endobject, object + s->inuse);
+                       return 0;
+               }
+       } else {
+               if ((s->flags & SLAB_POISON) && s->objsize < s->inuse &&
+                       !check_bytes(endobject, POISON_INUSE,
+                                       s->inuse - s->objsize)) {
+               object_err(s, page, p, "Alignment padding check fails");
+               /*
+                * Fix it so that there will not be another report.
+                *
+                * Hmmm... We may be corrupting an object that now expects
+                * to be longer than allowed.
+                */
+               restore_bytes(s, "alignment padding", POISON_INUSE,
+                       endobject, object + s->inuse);
+               }
+       }
+
+       if (s->flags & SLAB_POISON) {
+               if (!active && (s->flags & __OBJECT_POISON) &&
+                       (!check_bytes(p, POISON_FREE, s->objsize - 1) ||
+                               p[s->objsize - 1] != POISON_END)) {
+
+                       object_err(s, page, p, "Poison check failed");
+                       restore_bytes(s, "Poison", POISON_FREE,
+                                               p, p + s->objsize -1);
+                       restore_bytes(s, "Poison", POISON_END,
+                                       p + s->objsize - 1, p + s->objsize);
+                       return 0;
+               }
+               /*
+                * check_pad_bytes cleans up on its own.
+                */
+               check_pad_bytes(s, page, p);
+       }
+
+       if (!s->offset && active)
+               /*
+                * Object and freepointer overlap. Cannot check
+                * freepointer while object is allocated.
+                */
+               return 1;
+
+       /* Check free pointer validity */
+       if (!check_valid_pointer(s, page, get_freepointer(s, p))) {
+               object_err(s, page, p, "Freepointer corrupt");
+               /*
+                * No choice but to zap it and thus loose the remainder
+                * of the free objects in this slab. May cause
+                * another error because the object count maybe
+                * wrong now.
+                */
+               set_freepointer(s, p, NULL);
+               return 0;
+       }
+       return 1;
+}
+
+static int check_slab(struct kmem_cache *s, struct page *page)
+{
+       VM_BUG_ON(!irqs_disabled());
+
+       if (!PageSlab(page)) {
+               slab_err(s, page, "Not a valid slab page flags=%lx "
+                       "mapping=0x%p count=%d", page->flags, page->mapping,
+                       page_count(page));
+               return 0;
+       }
+       if (page->offset * sizeof(void *) != s->offset) {
+               slab_err(s, page, "Corrupted offset %lu flags=0x%lx "
+                       "mapping=0x%p count=%d",
+                       (unsigned long)(page->offset * sizeof(void *)),
+                       page->flags,
+                       page->mapping,
+                       page_count(page));
+               return 0;
+       }
+       if (page->inuse > s->objects) {
+               slab_err(s, page, "inuse %u > max %u @0x%p flags=%lx "
+                       "mapping=0x%p count=%d",
+                       s->name, page->inuse, s->objects, page->flags,
+                       page->mapping, page_count(page));
+               return 0;
+       }
+       /* Slab_pad_check fixes things up after itself */
+       slab_pad_check(s, page);
+       return 1;
+}
+
+/*
+ * Determine if a certain object on a page is on the freelist and
+ * therefore free. Must hold the slab lock for cpu slabs to
+ * guarantee that the chains are consistent.
+ */
+static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
+{
+       int nr = 0;
+       void *fp = page->freelist;
+       void *object = NULL;
+
+       while (fp && nr <= s->objects) {
+               if (fp == search)
+                       return 1;
+               if (!check_valid_pointer(s, page, fp)) {
+                       if (object) {
+                               object_err(s, page, object,
+                                       "Freechain corrupt");
+                               set_freepointer(s, object, NULL);
+                               break;
+                       } else {
+                               slab_err(s, page, "Freepointer 0x%p corrupt",
+                                                                       fp);
+                               page->freelist = NULL;
+                               page->inuse = s->objects;
+                               printk(KERN_ERR "@@@ SLUB %s: Freelist "
+                                       "cleared. Slab 0x%p\n",
+                                       s->name, page);
+                               return 0;
+                       }
+                       break;
+               }
+               object = fp;
+               fp = get_freepointer(s, object);
+               nr++;
+       }
+
+       if (page->inuse != s->objects - nr) {
+               slab_err(s, page, "Wrong object count. Counter is %d but "
+                       "counted were %d", s, page, page->inuse,
+                                                       s->objects - nr);
+               page->inuse = s->objects - nr;
+               printk(KERN_ERR "@@@ SLUB %s: Object count adjusted. "
+                       "Slab @0x%p\n", s->name, page);
+       }
+       return search == NULL;
+}
+
+/*
+ * Tracking of fully allocated slabs for debugging
+ */
+static void add_full(struct kmem_cache_node *n, struct page *page)
+{
+       spin_lock(&n->list_lock);
+       list_add(&page->lru, &n->full);
+       spin_unlock(&n->list_lock);
+}
+
+static void remove_full(struct kmem_cache *s, struct page *page)
+{
+       struct kmem_cache_node *n;
+
+       if (!(s->flags & SLAB_STORE_USER))
+               return;
+
+       n = get_node(s, page_to_nid(page));
+
+       spin_lock(&n->list_lock);
+       list_del(&page->lru);
+       spin_unlock(&n->list_lock);
+}
+
+static int alloc_object_checks(struct kmem_cache *s, struct page *page,
+                                                       void *object)
+{
+       if (!check_slab(s, page))
+               goto bad;
+
+       if (object && !on_freelist(s, page, object)) {
+               slab_err(s, page, "Object 0x%p already allocated", object);
+               goto bad;
+       }
+
+       if (!check_valid_pointer(s, page, object)) {
+               object_err(s, page, object, "Freelist Pointer check fails");
+               goto bad;
+       }
+
+       if (!object)
+               return 1;
+
+       if (!check_object(s, page, object, 0))
+               goto bad;
+
+       return 1;
+bad:
+       if (PageSlab(page)) {
+               /*
+                * If this is a slab page then lets do the best we can
+                * to avoid issues in the future. Marking all objects
+                * as used avoids touching the remainder.
+                */
+               printk(KERN_ERR "@@@ SLUB: %s slab 0x%p. Marking all objects used.\n",
+                       s->name, page);
+               page->inuse = s->objects;
+               page->freelist = NULL;
+               /* Fix up fields that may be corrupted */
+               page->offset = s->offset / sizeof(void *);
+       }
+       return 0;
+}
+
+static int free_object_checks(struct kmem_cache *s, struct page *page,
+                                                       void *object)
+{
+       if (!check_slab(s, page))
+               goto fail;
+
+       if (!check_valid_pointer(s, page, object)) {
+               slab_err(s, page, "Invalid object pointer 0x%p", object);
+               goto fail;
+       }
+
+       if (on_freelist(s, page, object)) {
+               slab_err(s, page, "Object 0x%p already free", object);
+               goto fail;
+       }
+
+       if (!check_object(s, page, object, 1))
+               return 0;
+
+       if (unlikely(s != page->slab)) {
+               if (!PageSlab(page))
+                       slab_err(s, page, "Attempt to free object(0x%p) "
+                               "outside of slab", object);
+               else
+               if (!page->slab) {
+                       printk(KERN_ERR
+                               "SLUB <none>: no slab for object 0x%p.\n",
+                                               object);
+                       dump_stack();
+               }
+               else
+                       slab_err(s, page, "object at 0x%p belongs "
+                               "to slab %s", object, page->slab->name);
+               goto fail;
+       }
+       return 1;
+fail:
+       printk(KERN_ERR "@@@ SLUB: %s slab 0x%p object at 0x%p not freed.\n",
+               s->name, page, object);
+       return 0;
+}
+
+/*
+ * Slab allocation and freeing
+ */
+static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
+{
+       struct page * page;
+       int pages = 1 << s->order;
+
+       if (s->order)
+               flags |= __GFP_COMP;
+
+       if (s->flags & SLAB_CACHE_DMA)
+               flags |= SLUB_DMA;
+
+       if (node == -1)
+               page = alloc_pages(flags, s->order);
+       else
+               page = alloc_pages_node(node, flags, s->order);
+
+       if (!page)
+               return NULL;
+
+       mod_zone_page_state(page_zone(page),
+               (s->flags & SLAB_RECLAIM_ACCOUNT) ?
+               NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+               pages);
+
+       return page;
+}
+
+static void setup_object(struct kmem_cache *s, struct page *page,
+                               void *object)
+{
+       if (PageError(page)) {
+               init_object(s, object, 0);
+               init_tracking(s, object);
+       }
+
+       if (unlikely(s->ctor))
+               s->ctor(object, s, SLAB_CTOR_CONSTRUCTOR);
+}
+
+static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+{
+       struct page *page;
+       struct kmem_cache_node *n;
+       void *start;
+       void *end;
+       void *last;
+       void *p;
+
+       BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+
+       if (flags & __GFP_WAIT)
+               local_irq_enable();
+
+       page = allocate_slab(s, flags & GFP_LEVEL_MASK, node);
+       if (!page)
+               goto out;
+
+       n = get_node(s, page_to_nid(page));
+       if (n)
+               atomic_long_inc(&n->nr_slabs);
+       page->offset = s->offset / sizeof(void *);
+       page->slab = s;
+       page->flags |= 1 << PG_slab;
+       if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
+                       SLAB_STORE_USER | SLAB_TRACE))
+               page->flags |= 1 << PG_error;
+
+       start = page_address(page);
+       end = start + s->objects * s->size;
+
+       if (unlikely(s->flags & SLAB_POISON))
+               memset(start, POISON_INUSE, PAGE_SIZE << s->order);
+
+       last = start;
+       for (p = start + s->size; p < end; p += s->size) {
+               setup_object(s, page, last);
+               set_freepointer(s, last, p);
+               last = p;
+       }
+       setup_object(s, page, last);
+       set_freepointer(s, last, NULL);
+
+       page->freelist = start;
+       page->inuse = 0;
+out:
+       if (flags & __GFP_WAIT)
+               local_irq_disable();
+       return page;
+}
+
+static void __free_slab(struct kmem_cache *s, struct page *page)
+{
+       int pages = 1 << s->order;
+
+       if (unlikely(PageError(page) || s->dtor)) {
+               void *start = page_address(page);
+               void *end = start + (pages << PAGE_SHIFT);
+               void *p;
+
+               slab_pad_check(s, page);
+               for (p = start; p <= end - s->size; p += s->size) {
+                       if (s->dtor)
+                               s->dtor(p, s, 0);
+                       check_object(s, page, p, 0);
+               }
+       }
+
+       mod_zone_page_state(page_zone(page),
+               (s->flags & SLAB_RECLAIM_ACCOUNT) ?
+               NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+               - pages);
+
+       page->mapping = NULL;
+       __free_pages(page, s->order);
+}
+
+static void rcu_free_slab(struct rcu_head *h)
+{
+       struct page *page;
+
+       page = container_of((struct list_head *)h, struct page, lru);
+       __free_slab(page->slab, page);
+}
+
+static void free_slab(struct kmem_cache *s, struct page *page)
+{
+       if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) {
+               /*
+                * RCU free overloads the RCU head over the LRU
+                */
+               struct rcu_head *head = (void *)&page->lru;
+
+               call_rcu(head, rcu_free_slab);
+       } else
+               __free_slab(s, page);
+}
+
+static void discard_slab(struct kmem_cache *s, struct page *page)
+{
+       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+
+       atomic_long_dec(&n->nr_slabs);
+       reset_page_mapcount(page);
+       page->flags &= ~(1 << PG_slab | 1 << PG_error);
+       free_slab(s, page);
+}
+
+/*
+ * Per slab locking using the pagelock
+ */
+static __always_inline void slab_lock(struct page *page)
+{
+       bit_spin_lock(PG_locked, &page->flags);
+}
+
+static __always_inline void slab_unlock(struct page *page)
+{
+       bit_spin_unlock(PG_locked, &page->flags);
+}
+
+static __always_inline int slab_trylock(struct page *page)
+{
+       int rc = 1;
+
+       rc = bit_spin_trylock(PG_locked, &page->flags);
+       return rc;
+}
+
+/*
+ * Management of partially allocated slabs
+ */
+static void add_partial_tail(struct kmem_cache_node *n, struct page *page)
+{
+       spin_lock(&n->list_lock);
+       n->nr_partial++;
+       list_add_tail(&page->lru, &n->partial);
+       spin_unlock(&n->list_lock);
+}
+
+static void add_partial(struct kmem_cache_node *n, struct page *page)
+{
+       spin_lock(&n->list_lock);
+       n->nr_partial++;
+       list_add(&page->lru, &n->partial);
+       spin_unlock(&n->list_lock);
+}
+
+static void remove_partial(struct kmem_cache *s,
+                                               struct page *page)
+{
+       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+
+       spin_lock(&n->list_lock);
+       list_del(&page->lru);
+       n->nr_partial--;
+       spin_unlock(&n->list_lock);
+}
+
+/*
+ * Lock page and remove it from the partial list
+ *
+ * Must hold list_lock
+ */
+static int lock_and_del_slab(struct kmem_cache_node *n, struct page *page)
+{
+       if (slab_trylock(page)) {
+               list_del(&page->lru);
+               n->nr_partial--;
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Try to get a partial slab from a specific node
+ */
+static struct page *get_partial_node(struct kmem_cache_node *n)
+{
+       struct page *page;
+
+       /*
+        * Racy check. If we mistakenly see no partial slabs then we
+        * just allocate an empty slab. If we mistakenly try to get a
+        * partial slab then get_partials() will return NULL.
+        */
+       if (!n || !n->nr_partial)
+               return NULL;
+
+       spin_lock(&n->list_lock);
+       list_for_each_entry(page, &n->partial, lru)
+               if (lock_and_del_slab(n, page))
+                       goto out;
+       page = NULL;
+out:
+       spin_unlock(&n->list_lock);
+       return page;
+}
+
+/*
+ * Get a page from somewhere. Search in increasing NUMA
+ * distances.
+ */
+static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
+{
+#ifdef CONFIG_NUMA
+       struct zonelist *zonelist;
+       struct zone **z;
+       struct page *page;
+
+       /*
+        * The defrag ratio allows to configure the tradeoffs between
+        * inter node defragmentation and node local allocations.
+        * A lower defrag_ratio increases the tendency to do local
+        * allocations instead of scanning throught the partial
+        * lists on other nodes.
+        *
+        * If defrag_ratio is set to 0 then kmalloc() always
+        * returns node local objects. If its higher then kmalloc()
+        * may return off node objects in order to avoid fragmentation.
+        *
+        * A higher ratio means slabs may be taken from other nodes
+        * thus reducing the number of partial slabs on those nodes.
+        *
+        * If /sys/slab/xx/defrag_ratio is set to 100 (which makes
+        * defrag_ratio = 1000) then every (well almost) allocation
+        * will first attempt to defrag slab caches on other nodes. This
+        * means scanning over all nodes to look for partial slabs which
+        * may be a bit expensive to do on every slab allocation.
+        */
+       if (!s->defrag_ratio || get_cycles() % 1024 > s->defrag_ratio)
+               return NULL;
+
+       zonelist = &NODE_DATA(slab_node(current->mempolicy))
+                                       ->node_zonelists[gfp_zone(flags)];
+       for (z = zonelist->zones; *z; z++) {
+               struct kmem_cache_node *n;
+
+               n = get_node(s, zone_to_nid(*z));
+
+               if (n && cpuset_zone_allowed_hardwall(*z, flags) &&
+                               n->nr_partial > MIN_PARTIAL) {
+                       page = get_partial_node(n);
+                       if (page)
+                               return page;
+               }
+       }
+#endif
+       return NULL;
+}
+
+/*
+ * Get a partial page, lock it and return it.
+ */
+static struct page *get_partial(struct kmem_cache *s, gfp_t flags, int node)
+{
+       struct page *page;
+       int searchnode = (node == -1) ? numa_node_id() : node;
+
+       page = get_partial_node(get_node(s, searchnode));
+       if (page || (flags & __GFP_THISNODE))
+               return page;
+
+       return get_any_partial(s, flags);
+}
+
+/*
+ * Move a page back to the lists.
+ *
+ * Must be called with the slab lock held.
+ *
+ * On exit the slab lock will have been dropped.
+ */
+static void putback_slab(struct kmem_cache *s, struct page *page)
+{
+       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+
+       if (page->inuse) {
+
+               if (page->freelist)
+                       add_partial(n, page);
+               else if (PageError(page) && (s->flags & SLAB_STORE_USER))
+                       add_full(n, page);
+               slab_unlock(page);
+
+       } else {
+               if (n->nr_partial < MIN_PARTIAL) {
+                       /*
+                        * Adding an empty page to the partial slabs in order
+                        * to avoid page allocator overhead. This page needs to
+                        * come after all the others that are not fully empty
+                        * in order to make sure that we do maximum
+                        * defragmentation.
+                        */
+                       add_partial_tail(n, page);
+                       slab_unlock(page);
+               } else {
+                       slab_unlock(page);
+                       discard_slab(s, page);
+               }
+       }
+}
+
+/*
+ * Remove the cpu slab
+ */
+static void deactivate_slab(struct kmem_cache *s, struct page *page, int cpu)
+{
+       s->cpu_slab[cpu] = NULL;
+       ClearPageActive(page);
+
+       putback_slab(s, page);
+}
+
+static void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
+{
+       slab_lock(page);
+       deactivate_slab(s, page, cpu);
+}
+
+/*
+ * Flush cpu slab.
+ * Called from IPI handler with interrupts disabled.
+ */
+static void __flush_cpu_slab(struct kmem_cache *s, int cpu)
+{
+       struct page *page = s->cpu_slab[cpu];
+
+       if (likely(page))
+               flush_slab(s, page, cpu);
+}
+
+static void flush_cpu_slab(void *d)
+{
+       struct kmem_cache *s = d;
+       int cpu = smp_processor_id();
+
+       __flush_cpu_slab(s, cpu);
+}
+
+static void flush_all(struct kmem_cache *s)
+{
+#ifdef CONFIG_SMP
+       on_each_cpu(flush_cpu_slab, s, 1, 1);
+#else
+       unsigned long flags;
+
+       local_irq_save(flags);
+       flush_cpu_slab(s);
+       local_irq_restore(flags);
+#endif
+}
+
+/*
+ * slab_alloc is optimized to only modify two cachelines on the fast path
+ * (aside from the stack):
+ *
+ * 1. The page struct
+ * 2. The first cacheline of the object to be allocated.
+ *
+ * The only cache lines that are read (apart from code) is the
+ * per cpu array in the kmem_cache struct.
+ *
+ * Fastpath is not possible if we need to get a new slab or have
+ * debugging enabled (which means all slabs are marked with PageError)
+ */
+static void *slab_alloc(struct kmem_cache *s,
+                               gfp_t gfpflags, int node, void *addr)
+{
+       struct page *page;
+       void **object;
+       unsigned long flags;
+       int cpu;
+
+       local_irq_save(flags);
+       cpu = smp_processor_id();
+       page = s->cpu_slab[cpu];
+       if (!page)
+               goto new_slab;
+
+       slab_lock(page);
+       if (unlikely(node != -1 && page_to_nid(page) != node))
+               goto another_slab;
+redo:
+       object = page->freelist;
+       if (unlikely(!object))
+               goto another_slab;
+       if (unlikely(PageError(page)))
+               goto debug;
+
+have_object:
+       page->inuse++;
+       page->freelist = object[page->offset];
+       slab_unlock(page);
+       local_irq_restore(flags);
+       return object;
+
+another_slab:
+       deactivate_slab(s, page, cpu);
+
+new_slab:
+       page = get_partial(s, gfpflags, node);
+       if (likely(page)) {
+have_slab:
+               s->cpu_slab[cpu] = page;
+               SetPageActive(page);
+               goto redo;
+       }
+
+       page = new_slab(s, gfpflags, node);
+       if (page) {
+               cpu = smp_processor_id();
+               if (s->cpu_slab[cpu]) {
+                       /*
+                        * Someone else populated the cpu_slab while we enabled
+                        * interrupts, or we have got scheduled on another cpu.
+                        * The page may not be on the requested node.
+                        */
+                       if (node == -1 ||
+                               page_to_nid(s->cpu_slab[cpu]) == node) {
+                               /*
+                                * Current cpuslab is acceptable and we
+                                * want the current one since its cache hot
+                                */
+                               discard_slab(s, page);
+                               page = s->cpu_slab[cpu];
+                               slab_lock(page);
+                               goto redo;
+                       }
+                       /* Dump the current slab */
+                       flush_slab(s, s->cpu_slab[cpu], cpu);
+               }
+               slab_lock(page);
+               goto have_slab;
+       }
+       local_irq_restore(flags);
+       return NULL;
+debug:
+       if (!alloc_object_checks(s, page, object))
+               goto another_slab;
+       if (s->flags & SLAB_STORE_USER)
+               set_track(s, object, TRACK_ALLOC, addr);
+       if (s->flags & SLAB_TRACE) {
+               printk(KERN_INFO "TRACE %s alloc 0x%p inuse=%d fp=0x%p\n",
+                       s->name, object, page->inuse,
+                       page->freelist);
+               dump_stack();
+       }
+       init_object(s, object, 1);
+       goto have_object;
+}
+
+void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
+{
+       return slab_alloc(s, gfpflags, -1, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(kmem_cache_alloc);
+
+#ifdef CONFIG_NUMA
+void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
+{
+       return slab_alloc(s, gfpflags, node, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(kmem_cache_alloc_node);
+#endif
+
+/*
+ * The fastpath only writes the cacheline of the page struct and the first
+ * cacheline of the object.
+ *
+ * No special cachelines need to be read
+ */
+static void slab_free(struct kmem_cache *s, struct page *page,
+                                       void *x, void *addr)
+{
+       void *prior;
+       void **object = (void *)x;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       slab_lock(page);
+
+       if (unlikely(PageError(page)))
+               goto debug;
+checks_ok:
+       prior = object[page->offset] = page->freelist;
+       page->freelist = object;
+       page->inuse--;
+
+       if (unlikely(PageActive(page)))
+               /*
+                * Cpu slabs are never on partial lists and are
+                * never freed.
+                */
+               goto out_unlock;
+
+       if (unlikely(!page->inuse))
+               goto slab_empty;
+
+       /*
+        * Objects left in the slab. If it
+        * was not on the partial list before
+        * then add it.
+        */
+       if (unlikely(!prior))
+               add_partial(get_node(s, page_to_nid(page)), page);
+
+out_unlock:
+       slab_unlock(page);
+       local_irq_restore(flags);
+       return;
+
+slab_empty:
+       if (prior)
+               /*
+                * Slab on the partial list.
+                */
+               remove_partial(s, page);
+
+       slab_unlock(page);
+       discard_slab(s, page);
+       local_irq_restore(flags);
+       return;
+
+debug:
+       if (!free_object_checks(s, page, x))
+               goto out_unlock;
+       if (!PageActive(page) && !page->freelist)
+               remove_full(s, page);
+       if (s->flags & SLAB_STORE_USER)
+               set_track(s, x, TRACK_FREE, addr);
+       if (s->flags & SLAB_TRACE) {
+               printk(KERN_INFO "TRACE %s free 0x%p inuse=%d fp=0x%p\n",
+                       s->name, object, page->inuse,
+                       page->freelist);
+               print_section("Object", (void *)object, s->objsize);
+               dump_stack();
+       }
+       init_object(s, object, 0);
+       goto checks_ok;
+}
+
+void kmem_cache_free(struct kmem_cache *s, void *x)
+{
+       struct page *page;
+
+       page = virt_to_head_page(x);
+
+       slab_free(s, page, x, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(kmem_cache_free);
+
+/* Figure out on which slab object the object resides */
+static struct page *get_object_page(const void *x)
+{
+       struct page *page = virt_to_head_page(x);
+
+       if (!PageSlab(page))
+               return NULL;
+
+       return page;
+}
+
+/*
+ * kmem_cache_open produces objects aligned at "size" and the first object
+ * is placed at offset 0 in the slab (We have no metainformation on the
+ * slab, all slabs are in essence "off slab").
+ *
+ * In order to get the desired alignment one just needs to align the
+ * size.
+ *
+ * Notice that the allocation order determines the sizes of the per cpu
+ * caches. Each processor has always one slab available for allocations.
+ * Increasing the allocation order reduces the number of times that slabs
+ * must be moved on and off the partial lists and therefore may influence
+ * locking overhead.
+ *
+ * The offset is used to relocate the free list link in each object. It is
+ * therefore possible to move the free list link behind the object. This
+ * is necessary for RCU to work properly and also useful for debugging.
+ */
+
+/*
+ * Mininum / Maximum order of slab pages. This influences locking overhead
+ * and slab fragmentation. A higher order reduces the number of partial slabs
+ * and increases the number of allocations possible without having to
+ * take the list_lock.
+ */
+static int slub_min_order;
+static int slub_max_order = DEFAULT_MAX_ORDER;
+
+/*
+ * Minimum number of objects per slab. This is necessary in order to
+ * reduce locking overhead. Similar to the queue size in SLAB.
+ */
+static int slub_min_objects = DEFAULT_MIN_OBJECTS;
+
+/*
+ * Merge control. If this is set then no merging of slab caches will occur.
+ */
+static int slub_nomerge;
+
+/*
+ * Debug settings:
+ */
+static int slub_debug;
+
+static char *slub_debug_slabs;
+
+/*
+ * Calculate the order of allocation given an slab object size.
+ *
+ * The order of allocation has significant impact on other elements
+ * of the system. Generally order 0 allocations should be preferred
+ * since they do not cause fragmentation in the page allocator. Larger
+ * objects may have problems with order 0 because there may be too much
+ * space left unused in a slab. We go to a higher order if more than 1/8th
+ * of the slab would be wasted.
+ *
+ * In order to reach satisfactory performance we must ensure that
+ * a minimum number of objects is in one slab. Otherwise we may
+ * generate too much activity on the partial lists. This is less a
+ * concern for large slabs though. slub_max_order specifies the order
+ * where we begin to stop considering the number of objects in a slab.
+ *
+ * Higher order allocations also allow the placement of more objects
+ * in a slab and thereby reduce object handling overhead. If the user
+ * has requested a higher mininum order then we start with that one
+ * instead of zero.
+ */
+static int calculate_order(int size)
+{
+       int order;
+       int rem;
+
+       for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT);
+                       order < MAX_ORDER; order++) {
+               unsigned long slab_size = PAGE_SIZE << order;
+
+               if (slub_max_order > order &&
+                               slab_size < slub_min_objects * size)
+                       continue;
+
+               if (slab_size < size)
+                       continue;
+
+               rem = slab_size % size;
+
+               if (rem <= (PAGE_SIZE << order) / 8)
+                       break;
+
+       }
+       if (order >= MAX_ORDER)
+               return -E2BIG;
+       return order;
+}
+
+/*
+ * Function to figure out which alignment to use from the
+ * various ways of specifying it.
+ */
+static unsigned long calculate_alignment(unsigned long flags,
+               unsigned long align, unsigned long size)
+{
+       /*
+        * If the user wants hardware cache aligned objects then
+        * follow that suggestion if the object is sufficiently
+        * large.
+        *
+        * The hardware cache alignment cannot override the
+        * specified alignment though. If that is greater
+        * then use it.
+        */
+       if ((flags & SLAB_HWCACHE_ALIGN) &&
+                       size > L1_CACHE_BYTES / 2)
+               return max_t(unsigned long, align, L1_CACHE_BYTES);
+
+       if (align < ARCH_SLAB_MINALIGN)
+               return ARCH_SLAB_MINALIGN;
+
+       return ALIGN(align, sizeof(void *));
+}
+
+static void init_kmem_cache_node(struct kmem_cache_node *n)
+{
+       n->nr_partial = 0;
+       atomic_long_set(&n->nr_slabs, 0);
+       spin_lock_init(&n->list_lock);
+       INIT_LIST_HEAD(&n->partial);
+       INIT_LIST_HEAD(&n->full);
+}
+
+#ifdef CONFIG_NUMA
+/*
+ * No kmalloc_node yet so do it by hand. We know that this is the first
+ * slab on the node for this slabcache. There are no concurrent accesses
+ * possible.
+ *
+ * Note that this function only works on the kmalloc_node_cache
+ * when allocating for the kmalloc_node_cache.
+ */
+static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflags,
+                                                               int node)
+{
+       struct page *page;
+       struct kmem_cache_node *n;
+
+       BUG_ON(kmalloc_caches->size < sizeof(struct kmem_cache_node));
+
+       page = new_slab(kmalloc_caches, gfpflags | GFP_THISNODE, node);
+       /* new_slab() disables interupts */
+       local_irq_enable();
+
+       BUG_ON(!page);
+       n = page->freelist;
+       BUG_ON(!n);
+       page->freelist = get_freepointer(kmalloc_caches, n);
+       page->inuse++;
+       kmalloc_caches->node[node] = n;
+       init_object(kmalloc_caches, n, 1);
+       init_kmem_cache_node(n);
+       atomic_long_inc(&n->nr_slabs);
+       add_partial(n, page);
+       return n;
+}
+
+static void free_kmem_cache_nodes(struct kmem_cache *s)
+{
+       int node;
+
+       for_each_online_node(node) {
+               struct kmem_cache_node *n = s->node[node];
+               if (n && n != &s->local_node)
+                       kmem_cache_free(kmalloc_caches, n);
+               s->node[node] = NULL;
+       }
+}
+
+static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
+{
+       int node;
+       int local_node;
+
+       if (slab_state >= UP)
+               local_node = page_to_nid(virt_to_page(s));
+       else
+               local_node = 0;
+
+       for_each_online_node(node) {
+               struct kmem_cache_node *n;
+
+               if (local_node == node)
+                       n = &s->local_node;
+               else {
+                       if (slab_state == DOWN) {
+                               n = early_kmem_cache_node_alloc(gfpflags,
+                                                               node);
+                               continue;
+                       }
+                       n = kmem_cache_alloc_node(kmalloc_caches,
+                                                       gfpflags, node);
+
+                       if (!n) {
+                               free_kmem_cache_nodes(s);
+                               return 0;
+                       }
+
+               }
+               s->node[node] = n;
+               init_kmem_cache_node(n);
+       }
+       return 1;
+}
+#else
+static void free_kmem_cache_nodes(struct kmem_cache *s)
+{
+}
+
+static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
+{
+       init_kmem_cache_node(&s->local_node);
+       return 1;
+}
+#endif
+
+/*
+ * calculate_sizes() determines the order and the distribution of data within
+ * a slab object.
+ */
+static int calculate_sizes(struct kmem_cache *s)
+{
+       unsigned long flags = s->flags;
+       unsigned long size = s->objsize;
+       unsigned long align = s->align;
+
+       /*
+        * Determine if we can poison the object itself. If the user of
+        * the slab may touch the object after free or before allocation
+        * then we should never poison the object itself.
+        */
+       if ((flags & SLAB_POISON) && !(flags & SLAB_DESTROY_BY_RCU) &&
+                       !s->ctor && !s->dtor)
+               s->flags |= __OBJECT_POISON;
+       else
+               s->flags &= ~__OBJECT_POISON;
+
+       /*
+        * Round up object size to the next word boundary. We can only
+        * place the free pointer at word boundaries and this determines
+        * the possible location of the free pointer.
+        */
+       size = ALIGN(size, sizeof(void *));
+
+       /*
+        * If we are redzoning then check if there is some space between the
+        * end of the object and the free pointer. If not then add an
+        * additional word, so that we can establish a redzone between
+        * the object and the freepointer to be able to check for overwrites.
+        */
+       if ((flags & SLAB_RED_ZONE) && size == s->objsize)
+               size += sizeof(void *);
+
+       /*
+        * With that we have determined how much of the slab is in actual
+        * use by the object. This is the potential offset to the free
+        * pointer.
+        */
+       s->inuse = size;
+
+       if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
+               s->ctor || s->dtor)) {
+               /*
+                * Relocate free pointer after the object if it is not
+                * permitted to overwrite the first word of the object on
+                * kmem_cache_free.
+                *
+                * This is the case if we do RCU, have a constructor or
+                * destructor or are poisoning the objects.
+                */
+               s->offset = size;
+               size += sizeof(void *);
+       }
+
+       if (flags & SLAB_STORE_USER)
+               /*
+                * Need to store information about allocs and frees after
+                * the object.
+                */
+               size += 2 * sizeof(struct track);
+
+       if (flags & DEBUG_DEFAULT_FLAGS)
+               /*
+                * Add some empty padding so that we can catch
+                * overwrites from earlier objects rather than let
+                * tracking information or the free pointer be
+                * corrupted if an user writes before the start
+                * of the object.
+                */
+               size += sizeof(void *);
+       /*
+        * Determine the alignment based on various parameters that the
+        * user specified (this is unecessarily complex due to the attempt
+        * to be compatible with SLAB. Should be cleaned up some day).
+        */
+       align = calculate_alignment(flags, align, s->objsize);
+
+       /*
+        * SLUB stores one object immediately after another beginning from
+        * offset 0. In order to align the objects we have to simply size
+        * each object to conform to the alignment.
+        */
+       size = ALIGN(size, align);
+       s->size = size;
+
+       s->order = calculate_order(size);
+       if (s->order < 0)
+               return 0;
+
+       /*
+        * Determine the number of objects per slab
+        */
+       s->objects = (PAGE_SIZE << s->order) / size;
+
+       /*
+        * Verify that the number of objects is within permitted limits.
+        * The page->inuse field is only 16 bit wide! So we cannot have
+        * more than 64k objects per slab.
+        */
+       if (!s->objects || s->objects > 65535)
+               return 0;
+       return 1;
+
+}
+
+static int __init finish_bootstrap(void)
+{
+       struct list_head *h;
+       int err;
+
+       slab_state = SYSFS;
+
+       list_for_each(h, &slab_caches) {
+               struct kmem_cache *s =
+                       container_of(h, struct kmem_cache, list);
+
+               err = sysfs_slab_add(s);
+               BUG_ON(err);
+       }
+       return 0;
+}
+
+static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
+               const char *name, size_t size,
+               size_t align, unsigned long flags,
+               void (*ctor)(void *, struct kmem_cache *, unsigned long),
+               void (*dtor)(void *, struct kmem_cache *, unsigned long))
+{
+       memset(s, 0, kmem_size);
+       s->name = name;
+       s->ctor = ctor;
+       s->dtor = dtor;
+       s->objsize = size;
+       s->flags = flags;
+       s->align = align;
+
+       /*
+        * The page->offset field is only 16 bit wide. This is an offset
+        * in units of words from the beginning of an object. If the slab
+        * size is bigger then we cannot move the free pointer behind the
+        * object anymore.
+        *
+        * On 32 bit platforms the limit is 256k. On 64bit platforms
+        * the limit is 512k.
+        *
+        * Debugging or ctor/dtors may create a need to move the free
+        * pointer. Fail if this happens.
+        */
+       if (s->size >= 65535 * sizeof(void *)) {
+               BUG_ON(flags & (SLAB_RED_ZONE | SLAB_POISON |
+                               SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
+               BUG_ON(ctor || dtor);
+       }
+       else
+               /*
+                * Enable debugging if selected on the kernel commandline.
+                */
+               if (slub_debug && (!slub_debug_slabs ||
+                   strncmp(slub_debug_slabs, name,
+                       strlen(slub_debug_slabs)) == 0))
+                               s->flags |= slub_debug;
+
+       if (!calculate_sizes(s))
+               goto error;
+
+       s->refcount = 1;
+#ifdef CONFIG_NUMA
+       s->defrag_ratio = 100;
+#endif
+
+       if (init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))
+               return 1;
+error:
+       if (flags & SLAB_PANIC)
+               panic("Cannot create slab %s size=%lu realsize=%u "
+                       "order=%u offset=%u flags=%lx\n",
+                       s->name, (unsigned long)size, s->size, s->order,
+                       s->offset, flags);
+       return 0;
+}
+EXPORT_SYMBOL(kmem_cache_open);
+
+/*
+ * Check if a given pointer is valid
+ */
+int kmem_ptr_validate(struct kmem_cache *s, const void *object)
+{
+       struct page * page;
+       void *addr;
+
+       page = get_object_page(object);
+
+       if (!page || s != page->slab)
+               /* No slab or wrong slab */
+               return 0;
+
+       addr = page_address(page);
+       if (object < addr || object >= addr + s->objects * s->size)
+               /* Out of bounds */
+               return 0;
+
+       if ((object - addr) % s->size)
+               /* Improperly aligned */
+               return 0;
+
+       /*
+        * We could also check if the object is on the slabs freelist.
+        * But this would be too expensive and it seems that the main
+        * purpose of kmem_ptr_valid is to check if the object belongs
+        * to a certain slab.
+        */
+       return 1;
+}
+EXPORT_SYMBOL(kmem_ptr_validate);
+
+/*
+ * Determine the size of a slab object
+ */
+unsigned int kmem_cache_size(struct kmem_cache *s)
+{
+       return s->objsize;
+}
+EXPORT_SYMBOL(kmem_cache_size);
+
+const char *kmem_cache_name(struct kmem_cache *s)
+{
+       return s->name;
+}
+EXPORT_SYMBOL(kmem_cache_name);
+
+/*
+ * Attempt to free all slabs on a node
+ */
+static int free_list(struct kmem_cache *s, struct kmem_cache_node *n,
+                       struct list_head *list)
+{
+       int slabs_inuse = 0;
+       unsigned long flags;
+       struct page *page, *h;
+
+       spin_lock_irqsave(&n->list_lock, flags);
+       list_for_each_entry_safe(page, h, list, lru)
+               if (!page->inuse) {
+                       list_del(&page->lru);
+                       discard_slab(s, page);
+               } else
+                       slabs_inuse++;
+       spin_unlock_irqrestore(&n->list_lock, flags);
+       return slabs_inuse;
+}
+
+/*
+ * Release all resources used by slab cache
+ */
+static int kmem_cache_close(struct kmem_cache *s)
+{
+       int node;
+
+       flush_all(s);
+
+       /* Attempt to free all objects */
+       for_each_online_node(node) {
+               struct kmem_cache_node *n = get_node(s, node);
+
+               n->nr_partial -= free_list(s, n, &n->partial);
+               if (atomic_long_read(&n->nr_slabs))
+                       return 1;
+       }
+       free_kmem_cache_nodes(s);
+       return 0;
+}
+
+/*
+ * Close a cache and release the kmem_cache structure
+ * (must be used for caches created using kmem_cache_create)
+ */
+void kmem_cache_destroy(struct kmem_cache *s)
+{
+       down_write(&slub_lock);
+       s->refcount--;
+       if (!s->refcount) {
+               list_del(&s->list);
+               if (kmem_cache_close(s))
+                       WARN_ON(1);
+               sysfs_slab_remove(s);
+               kfree(s);
+       }
+       up_write(&slub_lock);
+}
+EXPORT_SYMBOL(kmem_cache_destroy);
+
+/********************************************************************
+ *             Kmalloc subsystem
+ *******************************************************************/
+
+struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] __cacheline_aligned;
+EXPORT_SYMBOL(kmalloc_caches);
+
+#ifdef CONFIG_ZONE_DMA
+static struct kmem_cache *kmalloc_caches_dma[KMALLOC_SHIFT_HIGH + 1];
+#endif
+
+static int __init setup_slub_min_order(char *str)
+{
+       get_option (&str, &slub_min_order);
+
+       return 1;
+}
+
+__setup("slub_min_order=", setup_slub_min_order);
+
+static int __init setup_slub_max_order(char *str)
+{
+       get_option (&str, &slub_max_order);
+
+       return 1;
+}
+
+__setup("slub_max_order=", setup_slub_max_order);
+
+static int __init setup_slub_min_objects(char *str)
+{
+       get_option (&str, &slub_min_objects);
+
+       return 1;
+}
+
+__setup("slub_min_objects=", setup_slub_min_objects);
+
+static int __init setup_slub_nomerge(char *str)
+{
+       slub_nomerge = 1;
+       return 1;
+}
+
+__setup("slub_nomerge", setup_slub_nomerge);
+
+static int __init setup_slub_debug(char *str)
+{
+       if (!str || *str != '=')
+               slub_debug = DEBUG_DEFAULT_FLAGS;
+       else {
+               str++;
+               if (*str == 0 || *str == ',')
+                       slub_debug = DEBUG_DEFAULT_FLAGS;
+               else
+               for( ;*str && *str != ','; str++)
+                       switch (*str) {
+                       case 'f' : case 'F' :
+                               slub_debug |= SLAB_DEBUG_FREE;
+                               break;
+                       case 'z' : case 'Z' :
+                               slub_debug |= SLAB_RED_ZONE;
+                               break;
+                       case 'p' : case 'P' :
+                               slub_debug |= SLAB_POISON;
+                               break;
+                       case 'u' : case 'U' :
+                               slub_debug |= SLAB_STORE_USER;
+                               break;
+                       case 't' : case 'T' :
+                               slub_debug |= SLAB_TRACE;
+                               break;
+                       default:
+                               printk(KERN_ERR "slub_debug option '%c' "
+                                       "unknown. skipped\n",*str);
+                       }
+       }
+
+       if (*str == ',')
+               slub_debug_slabs = str + 1;
+       return 1;
+}
+
+__setup("slub_debug", setup_slub_debug);
+
+static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s,
+               const char *name, int size, gfp_t gfp_flags)
+{
+       unsigned int flags = 0;
+
+       if (gfp_flags & SLUB_DMA)
+               flags = SLAB_CACHE_DMA;
+
+       down_write(&slub_lock);
+       if (!kmem_cache_open(s, gfp_flags, name, size, ARCH_KMALLOC_MINALIGN,
+                       flags, NULL, NULL))
+               goto panic;
+
+       list_add(&s->list, &slab_caches);
+       up_write(&slub_lock);
+       if (sysfs_slab_add(s))
+               goto panic;
+       return s;
+
+panic:
+       panic("Creation of kmalloc slab %s size=%d failed.\n", name, size);
+}
+
+static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+{
+       int index = kmalloc_index(size);
+
+       if (!index)
+               return NULL;
+
+       /* Allocation too large? */
+       BUG_ON(index < 0);
+
+#ifdef CONFIG_ZONE_DMA
+       if ((flags & SLUB_DMA)) {
+               struct kmem_cache *s;
+               struct kmem_cache *x;
+               char *text;
+               size_t realsize;
+
+               s = kmalloc_caches_dma[index];
+               if (s)
+                       return s;
+
+               /* Dynamically create dma cache */
+               x = kmalloc(kmem_size, flags & ~SLUB_DMA);
+               if (!x)
+                       panic("Unable to allocate memory for dma cache\n");
+
+               if (index <= KMALLOC_SHIFT_HIGH)
+                       realsize = 1 << index;
+               else {
+                       if (index == 1)
+                               realsize = 96;
+                       else
+                               realsize = 192;
+               }
+
+               text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
+                               (unsigned int)realsize);
+               s = create_kmalloc_cache(x, text, realsize, flags);
+               kmalloc_caches_dma[index] = s;
+               return s;
+       }
+#endif
+       return &kmalloc_caches[index];
+}
+
+void *__kmalloc(size_t size, gfp_t flags)
+{
+       struct kmem_cache *s = get_slab(size, flags);
+
+       if (s)
+               return slab_alloc(s, flags, -1, __builtin_return_address(0));
+       return NULL;
+}
+EXPORT_SYMBOL(__kmalloc);
+
+#ifdef CONFIG_NUMA
+void *__kmalloc_node(size_t size, gfp_t flags, int node)
+{
+       struct kmem_cache *s = get_slab(size, flags);
+
+       if (s)
+               return slab_alloc(s, flags, node, __builtin_return_address(0));
+       return NULL;
+}
+EXPORT_SYMBOL(__kmalloc_node);
+#endif
+
+size_t ksize(const void *object)
+{
+       struct page *page = get_object_page(object);
+       struct kmem_cache *s;
+
+       BUG_ON(!page);
+       s = page->slab;
+       BUG_ON(!s);
+
+       /*
+        * Debugging requires use of the padding between object
+        * and whatever may come after it.
+        */
+       if (s->flags & (SLAB_RED_ZONE | SLAB_POISON))
+               return s->objsize;
+
+       /*
+        * If we have the need to store the freelist pointer
+        * back there or track user information then we can
+        * only use the space before that information.
+        */
+       if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
+               return s->inuse;
+
+       /*
+        * Else we can use all the padding etc for the allocation
+        */
+       return s->size;
+}
+EXPORT_SYMBOL(ksize);
+
+void kfree(const void *x)
+{
+       struct kmem_cache *s;
+       struct page *page;
+
+       if (!x)
+               return;
+
+       page = virt_to_head_page(x);
+       s = page->slab;
+
+       slab_free(s, page, (void *)x, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(kfree);
+
+/*
+ *  kmem_cache_shrink removes empty slabs from the partial lists
+ *  and then sorts the partially allocated slabs by the number
+ *  of items in use. The slabs with the most items in use
+ *  come first. New allocations will remove these from the
+ *  partial list because they are full. The slabs with the
+ *  least items are placed last. If it happens that the objects
+ *  are freed then the page can be returned to the page allocator.
+ */
+int kmem_cache_shrink(struct kmem_cache *s)
+{
+       int node;
+       int i;
+       struct kmem_cache_node *n;
+       struct page *page;
+       struct page *t;
+       struct list_head *slabs_by_inuse =
+               kmalloc(sizeof(struct list_head) * s->objects, GFP_KERNEL);
+       unsigned long flags;
+
+       if (!slabs_by_inuse)
+               return -ENOMEM;
+
+       flush_all(s);
+       for_each_online_node(node) {
+               n = get_node(s, node);
+
+               if (!n->nr_partial)
+                       continue;
+
+               for (i = 0; i < s->objects; i++)
+                       INIT_LIST_HEAD(slabs_by_inuse + i);
+
+               spin_lock_irqsave(&n->list_lock, flags);
+
+               /*
+                * Build lists indexed by the items in use in
+                * each slab or free slabs if empty.
+                *
+                * Note that concurrent frees may occur while
+                * we hold the list_lock. page->inuse here is
+                * the upper limit.
+                */
+               list_for_each_entry_safe(page, t, &n->partial, lru) {
+                       if (!page->inuse && slab_trylock(page)) {
+                               /*
+                                * Must hold slab lock here because slab_free
+                                * may have freed the last object and be
+                                * waiting to release the slab.
+                                */
+                               list_del(&page->lru);
+                               n->nr_partial--;
+                               slab_unlock(page);
+                               discard_slab(s, page);
+                       } else {
+                               if (n->nr_partial > MAX_PARTIAL)
+                                       list_move(&page->lru,
+                                       slabs_by_inuse + page->inuse);
+                       }
+               }
+
+               if (n->nr_partial <= MAX_PARTIAL)
+                       goto out;
+
+               /*
+                * Rebuild the partial list with the slabs filled up
+                * most first and the least used slabs at the end.
+                */
+               for (i = s->objects - 1; i >= 0; i--)
+                       list_splice(slabs_by_inuse + i, n->partial.prev);
+
+       out:
+               spin_unlock_irqrestore(&n->list_lock, flags);
+       }
+
+       kfree(slabs_by_inuse);
+       return 0;
+}
+EXPORT_SYMBOL(kmem_cache_shrink);
+
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ *
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+       struct kmem_cache *new_cache;
+       void *ret;
+       struct page *page;
+
+       if (unlikely(!p))
+               return kmalloc(new_size, flags);
+
+       if (unlikely(!new_size)) {
+               kfree(p);
+               return NULL;
+       }
+
+       page = virt_to_head_page(p);
+
+       new_cache = get_slab(new_size, flags);
+
+       /*
+        * If new size fits in the current cache, bail out.
+        */
+       if (likely(page->slab == new_cache))
+               return (void *)p;
+
+       ret = kmalloc(new_size, flags);
+       if (ret) {
+               memcpy(ret, p, min(new_size, ksize(p)));
+               kfree(p);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(krealloc);
+
+/********************************************************************
+ *                     Basic setup of slabs
+ *******************************************************************/
+
+void __init kmem_cache_init(void)
+{
+       int i;
+
+#ifdef CONFIG_NUMA
+       /*
+        * Must first have the slab cache available for the allocations of the
+        * struct kmalloc_cache_node's. There is special bootstrap code in
+        * kmem_cache_open for slab_state == DOWN.
+        */
+       create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
+               sizeof(struct kmem_cache_node), GFP_KERNEL);
+#endif
+
+       /* Able to allocate the per node structures */
+       slab_state = PARTIAL;
+
+       /* Caches that are not of the two-to-the-power-of size */
+       create_kmalloc_cache(&kmalloc_caches[1],
+                               "kmalloc-96", 96, GFP_KERNEL);
+       create_kmalloc_cache(&kmalloc_caches[2],
+                               "kmalloc-192", 192, GFP_KERNEL);
+
+       for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+               create_kmalloc_cache(&kmalloc_caches[i],
+                       "kmalloc", 1 << i, GFP_KERNEL);
+
+       slab_state = UP;
+
+       /* Provide the correct kmalloc names now that the caches are up */
+       for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+               kmalloc_caches[i]. name =
+                       kasprintf(GFP_KERNEL, "kmalloc-%d", 1 << i);
+
+#ifdef CONFIG_SMP
+       register_cpu_notifier(&slab_notifier);
+#endif
+
+       if (nr_cpu_ids) /* Remove when nr_cpu_ids is fixed upstream ! */
+               kmem_size = offsetof(struct kmem_cache, cpu_slab)
+                        + nr_cpu_ids * sizeof(struct page *);
+
+       printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
+               " Processors=%d, Nodes=%d\n",
+               KMALLOC_SHIFT_HIGH, L1_CACHE_BYTES,
+               slub_min_order, slub_max_order, slub_min_objects,
+               nr_cpu_ids, nr_node_ids);
+}
+
+/*
+ * Find a mergeable slab cache
+ */
+static int slab_unmergeable(struct kmem_cache *s)
+{
+       if (slub_nomerge || (s->flags & SLUB_NEVER_MERGE))
+               return 1;
+
+       if (s->ctor || s->dtor)
+               return 1;
+
+       return 0;
+}
+
+static struct kmem_cache *find_mergeable(size_t size,
+               size_t align, unsigned long flags,
+               void (*ctor)(void *, struct kmem_cache *, unsigned long),
+               void (*dtor)(void *, struct kmem_cache *, unsigned long))
+{
+       struct list_head *h;
+
+       if (slub_nomerge || (flags & SLUB_NEVER_MERGE))
+               return NULL;
+
+       if (ctor || dtor)
+               return NULL;
+
+       size = ALIGN(size, sizeof(void *));
+       align = calculate_alignment(flags, align, size);
+       size = ALIGN(size, align);
+
+       list_for_each(h, &slab_caches) {
+               struct kmem_cache *s =
+                       container_of(h, struct kmem_cache, list);
+
+               if (slab_unmergeable(s))
+                       continue;
+
+               if (size > s->size)
+                       continue;
+
+               if (((flags | slub_debug) & SLUB_MERGE_SAME) !=
+                       (s->flags & SLUB_MERGE_SAME))
+                               continue;
+               /*
+                * Check if alignment is compatible.
+                * Courtesy of Adrian Drzewiecki
+                */
+               if ((s->size & ~(align -1)) != s->size)
+                       continue;
+
+               if (s->size - size >= sizeof(void *))
+                       continue;
+
+               return s;
+       }
+       return NULL;
+}
+
+struct kmem_cache *kmem_cache_create(const char *name, size_t size,
+               size_t align, unsigned long flags,
+               void (*ctor)(void *, struct kmem_cache *, unsigned long),
+               void (*dtor)(void *, struct kmem_cache *, unsigned long))
+{
+       struct kmem_cache *s;
+
+       down_write(&slub_lock);
+       s = find_mergeable(size, align, flags, dtor, ctor);
+       if (s) {
+               s->refcount++;
+               /*
+                * Adjust the object sizes so that we clear
+                * the complete object on kzalloc.
+                */
+               s->objsize = max(s->objsize, (int)size);
+               s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
+               if (sysfs_slab_alias(s, name))
+                       goto err;
+       } else {
+               s = kmalloc(kmem_size, GFP_KERNEL);
+               if (s && kmem_cache_open(s, GFP_KERNEL, name,
+                               size, align, flags, ctor, dtor)) {
+                       if (sysfs_slab_add(s)) {
+                               kfree(s);
+                               goto err;
+                       }
+                       list_add(&s->list, &slab_caches);
+               } else
+                       kfree(s);
+       }
+       up_write(&slub_lock);
+       return s;
+
+err:
+       up_write(&slub_lock);
+       if (flags & SLAB_PANIC)
+               panic("Cannot create slabcache %s\n", name);
+       else
+               s = NULL;
+       return s;
+}
+EXPORT_SYMBOL(kmem_cache_create);
+
+void *kmem_cache_zalloc(struct kmem_cache *s, gfp_t flags)
+{
+       void *x;
+
+       x = slab_alloc(s, flags, -1, __builtin_return_address(0));
+       if (x)
+               memset(x, 0, s->objsize);
+       return x;
+}
+EXPORT_SYMBOL(kmem_cache_zalloc);
+
+#ifdef CONFIG_SMP
+static void for_all_slabs(void (*func)(struct kmem_cache *, int), int cpu)
+{
+       struct list_head *h;
+
+       down_read(&slub_lock);
+       list_for_each(h, &slab_caches) {
+               struct kmem_cache *s =
+                       container_of(h, struct kmem_cache, list);
+
+               func(s, cpu);
+       }
+       up_read(&slub_lock);
+}
+
+/*
+ * Use the cpu notifier to insure that the slab are flushed
+ * when necessary.
+ */
+static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
+               unsigned long action, void *hcpu)
+{
+       long cpu = (long)hcpu;
+
+       switch (action) {
+       case CPU_UP_CANCELED:
+       case CPU_DEAD:
+               for_all_slabs(__flush_cpu_slab, cpu);
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata slab_notifier =
+       { &slab_cpuup_callback, NULL, 0 };
+
+#endif
+
+#ifdef CONFIG_NUMA
+
+/*****************************************************************
+ * Generic reaper used to support the page allocator
+ * (the cpu slabs are reaped by a per slab workqueue).
+ *
+ * Maybe move this to the page allocator?
+ ****************************************************************/
+
+static DEFINE_PER_CPU(unsigned long, reap_node);
+
+static void init_reap_node(int cpu)
+{
+       int node;
+
+       node = next_node(cpu_to_node(cpu), node_online_map);
+       if (node == MAX_NUMNODES)
+               node = first_node(node_online_map);
+
+       __get_cpu_var(reap_node) = node;
+}
+
+static void next_reap_node(void)
+{
+       int node = __get_cpu_var(reap_node);
+
+       /*
+        * Also drain per cpu pages on remote zones
+        */
+       if (node != numa_node_id())
+               drain_node_pages(node);
+
+       node = next_node(node, node_online_map);
+       if (unlikely(node >= MAX_NUMNODES))
+               node = first_node(node_online_map);
+       __get_cpu_var(reap_node) = node;
+}
+#else
+#define init_reap_node(cpu) do { } while (0)
+#define next_reap_node(void) do { } while (0)
+#endif
+
+#define REAPTIMEOUT_CPUC       (2*HZ)
+
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct delayed_work, reap_work);
+
+static void cache_reap(struct work_struct *unused)
+{
+       next_reap_node();
+       refresh_cpu_vm_stats(smp_processor_id());
+       schedule_delayed_work(&__get_cpu_var(reap_work),
+                                     REAPTIMEOUT_CPUC);
+}
+
+static void __devinit start_cpu_timer(int cpu)
+{
+       struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
+
+       /*
+        * When this gets called from do_initcalls via cpucache_init(),
+        * init_workqueues() has already run, so keventd will be setup
+        * at that time.
+        */
+       if (keventd_up() && reap_work->work.func == NULL) {
+               init_reap_node(cpu);
+               INIT_DELAYED_WORK(reap_work, cache_reap);
+               schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
+       }
+}
+
+static int __init cpucache_init(void)
+{
+       int cpu;
+
+       /*
+        * Register the timers that drain pcp pages and update vm statistics
+        */
+       for_each_online_cpu(cpu)
+               start_cpu_timer(cpu);
+       return 0;
+}
+__initcall(cpucache_init);
+#endif
+
+#ifdef SLUB_RESILIENCY_TEST
+static unsigned long validate_slab_cache(struct kmem_cache *s);
+
+static void resiliency_test(void)
+{
+       u8 *p;
+
+       printk(KERN_ERR "SLUB resiliency testing\n");
+       printk(KERN_ERR "-----------------------\n");
+       printk(KERN_ERR "A. Corruption after allocation\n");
+
+       p = kzalloc(16, GFP_KERNEL);
+       p[16] = 0x12;
+       printk(KERN_ERR "\n1. kmalloc-16: Clobber Redzone/next pointer"
+                       " 0x12->0x%p\n\n", p + 16);
+
+       validate_slab_cache(kmalloc_caches + 4);
+
+       /* Hmmm... The next two are dangerous */
+       p = kzalloc(32, GFP_KERNEL);
+       p[32 + sizeof(void *)] = 0x34;
+       printk(KERN_ERR "\n2. kmalloc-32: Clobber next pointer/next slab"
+                       " 0x34 -> -0x%p\n", p);
+       printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
+
+       validate_slab_cache(kmalloc_caches + 5);
+       p = kzalloc(64, GFP_KERNEL);
+       p += 64 + (get_cycles() & 0xff) * sizeof(void *);
+       *p = 0x56;
+       printk(KERN_ERR "\n3. kmalloc-64: corrupting random byte 0x56->0x%p\n",
+                                                                       p);
+       printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
+       validate_slab_cache(kmalloc_caches + 6);
+
+       printk(KERN_ERR "\nB. Corruption after free\n");
+       p = kzalloc(128, GFP_KERNEL);
+       kfree(p);
+       *p = 0x78;
+       printk(KERN_ERR "1. kmalloc-128: Clobber first word 0x78->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches + 7);
+
+       p = kzalloc(256, GFP_KERNEL);
+       kfree(p);
+       p[50] = 0x9a;
+       printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches + 8);
+
+       p = kzalloc(512, GFP_KERNEL);
+       kfree(p);
+       p[512] = 0xab;
+       printk(KERN_ERR "\n3. kmalloc-512: Clobber redzone 0xab->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches + 9);
+}
+#else
+static void resiliency_test(void) {};
+#endif
+
+/*
+ * These are not as efficient as kmalloc for the non debug case.
+ * We do not have the page struct available so we have to touch one
+ * cacheline in struct kmem_cache to check slab flags.
+ */
+void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
+{
+       struct kmem_cache *s = get_slab(size, gfpflags);
+
+       if (!s)
+               return NULL;
+
+       return slab_alloc(s, gfpflags, -1, caller);
+}
+
+void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
+                                       int node, void *caller)
+{
+       struct kmem_cache *s = get_slab(size, gfpflags);
+
+       if (!s)
+               return NULL;
+
+       return slab_alloc(s, gfpflags, node, caller);
+}
+
+#ifdef CONFIG_SYSFS
+
+static int validate_slab(struct kmem_cache *s, struct page *page)
+{
+       void *p;
+       void *addr = page_address(page);
+       unsigned long map[BITS_TO_LONGS(s->objects)];
+
+       if (!check_slab(s, page) ||
+                       !on_freelist(s, page, NULL))
+               return 0;
+
+       /* Now we know that a valid freelist exists */
+       bitmap_zero(map, s->objects);
+
+       for(p = page->freelist; p; p = get_freepointer(s, p)) {
+               set_bit((p - addr) / s->size, map);
+               if (!check_object(s, page, p, 0))
+                       return 0;
+       }
+
+       for(p = addr; p < addr + s->objects * s->size; p += s->size)
+               if (!test_bit((p - addr) / s->size, map))
+                       if (!check_object(s, page, p, 1))
+                               return 0;
+       return 1;
+}
+
+static void validate_slab_slab(struct kmem_cache *s, struct page *page)
+{
+       if (slab_trylock(page)) {
+               validate_slab(s, page);
+               slab_unlock(page);
+       } else
+               printk(KERN_INFO "SLUB %s: Skipped busy slab 0x%p\n",
+                       s->name, page);
+
+       if (s->flags & DEBUG_DEFAULT_FLAGS) {
+               if (!PageError(page))
+                       printk(KERN_ERR "SLUB %s: PageError not set "
+                               "on slab 0x%p\n", s->name, page);
+       } else {
+               if (PageError(page))
+                       printk(KERN_ERR "SLUB %s: PageError set on "
+                               "slab 0x%p\n", s->name, page);
+       }
+}
+
+static int validate_slab_node(struct kmem_cache *s, struct kmem_cache_node *n)
+{
+       unsigned long count = 0;
+       struct page *page;
+       unsigned long flags;
+
+       spin_lock_irqsave(&n->list_lock, flags);
+
+       list_for_each_entry(page, &n->partial, lru) {
+               validate_slab_slab(s, page);
+               count++;
+       }
+       if (count != n->nr_partial)
+               printk(KERN_ERR "SLUB %s: %ld partial slabs counted but "
+                       "counter=%ld\n", s->name, count, n->nr_partial);
+
+       if (!(s->flags & SLAB_STORE_USER))
+               goto out;
+
+       list_for_each_entry(page, &n->full, lru) {
+               validate_slab_slab(s, page);
+               count++;
+       }
+       if (count != atomic_long_read(&n->nr_slabs))
+               printk(KERN_ERR "SLUB: %s %ld slabs counted but "
+                       "counter=%ld\n", s->name, count,
+                       atomic_long_read(&n->nr_slabs));
+
+out:
+       spin_unlock_irqrestore(&n->list_lock, flags);
+       return count;
+}
+
+static unsigned long validate_slab_cache(struct kmem_cache *s)
+{
+       int node;
+       unsigned long count = 0;
+
+       flush_all(s);
+       for_each_online_node(node) {
+               struct kmem_cache_node *n = get_node(s, node);
+
+               count += validate_slab_node(s, n);
+       }
+       return count;
+}
+
+/*
+ * Generate lists of locations where slabcache objects are allocated
+ * and freed.
+ */
+
+struct location {
+       unsigned long count;
+       void *addr;
+};
+
+struct loc_track {
+       unsigned long max;
+       unsigned long count;
+       struct location *loc;
+};
+
+static void free_loc_track(struct loc_track *t)
+{
+       if (t->max)
+               free_pages((unsigned long)t->loc,
+                       get_order(sizeof(struct location) * t->max));
+}
+
+static int alloc_loc_track(struct loc_track *t, unsigned long max)
+{
+       struct location *l;
+       int order;
+
+       if (!max)
+               max = PAGE_SIZE / sizeof(struct location);
+
+       order = get_order(sizeof(struct location) * max);
+
+       l = (void *)__get_free_pages(GFP_KERNEL, order);
+
+       if (!l)
+               return 0;
+
+       if (t->count) {
+               memcpy(l, t->loc, sizeof(struct location) * t->count);
+               free_loc_track(t);
+       }
+       t->max = max;
+       t->loc = l;
+       return 1;
+}
+
+static int add_location(struct loc_track *t, struct kmem_cache *s,
+                                               void *addr)
+{
+       long start, end, pos;
+       struct location *l;
+       void *caddr;
+
+       start = -1;
+       end = t->count;
+
+       for ( ; ; ) {
+               pos = start + (end - start + 1) / 2;
+
+               /*
+                * There is nothing at "end". If we end up there
+                * we need to add something to before end.
+                */
+               if (pos == end)
+                       break;
+
+               caddr = t->loc[pos].addr;
+               if (addr == caddr) {
+                       t->loc[pos].count++;
+                       return 1;
+               }
+
+               if (addr < caddr)
+                       end = pos;
+               else
+                       start = pos;
+       }
+
+       /*
+        * Not found. Insert new tracking element
+        */
+       if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max))
+               return 0;
+
+       l = t->loc + pos;
+       if (pos < t->count)
+               memmove(l + 1, l,
+                       (t->count - pos) * sizeof(struct location));
+       t->count++;
+       l->count = 1;
+       l->addr = addr;
+       return 1;
+}
+
+static void process_slab(struct loc_track *t, struct kmem_cache *s,
+               struct page *page, enum track_item alloc)
+{
+       void *addr = page_address(page);
+       unsigned long map[BITS_TO_LONGS(s->objects)];
+       void *p;
+
+       bitmap_zero(map, s->objects);
+       for (p = page->freelist; p; p = get_freepointer(s, p))
+               set_bit((p - addr) / s->size, map);
+
+       for (p = addr; p < addr + s->objects * s->size; p += s->size)
+               if (!test_bit((p - addr) / s->size, map)) {
+                       void *addr = get_track(s, p, alloc)->addr;
+
+                       add_location(t, s, addr);
+               }
+}
+
+static int list_locations(struct kmem_cache *s, char *buf,
+                                       enum track_item alloc)
+{
+       int n = 0;
+       unsigned long i;
+       struct loc_track t;
+       int node;
+
+       t.count = 0;
+       t.max = 0;
+
+       /* Push back cpu slabs */
+       flush_all(s);
+
+       for_each_online_node(node) {
+               struct kmem_cache_node *n = get_node(s, node);
+               unsigned long flags;
+               struct page *page;
+
+               if (!atomic_read(&n->nr_slabs))
+                       continue;
+
+               spin_lock_irqsave(&n->list_lock, flags);
+               list_for_each_entry(page, &n->partial, lru)
+                       process_slab(&t, s, page, alloc);
+               list_for_each_entry(page, &n->full, lru)
+                       process_slab(&t, s, page, alloc);
+               spin_unlock_irqrestore(&n->list_lock, flags);
+       }
+
+       for (i = 0; i < t.count; i++) {
+               void *addr = t.loc[i].addr;
+
+               if (n > PAGE_SIZE - 100)
+                       break;
+               n += sprintf(buf + n, "%7ld ", t.loc[i].count);
+               if (addr)
+                       n += sprint_symbol(buf + n, (unsigned long)t.loc[i].addr);
+               else
+                       n += sprintf(buf + n, "<not-available>");
+               n += sprintf(buf + n, "\n");
+       }
+
+       free_loc_track(&t);
+       if (!t.count)
+               n += sprintf(buf, "No data\n");
+       return n;
+}
+
+static unsigned long count_partial(struct kmem_cache_node *n)
+{
+       unsigned long flags;
+       unsigned long x = 0;
+       struct page *page;
+
+       spin_lock_irqsave(&n->list_lock, flags);
+       list_for_each_entry(page, &n->partial, lru)
+               x += page->inuse;
+       spin_unlock_irqrestore(&n->list_lock, flags);
+       return x;
+}
+
+enum slab_stat_type {
+       SL_FULL,
+       SL_PARTIAL,
+       SL_CPU,
+       SL_OBJECTS
+};
+
+#define SO_FULL                (1 << SL_FULL)
+#define SO_PARTIAL     (1 << SL_PARTIAL)
+#define SO_CPU         (1 << SL_CPU)
+#define SO_OBJECTS     (1 << SL_OBJECTS)
+
+static unsigned long slab_objects(struct kmem_cache *s,
+                       char *buf, unsigned long flags)
+{
+       unsigned long total = 0;
+       int cpu;
+       int node;
+       int x;
+       unsigned long *nodes;
+       unsigned long *per_cpu;
+
+       nodes = kzalloc(2 * sizeof(unsigned long) * nr_node_ids, GFP_KERNEL);
+       per_cpu = nodes + nr_node_ids;
+
+       for_each_possible_cpu(cpu) {
+               struct page *page = s->cpu_slab[cpu];
+               int node;
+
+               if (page) {
+                       node = page_to_nid(page);
+                       if (flags & SO_CPU) {
+                               int x = 0;
+
+                               if (flags & SO_OBJECTS)
+                                       x = page->inuse;
+                               else
+                                       x = 1;
+                               total += x;
+                               nodes[node] += x;
+                       }
+                       per_cpu[node]++;
+               }
+       }
+
+       for_each_online_node(node) {
+               struct kmem_cache_node *n = get_node(s, node);
+
+               if (flags & SO_PARTIAL) {
+                       if (flags & SO_OBJECTS)
+                               x = count_partial(n);
+                       else
+                               x = n->nr_partial;
+                       total += x;
+                       nodes[node] += x;
+               }
+
+               if (flags & SO_FULL) {
+                       int full_slabs = atomic_read(&n->nr_slabs)
+                                       - per_cpu[node]
+                                       - n->nr_partial;
+
+                       if (flags & SO_OBJECTS)
+                               x = full_slabs * s->objects;
+                       else
+                               x = full_slabs;
+                       total += x;
+                       nodes[node] += x;
+               }
+       }
+
+       x = sprintf(buf, "%lu", total);
+#ifdef CONFIG_NUMA
+       for_each_online_node(node)
+               if (nodes[node])
+                       x += sprintf(buf + x, " N%d=%lu",
+                                       node, nodes[node]);
+#endif
+       kfree(nodes);
+       return x + sprintf(buf + x, "\n");
+}
+
+static int any_slab_objects(struct kmem_cache *s)
+{
+       int node;
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               if (s->cpu_slab[cpu])
+                       return 1;
+
+       for_each_node(node) {
+               struct kmem_cache_node *n = get_node(s, node);
+
+               if (n->nr_partial || atomic_read(&n->nr_slabs))
+                       return 1;
+       }
+       return 0;
+}
+
+#define to_slab_attr(n) container_of(n, struct slab_attribute, attr)
+#define to_slab(n) container_of(n, struct kmem_cache, kobj);
+
+struct slab_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct kmem_cache *s, char *buf);
+       ssize_t (*store)(struct kmem_cache *s, const char *x, size_t count);
+};
+
+#define SLAB_ATTR_RO(_name) \
+       static struct slab_attribute _name##_attr = __ATTR_RO(_name)
+
+#define SLAB_ATTR(_name) \
+       static struct slab_attribute _name##_attr =  \
+       __ATTR(_name, 0644, _name##_show, _name##_store)
+
+static ssize_t slab_size_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->size);
+}
+SLAB_ATTR_RO(slab_size);
+
+static ssize_t align_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->align);
+}
+SLAB_ATTR_RO(align);
+
+static ssize_t object_size_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->objsize);
+}
+SLAB_ATTR_RO(object_size);
+
+static ssize_t objs_per_slab_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->objects);
+}
+SLAB_ATTR_RO(objs_per_slab);
+
+static ssize_t order_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->order);
+}
+SLAB_ATTR_RO(order);
+
+static ssize_t ctor_show(struct kmem_cache *s, char *buf)
+{
+       if (s->ctor) {
+               int n = sprint_symbol(buf, (unsigned long)s->ctor);
+
+               return n + sprintf(buf + n, "\n");
+       }
+       return 0;
+}
+SLAB_ATTR_RO(ctor);
+
+static ssize_t dtor_show(struct kmem_cache *s, char *buf)
+{
+       if (s->dtor) {
+               int n = sprint_symbol(buf, (unsigned long)s->dtor);
+
+               return n + sprintf(buf + n, "\n");
+       }
+       return 0;
+}
+SLAB_ATTR_RO(dtor);
+
+static ssize_t aliases_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->refcount - 1);
+}
+SLAB_ATTR_RO(aliases);
+
+static ssize_t slabs_show(struct kmem_cache *s, char *buf)
+{
+       return slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU);
+}
+SLAB_ATTR_RO(slabs);
+
+static ssize_t partial_show(struct kmem_cache *s, char *buf)
+{
+       return slab_objects(s, buf, SO_PARTIAL);
+}
+SLAB_ATTR_RO(partial);
+
+static ssize_t cpu_slabs_show(struct kmem_cache *s, char *buf)
+{
+       return slab_objects(s, buf, SO_CPU);
+}
+SLAB_ATTR_RO(cpu_slabs);
+
+static ssize_t objects_show(struct kmem_cache *s, char *buf)
+{
+       return slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU|SO_OBJECTS);
+}
+SLAB_ATTR_RO(objects);
+
+static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE));
+}
+
+static ssize_t sanity_checks_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
+{
+       s->flags &= ~SLAB_DEBUG_FREE;
+       if (buf[0] == '1')
+               s->flags |= SLAB_DEBUG_FREE;
+       return length;
+}
+SLAB_ATTR(sanity_checks);
+
+static ssize_t trace_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_TRACE));
+}
+
+static ssize_t trace_store(struct kmem_cache *s, const char *buf,
+                                                       size_t length)
+{
+       s->flags &= ~SLAB_TRACE;
+       if (buf[0] == '1')
+               s->flags |= SLAB_TRACE;
+       return length;
+}
+SLAB_ATTR(trace);
+
+static ssize_t reclaim_account_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_RECLAIM_ACCOUNT));
+}
+
+static ssize_t reclaim_account_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
+{
+       s->flags &= ~SLAB_RECLAIM_ACCOUNT;
+       if (buf[0] == '1')
+               s->flags |= SLAB_RECLAIM_ACCOUNT;
+       return length;
+}
+SLAB_ATTR(reclaim_account);
+
+static ssize_t hwcache_align_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_HWCACHE_ALIGN));
+}
+SLAB_ATTR_RO(hwcache_align);
+
+#ifdef CONFIG_ZONE_DMA
+static ssize_t cache_dma_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_CACHE_DMA));
+}
+SLAB_ATTR_RO(cache_dma);
+#endif
+
+static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DESTROY_BY_RCU));
+}
+SLAB_ATTR_RO(destroy_by_rcu);
+
+static ssize_t red_zone_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_RED_ZONE));
+}
+
+static ssize_t red_zone_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
+{
+       if (any_slab_objects(s))
+               return -EBUSY;
+
+       s->flags &= ~SLAB_RED_ZONE;
+       if (buf[0] == '1')
+               s->flags |= SLAB_RED_ZONE;
+       calculate_sizes(s);
+       return length;
+}
+SLAB_ATTR(red_zone);
+
+static ssize_t poison_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_POISON));
+}
+
+static ssize_t poison_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
+{
+       if (any_slab_objects(s))
+               return -EBUSY;
+
+       s->flags &= ~SLAB_POISON;
+       if (buf[0] == '1')
+               s->flags |= SLAB_POISON;
+       calculate_sizes(s);
+       return length;
+}
+SLAB_ATTR(poison);
+
+static ssize_t store_user_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_STORE_USER));
+}
+
+static ssize_t store_user_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
+{
+       if (any_slab_objects(s))
+               return -EBUSY;
+
+       s->flags &= ~SLAB_STORE_USER;
+       if (buf[0] == '1')
+               s->flags |= SLAB_STORE_USER;
+       calculate_sizes(s);
+       return length;
+}
+SLAB_ATTR(store_user);
+
+static ssize_t validate_show(struct kmem_cache *s, char *buf)
+{
+       return 0;
+}
+
+static ssize_t validate_store(struct kmem_cache *s,
+                       const char *buf, size_t length)
+{
+       if (buf[0] == '1')
+               validate_slab_cache(s);
+       else
+               return -EINVAL;
+       return length;
+}
+SLAB_ATTR(validate);
+
+static ssize_t shrink_show(struct kmem_cache *s, char *buf)
+{
+       return 0;
+}
+
+static ssize_t shrink_store(struct kmem_cache *s,
+                       const char *buf, size_t length)
+{
+       if (buf[0] == '1') {
+               int rc = kmem_cache_shrink(s);
+
+               if (rc)
+                       return rc;
+       } else
+               return -EINVAL;
+       return length;
+}
+SLAB_ATTR(shrink);
+
+static ssize_t alloc_calls_show(struct kmem_cache *s, char *buf)
+{
+       if (!(s->flags & SLAB_STORE_USER))
+               return -ENOSYS;
+       return list_locations(s, buf, TRACK_ALLOC);
+}
+SLAB_ATTR_RO(alloc_calls);
+
+static ssize_t free_calls_show(struct kmem_cache *s, char *buf)
+{
+       if (!(s->flags & SLAB_STORE_USER))
+               return -ENOSYS;
+       return list_locations(s, buf, TRACK_FREE);
+}
+SLAB_ATTR_RO(free_calls);
+
+#ifdef CONFIG_NUMA
+static ssize_t defrag_ratio_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", s->defrag_ratio / 10);
+}
+
+static ssize_t defrag_ratio_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
+{
+       int n = simple_strtoul(buf, NULL, 10);
+
+       if (n < 100)
+               s->defrag_ratio = n * 10;
+       return length;
+}
+SLAB_ATTR(defrag_ratio);
+#endif
+
+static struct attribute * slab_attrs[] = {
+       &slab_size_attr.attr,
+       &object_size_attr.attr,
+       &objs_per_slab_attr.attr,
+       &order_attr.attr,
+       &objects_attr.attr,
+       &slabs_attr.attr,
+       &partial_attr.attr,
+       &cpu_slabs_attr.attr,
+       &ctor_attr.attr,
+       &dtor_attr.attr,
+       &aliases_attr.attr,
+       &align_attr.attr,
+       &sanity_checks_attr.attr,
+       &trace_attr.attr,
+       &hwcache_align_attr.attr,
+       &reclaim_account_attr.attr,
+       &destroy_by_rcu_attr.attr,
+       &red_zone_attr.attr,
+       &poison_attr.attr,
+       &store_user_attr.attr,
+       &validate_attr.attr,
+       &shrink_attr.attr,
+       &alloc_calls_attr.attr,
+       &free_calls_attr.attr,
+#ifdef CONFIG_ZONE_DMA
+       &cache_dma_attr.attr,
+#endif
+#ifdef CONFIG_NUMA
+       &defrag_ratio_attr.attr,
+#endif
+       NULL
+};
+
+static struct attribute_group slab_attr_group = {
+       .attrs = slab_attrs,
+};
+
+static ssize_t slab_attr_show(struct kobject *kobj,
+                               struct attribute *attr,
+                               char *buf)
+{
+       struct slab_attribute *attribute;
+       struct kmem_cache *s;
+       int err;
+
+       attribute = to_slab_attr(attr);
+       s = to_slab(kobj);
+
+       if (!attribute->show)
+               return -EIO;
+
+       err = attribute->show(s, buf);
+
+       return err;
+}
+
+static ssize_t slab_attr_store(struct kobject *kobj,
+                               struct attribute *attr,
+                               const char *buf, size_t len)
+{
+       struct slab_attribute *attribute;
+       struct kmem_cache *s;
+       int err;
+
+       attribute = to_slab_attr(attr);
+       s = to_slab(kobj);
+
+       if (!attribute->store)
+               return -EIO;
+
+       err = attribute->store(s, buf, len);
+
+       return err;
+}
+
+static struct sysfs_ops slab_sysfs_ops = {
+       .show = slab_attr_show,
+       .store = slab_attr_store,
+};
+
+static struct kobj_type slab_ktype = {
+       .sysfs_ops = &slab_sysfs_ops,
+};
+
+static int uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+       struct kobj_type *ktype = get_ktype(kobj);
+
+       if (ktype == &slab_ktype)
+               return 1;
+       return 0;
+}
+
+static struct kset_uevent_ops slab_uevent_ops = {
+       .filter = uevent_filter,
+};
+
+decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
+
+#define ID_STR_LENGTH 64
+
+/* Create a unique string id for a slab cache:
+ * format
+ * :[flags-]size:[memory address of kmemcache]
+ */
+static char *create_unique_id(struct kmem_cache *s)
+{
+       char *name = kmalloc(ID_STR_LENGTH, GFP_KERNEL);
+       char *p = name;
+
+       BUG_ON(!name);
+
+       *p++ = ':';
+       /*
+        * First flags affecting slabcache operations. We will only
+        * get here for aliasable slabs so we do not need to support
+        * too many flags. The flags here must cover all flags that
+        * are matched during merging to guarantee that the id is
+        * unique.
+        */
+       if (s->flags & SLAB_CACHE_DMA)
+               *p++ = 'd';
+       if (s->flags & SLAB_RECLAIM_ACCOUNT)
+               *p++ = 'a';
+       if (s->flags & SLAB_DEBUG_FREE)
+               *p++ = 'F';
+       if (p != name + 1)
+               *p++ = '-';
+       p += sprintf(p, "%07d", s->size);
+       BUG_ON(p > name + ID_STR_LENGTH - 1);
+       return name;
+}
+
+static int sysfs_slab_add(struct kmem_cache *s)
+{
+       int err;
+       const char *name;
+       int unmergeable;
+
+       if (slab_state < SYSFS)
+               /* Defer until later */
+               return 0;
+
+       unmergeable = slab_unmergeable(s);
+       if (unmergeable) {
+               /*
+                * Slabcache can never be merged so we can use the name proper.
+                * This is typically the case for debug situations. In that
+                * case we can catch duplicate names easily.
+                */
+               sysfs_remove_link(&slab_subsys.kobj, s->name);
+               name = s->name;
+       } else {
+               /*
+                * Create a unique name for the slab as a target
+                * for the symlinks.
+                */
+               name = create_unique_id(s);
+       }
+
+       kobj_set_kset_s(s, slab_subsys);
+       kobject_set_name(&s->kobj, name);
+       kobject_init(&s->kobj);
+       err = kobject_add(&s->kobj);
+       if (err)
+               return err;
+
+       err = sysfs_create_group(&s->kobj, &slab_attr_group);
+       if (err)
+               return err;
+       kobject_uevent(&s->kobj, KOBJ_ADD);
+       if (!unmergeable) {
+               /* Setup first alias */
+               sysfs_slab_alias(s, s->name);
+               kfree(name);
+       }
+       return 0;
+}
+
+static void sysfs_slab_remove(struct kmem_cache *s)
+{
+       kobject_uevent(&s->kobj, KOBJ_REMOVE);
+       kobject_del(&s->kobj);
+}
+
+/*
+ * Need to buffer aliases during bootup until sysfs becomes
+ * available lest we loose that information.
+ */
+struct saved_alias {
+       struct kmem_cache *s;
+       const char *name;
+       struct saved_alias *next;
+};
+
+struct saved_alias *alias_list;
+
+static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
+{
+       struct saved_alias *al;
+
+       if (slab_state == SYSFS) {
+               /*
+                * If we have a leftover link then remove it.
+                */
+               sysfs_remove_link(&slab_subsys.kobj, name);
+               return sysfs_create_link(&slab_subsys.kobj,
+                                               &s->kobj, name);
+       }
+
+       al = kmalloc(sizeof(struct saved_alias), GFP_KERNEL);
+       if (!al)
+               return -ENOMEM;
+
+       al->s = s;
+       al->name = name;
+       al->next = alias_list;
+       alias_list = al;
+       return 0;
+}
+
+static int __init slab_sysfs_init(void)
+{
+       int err;
+
+       err = subsystem_register(&slab_subsys);
+       if (err) {
+               printk(KERN_ERR "Cannot register slab subsystem.\n");
+               return -ENOSYS;
+       }
+
+       finish_bootstrap();
+
+       while (alias_list) {
+               struct saved_alias *al = alias_list;
+
+               alias_list = alias_list->next;
+               err = sysfs_slab_alias(al->s, al->name);
+               BUG_ON(err);
+               kfree(al);
+       }
+
+       resiliency_test();
+       return 0;
+}
+
+__initcall(slab_sysfs_init);
+#else
+__initcall(finish_bootstrap);
+#endif
index ac26eb0..893e562 100644 (file)
@@ -272,7 +272,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
  * Allocate the accumulated non-linear sections, allocate a mem_map
  * for each and record the physical to section mapping.
  */
-void sparse_init(void)
+void __init sparse_init(void)
 {
        unsigned long pnum;
        struct page *map;
index 2ed7be3..218c52a 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -55,7 +55,7 @@ static void fastcall __page_cache_release(struct page *page)
 
 static void put_compound_page(struct page *page)
 {
-       page = (struct page *)page_private(page);
+       page = compound_head(page);
        if (put_page_testzero(page)) {
                compound_page_dtor *dtor;
 
index a2d9bb4..acc172c 100644 (file)
@@ -1531,9 +1531,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                error = PTR_ERR(page);
                goto bad_swap;
        }
-       wait_on_page_locked(page);
-       if (!PageUptodate(page))
-               goto bad_swap;
        kmap(page);
        swap_header = page_address(page);
 
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 db023e2..56651a1 100644 (file)
@@ -1323,8 +1323,6 @@ static int kswapd(void *p)
        for ( ; ; ) {
                unsigned long new_order;
 
-               try_to_freeze();
-
                prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
                new_order = pgdat->kswapd_max_order;
                pgdat->kswapd_max_order = 0;
@@ -1335,12 +1333,19 @@ static int kswapd(void *p)
                         */
                        order = new_order;
                } else {
-                       schedule();
+                       if (!freezing(current))
+                               schedule();
+
                        order = pgdat->kswapd_max_order;
                }
                finish_wait(&pgdat->kswapd_wait, &wait);
 
-               balance_pgdat(pgdat, order);
+               if (!try_to_freeze()) {
+                       /* We can speed up thawing tasks if we don't call
+                        * balance_pgdat after returning from the refrigerator
+                        */
+                       balance_pgdat(pgdat, order);
+               }
        }
        return 0;
 }
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..caeacd1 100644 (file)
@@ -220,10 +220,13 @@ config FIB_RULES
 menu "Wireless"
 
 source "net/wireless/Kconfig"
+source "net/mac80211/Kconfig"
 source "net/ieee80211/Kconfig"
 
 endmenu
 
+source "net/rfkill/Kconfig"
+
 endif   # if NET
 endmenu # Networking
 
index 6b74d41..34e5b2d 100644 (file)
@@ -45,13 +45,14 @@ 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/
 obj-$(CONFIG_IUCV)             += iucv/
+obj-$(CONFIG_RFKILL)           += rfkill/
 
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)           += sysctl_net.o
 endif
-
-obj-y                          += wireless/
index 832b5f4..bfc9a35 100644 (file)
@@ -499,6 +499,15 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char
                break;
 
        case HCI_FILTER:
+               {
+                       struct hci_filter *f = &hci_pi(sk)->filter;
+
+                       uf.type_mask = f->type_mask;
+                       uf.opcode    = f->opcode;
+                       uf.event_mask[0] = *((u32 *) f->event_mask + 0);
+                       uf.event_mask[1] = *((u32 *) f->event_mask + 1);
+               }
+
                len = min_t(unsigned int, len, sizeof(uf));
                if (copy_from_user(&uf, optval, len)) {
                        err = -EFAULT;
index 801d687..2583540 100644 (file)
@@ -305,7 +305,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
 
        BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-       dev->class = bt_class;
+       dev->bus = &bt_bus;
        dev->parent = hdev->parent;
 
        strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
@@ -322,6 +322,10 @@ int hci_register_sysfs(struct hci_dev *hdev)
                if (device_create_file(dev, bt_attrs[i]) < 0)
                        BT_ERR("Failed to create device attribute");
 
+       if (sysfs_create_link(&bt_class->subsys.kobj,
+                               &dev->kobj, kobject_name(&dev->kobj)) < 0)
+               BT_ERR("Failed to create class symlink");
+
        return 0;
 }
 
@@ -329,6 +333,9 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
 {
        BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
+       sysfs_remove_link(&bt_class->subsys.kobj,
+                                       kobject_name(&hdev->dev.kobj));
+
        device_del(&hdev->dev);
 }
 
index a586787..a59b1fb 100644 (file)
@@ -954,11 +954,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               opts.imtu     = l2cap_pi(sk)->imtu;
+               opts.omtu     = l2cap_pi(sk)->omtu;
+               opts.flush_to = l2cap_pi(sk)->flush_to;
+               opts.mode     = 0x00;
+
                len = min_t(unsigned int, sizeof(opts), optlen);
                if (copy_from_user((char *) &opts, optval, len)) {
                        err = -EFAULT;
                        break;
                }
+
                l2cap_pi(sk)->imtu  = opts.imtu;
                l2cap_pi(sk)->omtu  = opts.omtu;
                break;
index fe7df90..52e04df 100644 (file)
@@ -622,7 +622,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
        bacpy(&addr.l2_bdaddr, src);
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = 0;
-       *err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr));
+       *err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (*err < 0)
                goto failed;
 
@@ -643,7 +643,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
        bacpy(&addr.l2_bdaddr, dst);
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = htobs(RFCOMM_PSM);
-       *err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
+       *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
        if (*err == 0 || *err == -EINPROGRESS)
                return s;
 
@@ -1058,6 +1058,12 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
                case BT_DISCONN:
                        d->state = BT_CLOSED;
                        __rfcomm_dlc_close(d, 0);
+
+                       if (list_empty(&s->dlcs)) {
+                               s->state = BT_DISCONN;
+                               rfcomm_send_disc(s, 0);
+                       }
+
                        break;
                }
        } else {
@@ -1067,6 +1073,10 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
                        s->state = BT_CONNECTED;
                        rfcomm_process_connect(s);
                        break;
+
+               case BT_DISCONN:
+                       rfcomm_session_put(s);
+                       break;
                }
        }
        return 0;
@@ -1757,19 +1767,12 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
 
        BT_DBG("session %p", s);
 
-       if (sock_create_lite(PF_BLUETOOTH, sock->type, BTPROTO_L2CAP, &nsock))
+       err = kernel_accept(sock, &nsock, O_NONBLOCK);
+       if (err < 0)
                return;
 
-       nsock->ops  = sock->ops;
-
        __module_get(nsock->ops->owner);
 
-       err = sock->ops->accept(sock, nsock, O_NONBLOCK);
-       if (err < 0) {
-               sock_release(nsock);
-               return;
-       }
-
        /* Set our callbacks */
        nsock->sk->sk_data_ready   = rfcomm_l2data_ready;
        nsock->sk->sk_state_change = rfcomm_l2state_change;
@@ -1885,7 +1888,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
        bacpy(&addr.l2_bdaddr, ba);
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = htobs(RFCOMM_PSM);
-       err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr));
+       err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (err < 0) {
                BT_ERR("Bind failed %d", err);
                goto failed;
@@ -1898,7 +1901,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
        release_sock(sk);
 
        /* Start listening on the socket */
-       err = sock->ops->listen(sock, 10);
+       err = kernel_listen(sock, 10);
        if (err) {
                BT_ERR("Listen failed %d", err);
                goto failed;
index 9a7a44f..b2b1cce 100644 (file)
@@ -517,9 +517,10 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
        if (dlc->state == BT_CLOSED) {
                if (!dev->tty) {
                        if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
-                               rfcomm_dev_hold(dev);
-                               rfcomm_dev_del(dev);
+                               if (rfcomm_dev_get(dev->id) == NULL)
+                                       return;
 
+                               rfcomm_dev_del(dev);
                                /* We have to drop DLC lock here, otherwise
                                   rfcomm_dev_put() will dead lock if it's
                                   the last reference. */
@@ -974,8 +975,12 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
 
        rfcomm_tty_flush_buffer(tty);
 
-       if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
+       if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
+               if (rfcomm_dev_get(dev->id) == NULL)
+                       return;
                rfcomm_dev_del(dev);
+               rfcomm_dev_put(dev);
+       }
 }
 
 static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused)
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..4317c1b 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)
@@ -2362,9 +2377,9 @@ static int __init dev_proc_init(void)
 out:
        return rc;
 out_softnet:
-       proc_net_remove("softnet_stat");
-out_dev2:
        proc_net_remove("ptype");
+out_dev2:
+       proc_net_remove("softnet_stat");
 out_dev:
        proc_net_remove("dev");
        goto out;
@@ -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 da07e9a..bbe99f8 100644 (file)
@@ -198,7 +198,7 @@ config IP6_NF_RAW
          and OUTPUT chains.
        
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 endmenu
 
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 c558f32..ea6211c 100644 (file)
@@ -100,7 +100,7 @@ config NF_CT_PROTO_SCTP
          tracking code will be able to do state tracking on SCTP connections.
 
          If you want to compile it as a module, say M here and read
-         Documentation/modules.txt.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NF_CONNTRACK_AMANDA
        tristate "Amanda backup protocol support"
@@ -279,8 +279,8 @@ config NETFILTER_XT_TARGET_CONNMARK
          affects the connection mark value rather than the packet mark value.
        
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  The module will be called
-         ipt_CONNMARK.o.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  The module will be called
+         ipt_CONNMARK.ko.  If unsure, say `N'.
 
 config NETFILTER_XT_TARGET_DSCP
        tristate '"DSCP" target support'
@@ -341,7 +341,7 @@ config NETFILTER_XT_TARGET_NOTRACK
          no protocol helpers for the selected packets).
        
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_TARGET_SECMARK
        tristate '"SECMARK" target support'
@@ -397,7 +397,7 @@ config NETFILTER_XT_MATCH_COMMENT
          comments in your iptables ruleset.
 
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_CONNBYTES
        tristate  '"connbytes" per-connection counter match support'
@@ -409,7 +409,7 @@ config NETFILTER_XT_MATCH_CONNBYTES
          number of bytes and/or packets for each direction within a connection.
 
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_CONNMARK
        tristate  '"connmark" connection mark match support'
@@ -421,8 +421,8 @@ config NETFILTER_XT_MATCH_CONNMARK
          connection mark value previously set for the session by `CONNMARK'. 
        
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  The module will be called
-         ipt_connmark.o.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  The module will be called
+         ipt_connmark.ko.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_CONNTRACK
        tristate '"conntrack" connection tracking match support'
@@ -446,7 +446,7 @@ config NETFILTER_XT_MATCH_DCCP
          and DCCP flags.
 
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_DSCP
        tristate '"DSCP" match support'
@@ -565,7 +565,7 @@ config NETFILTER_XT_MATCH_QUOTA
          byte counter.
 
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_REALM
        tristate  '"realm" match support'
@@ -579,7 +579,7 @@ config NETFILTER_XT_MATCH_REALM
          in tc world.
        
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_SCTP
        tristate  '"sctp" protocol match support (EXPERIMENTAL)'
@@ -590,7 +590,7 @@ config NETFILTER_XT_MATCH_SCTP
          and SCTP chunk types.
 
          If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>.  If unsure, say `N'.
+         <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
 config NETFILTER_XT_MATCH_STATE
        tristate '"state" match support'
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;
diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig
new file mode 100644 (file)
index 0000000..8b31759
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# RF switch subsystem configuration
+#
+menuconfig RFKILL
+       tristate "RF switch subsystem support"
+       help
+         Say Y here if you want to have control over RF switches
+         found on many WiFi, Bluetooth and IRDA cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rfkill.
+
+config RFKILL_INPUT
+       tristate "Input layer to RF switch connector"
+       depends on RFKILL && INPUT
+       help
+         Say Y here if you want kernel automatically toggle state
+         of RF switches on and off when user presses appropriate
+         button or a key on the keyboard. Without this module you
+         need a some kind of userspace application to control
+         state of the switches.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rfkill-input.
diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile
new file mode 100644 (file)
index 0000000..b38c430
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the RF switch subsystem.
+#
+
+obj-$(CONFIG_RFKILL)                   += rfkill.o
+obj-$(CONFIG_RFKILL_INPUT)             += rfkill-input.o
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
new file mode 100644 (file)
index 0000000..e5c840c
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Input layer to RF Kill interface connector
+ *
+ * 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/module.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/init.h>
+#include <linux/rfkill.h>
+
+MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
+MODULE_DESCRIPTION("Input layer to RF switch connector");
+MODULE_LICENSE("GPL");
+
+struct rfkill_task {
+       struct work_struct work;
+       enum rfkill_type type;
+       struct mutex mutex; /* ensures that task is serialized */
+       spinlock_t lock; /* for accessing last and desired state */
+       unsigned long last; /* last schedule */
+       enum rfkill_state desired_state; /* on/off */
+       enum rfkill_state current_state; /* on/off */
+};
+
+static void rfkill_task_handler(struct work_struct *work)
+{
+       struct rfkill_task *task = container_of(work, struct rfkill_task, work);
+       enum rfkill_state state;
+
+       mutex_lock(&task->mutex);
+
+       /*
+        * Use temp variable to fetch desired state to keep it
+        * consistent even if rfkill_schedule_toggle() runs in
+        * another thread or interrupts us.
+        */
+       state = task->desired_state;
+
+       if (state != task->current_state) {
+               rfkill_switch_all(task->type, state);
+               task->current_state = state;
+       }
+
+       mutex_unlock(&task->mutex);
+}
+
+static void rfkill_schedule_toggle(struct rfkill_task *task)
+{
+       unsigned int flags;
+
+       spin_lock_irqsave(&task->lock, flags);
+
+       if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
+               task->desired_state = !task->desired_state;
+               task->last = jiffies;
+               schedule_work(&task->work);
+       }
+
+       spin_unlock_irqrestore(&task->lock, flags);
+}
+
+#define DEFINE_RFKILL_TASK(n, t)                       \
+       struct rfkill_task n = {                        \
+               .work = __WORK_INITIALIZER(n.work,      \
+                               rfkill_task_handler),   \
+               .type = t,                              \
+               .mutex = __MUTEX_INITIALIZER(n.mutex),  \
+               .lock = __SPIN_LOCK_UNLOCKED(n.lock),   \
+               .desired_state = RFKILL_STATE_ON,       \
+               .current_state = RFKILL_STATE_ON,       \
+       }
+
+static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
+static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH);
+
+static void rfkill_event(struct input_handle *handle, unsigned int type,
+                       unsigned int code, int down)
+{
+       if (type == EV_KEY && down == 1) {
+               switch (code) {
+               case KEY_WLAN:
+                       rfkill_schedule_toggle(&rfkill_wlan);
+                       break;
+               case KEY_BLUETOOTH:
+                       rfkill_schedule_toggle(&rfkill_bt);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
+                         const struct input_device_id *id)
+{
+       struct input_handle *handle;
+       int error;
+
+       handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+       if (!handle)
+               return -ENOMEM;
+
+       handle->dev = dev;
+       handle->handler = handler;
+       handle->name = "rfkill";
+
+       error = input_register_handle(handle);
+       if (error)
+               goto err_free_handle;
+
+       error = input_open_device(handle);
+       if (error)
+               goto err_unregister_handle;
+
+       return 0;
+
+ err_unregister_handle:
+       input_unregister_handle(handle);
+ err_free_handle:
+       kfree(handle);
+       return error;
+}
+
+static void rfkill_disconnect(struct input_handle *handle)
+{
+       input_close_device(handle);
+       input_unregister_handle(handle);
+       kfree(handle);
+}
+
+static const struct input_device_id rfkill_ids[] = {
+       {
+               .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
+               .evbit = { BIT(EV_KEY) },
+               .keybit = { [LONG(KEY_WLAN)] = BIT(KEY_WLAN) },
+       },
+       {
+               .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
+               .evbit = { BIT(EV_KEY) },
+               .keybit = { [LONG(KEY_BLUETOOTH)] = BIT(KEY_BLUETOOTH) },
+       },
+       { }
+};
+
+static struct input_handler rfkill_handler = {
+       .event =        rfkill_event,
+       .connect =      rfkill_connect,
+       .disconnect =   rfkill_disconnect,
+       .name =         "rfkill",
+       .id_table =     rfkill_ids,
+};
+
+static int __init rfkill_handler_init(void)
+{
+       return input_register_handler(&rfkill_handler);
+}
+
+static void __exit rfkill_handler_exit(void)
+{
+       input_unregister_handler(&rfkill_handler);
+       flush_scheduled_work();
+}
+
+module_init(rfkill_handler_init);
+module_exit(rfkill_handler_exit);
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
new file mode 100644 (file)
index 0000000..a973603
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2006 Ivo van Doorn
+ * 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 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/workqueue.h>
+#include <linux/capability.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/rfkill.h>
+
+MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("RF switch support");
+MODULE_LICENSE("GPL");
+
+static LIST_HEAD(rfkill_list); /* list of registered rf switches */
+static DEFINE_MUTEX(rfkill_mutex);
+
+static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX];
+
+static int rfkill_toggle_radio(struct rfkill *rfkill,
+                               enum rfkill_state state)
+{
+       int retval;
+
+       retval = mutex_lock_interruptible(&rfkill->mutex);
+       if (retval)
+               return retval;
+
+       if (state != rfkill->state) {
+               retval = rfkill->toggle_radio(rfkill->data, state);
+               if (!retval)
+                       rfkill->state = state;
+       }
+
+       mutex_unlock(&rfkill->mutex);
+       return retval;
+}
+
+/**
+ * rfkill_switch_all - Toggle state of all switches of given type
+ * @type: type of interfaces to be affeceted
+ * @state: the new state
+ *
+ * This function toggles state of all switches of given type unless
+ * a specific switch is claimed by userspace in which case it is
+ * left alone.
+ */
+
+void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
+{
+       struct rfkill *rfkill;
+
+       mutex_lock(&rfkill_mutex);
+
+       rfkill_states[type] = state;
+
+       list_for_each_entry(rfkill, &rfkill_list, node) {
+               if (!rfkill->user_claim)
+                       rfkill_toggle_radio(rfkill, state);
+       }
+
+       mutex_unlock(&rfkill_mutex);
+}
+EXPORT_SYMBOL(rfkill_switch_all);
+
+static ssize_t rfkill_name_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+
+       return sprintf(buf, "%s\n", rfkill->name);
+}
+
+static ssize_t rfkill_type_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+       const char *type;
+
+       switch (rfkill->type) {
+       case RFKILL_TYPE_WLAN:
+               type = "wlan";
+               break;
+       case RFKILL_TYPE_BLUETOOTH:
+               type = "bluetooth";
+               break;
+       case RFKILL_TYPE_IRDA:
+               type = "irda";
+               break;
+       default:
+               BUG();
+       }
+
+       return sprintf(buf, "%s\n", type);
+}
+
+static ssize_t rfkill_state_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+
+       return sprintf(buf, "%d\n", rfkill->state);
+}
+
+static ssize_t rfkill_state_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+       unsigned int state = simple_strtoul(buf, NULL, 0);
+       int error;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       error = rfkill_toggle_radio(rfkill,
+                       state ? RFKILL_STATE_ON : RFKILL_STATE_OFF);
+       if (error)
+               return error;
+
+       return count;
+}
+
+static ssize_t rfkill_claim_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+
+       return sprintf(buf, "%d", rfkill->user_claim);
+}
+
+static ssize_t rfkill_claim_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+       bool claim = !!simple_strtoul(buf, NULL, 0);
+       int error;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       /*
+        * Take the global lock to make sure the kernel is not in
+        * the middle of rfkill_switch_all
+        */
+       error = mutex_lock_interruptible(&rfkill_mutex);
+       if (error)
+               return error;
+
+       if (rfkill->user_claim != claim) {
+               if (!claim)
+                       rfkill_toggle_radio(rfkill,
+                                           rfkill_states[rfkill->type]);
+               rfkill->user_claim = claim;
+       }
+
+       mutex_unlock(&rfkill_mutex);
+
+       return count;
+}
+
+static struct device_attribute rfkill_dev_attrs[] = {
+       __ATTR(name, S_IRUGO, rfkill_name_show, NULL),
+       __ATTR(type, S_IRUGO, rfkill_type_show, NULL),
+       __ATTR(state, S_IRUGO, rfkill_state_show, rfkill_state_store),
+       __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store),
+       __ATTR_NULL
+};
+
+static void rfkill_release(struct device *dev)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+
+       kfree(rfkill);
+       module_put(THIS_MODULE);
+}
+
+#ifdef CONFIG_PM
+static int rfkill_suspend(struct device *dev, pm_message_t state)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+
+       if (dev->power.power_state.event != state.event) {
+               if (state.event == PM_EVENT_SUSPEND) {
+                       mutex_lock(&rfkill->mutex);
+
+                       if (rfkill->state == RFKILL_STATE_ON)
+                               rfkill->toggle_radio(rfkill->data,
+                                                    RFKILL_STATE_OFF);
+
+                       mutex_unlock(&rfkill->mutex);
+               }
+
+               dev->power.power_state = state;
+       }
+
+       return 0;
+}
+
+static int rfkill_resume(struct device *dev)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+
+       if (dev->power.power_state.event != PM_EVENT_ON) {
+               mutex_lock(&rfkill->mutex);
+
+               if (rfkill->state == RFKILL_STATE_ON)
+                       rfkill->toggle_radio(rfkill->data, RFKILL_STATE_ON);
+
+               mutex_unlock(&rfkill->mutex);
+       }
+
+       dev->power.power_state = PMSG_ON;
+       return 0;
+}
+#else
+#define rfkill_suspend NULL
+#define rfkill_resume NULL
+#endif
+
+static struct class rfkill_class = {
+       .name           = "rfkill",
+       .dev_release    = rfkill_release,
+       .dev_attrs      = rfkill_dev_attrs,
+       .suspend        = rfkill_suspend,
+       .resume         = rfkill_resume,
+};
+
+static int rfkill_add_switch(struct rfkill *rfkill)
+{
+       int retval;
+
+       retval = mutex_lock_interruptible(&rfkill_mutex);
+       if (retval)
+               return retval;
+
+       retval = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]);
+       if (retval)
+               goto out;
+
+       list_add_tail(&rfkill->node, &rfkill_list);
+
+ out:
+       mutex_unlock(&rfkill_mutex);
+       return retval;
+}
+
+static void rfkill_remove_switch(struct rfkill *rfkill)
+{
+       mutex_lock(&rfkill_mutex);
+       list_del_init(&rfkill->node);
+       rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF);
+       mutex_unlock(&rfkill_mutex);
+}
+
+/**
+ * rfkill_allocate - allocate memory for rfkill structure.
+ * @parent: device that has rf switch on it
+ * @type: type of the switch (wlan, bluetooth, irda)
+ *
+ * This function should be called by the network driver when it needs
+ * rfkill structure. Once the structure is allocated the driver shoud
+ * finish its initialization by setting name, private data, enable_radio
+ * and disable_radio methods and then register it with rfkill_register().
+ * NOTE: If registration fails the structure shoudl be freed by calling
+ * rfkill_free() otherwise rfkill_unregister() should be used.
+ */
+struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type)
+{
+       struct rfkill *rfkill;
+       struct device *dev;
+
+       rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL);
+       if (rfkill)
+               return NULL;
+
+       mutex_init(&rfkill->mutex);
+       INIT_LIST_HEAD(&rfkill->node);
+       rfkill->type = type;
+
+       dev = &rfkill->dev;
+       dev->class = &rfkill_class;
+       dev->parent = parent;
+       device_initialize(dev);
+
+       __module_get(THIS_MODULE);
+
+       return rfkill;
+}
+EXPORT_SYMBOL(rfkill_allocate);
+
+/**
+ * rfkill_free - Mark rfkill structure for deletion
+ * @rfkill: rfkill structure to be destroyed
+ *
+ * Decrements reference count of rfkill structure so it is destoryed.
+ * Note that rfkill_free() should _not_ be called after rfkill_unregister().
+ */
+void rfkill_free(struct rfkill *rfkill)
+{
+       if (rfkill)
+               put_device(&rfkill->dev);
+}
+EXPORT_SYMBOL(rfkill_free);
+
+/**
+ * rfkill_register - Register a rfkill structure.
+ * @rfkill: rfkill structure to be registered
+ *
+ * This function should be called by the network driver when the rfkill
+ * structure needs to be registered. Immediately from registration the
+ * switch driver should be able to service calls to toggle_radio.
+ */
+int rfkill_register(struct rfkill *rfkill)
+{
+       static atomic_t rfkill_no = ATOMIC_INIT(0);
+       struct device *dev = &rfkill->dev;
+       int error;
+
+       if (!rfkill->toggle_radio)
+               return -EINVAL;
+
+       error = rfkill_add_switch(rfkill);
+       if (error)
+               return error;
+
+       snprintf(dev->bus_id, sizeof(dev->bus_id),
+                "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
+
+       error = device_add(dev);
+       if (error) {
+               rfkill_remove_switch(rfkill);
+               return error;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(rfkill_register);
+
+/**
+ * rfkill_unregister - Uegister a rfkill structure.
+ * @rfkill: rfkill structure to be unregistered
+ *
+ * This function should be called by the network driver during device
+ * teardown to destroy rfkill structure. Note that rfkill_free() should
+ * _not_ be called after rfkill_unregister().
+ */
+void rfkill_unregister(struct rfkill *rfkill)
+{
+       device_del(&rfkill->dev);
+       rfkill_remove_switch(rfkill);
+       put_device(&rfkill->dev);
+}
+EXPORT_SYMBOL(rfkill_unregister);
+
+/*
+ * Rfkill module initialization/deinitialization.
+ */
+static int __init rfkill_init(void)
+{
+       int error;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(rfkill_states); i++)
+               rfkill_states[i] = RFKILL_STATE_ON;
+
+       error = class_register(&rfkill_class);
+       if (error) {
+               printk(KERN_ERR "rfkill: unable to register rfkill class\n");
+               return error;
+       }
+
+       return 0;
+}
+
+static void __exit rfkill_exit(void)
+{
+       class_unregister(&rfkill_class);
+}
+
+module_init(rfkill_init);
+module_exit(rfkill_exit);
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 1ad62c0..759825b 100644 (file)
@@ -261,8 +261,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct socket_alloc *ei = (struct socket_alloc *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR))
-           == SLAB_CTOR_CONSTRUCTOR)
+       if (flags & SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
 
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,
-};
index 9b9ea50..ad39b47 100644 (file)
@@ -828,8 +828,7 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct rpc_inode *rpci = (struct rpc_inode *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+       if (flags & SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&rpci->vfs_inode);
                rpci->private = NULL;
                rpci->nreaders = 0;
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 3891cc0..f9e367d 100644 (file)
@@ -18,7 +18,7 @@ config TIPC
          This protocol support is also available as a module ( = code which
          can be inserted in and removed from the running kernel whenever you
          want). The module will be called tipc. If you want to compile it
-         as a module, say M here and read <file:Documentation/modules.txt>.
+         as a module, say M here and read <file:Documentation/kbuild/modules.txt>.
 
          If in doubt, say N.
 
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 e2ad2dc..a525112 100644 (file)
@@ -131,13 +131,13 @@ $(multi-objs-y:.o=.lst) : modname = $(modname-multi)
 quiet_cmd_cc_s_c = CC $(quiet_modtag)  $@
 cmd_cc_s_c       = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
 
-%.s: %.c FORCE
+$(obj)/%.s: $(src)/%.c FORCE
        $(call if_changed_dep,cc_s_c)
 
 quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
 cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $<
 
-%.i: %.c FORCE
+$(obj)/%.i: $(src)/%.c FORCE
        $(call if_changed_dep,cc_i_c)
 
 quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
@@ -146,7 +146,7 @@ cmd_cc_symtypes_c      = \
                | $(GENKSYMS) -T $@ >/dev/null;                         \
                test -s $@ || rm -f $@
 
-%.symtypes : %.c FORCE
+$(obj)/%.symtypes : $(src)/%.c FORCE
        $(call if_changed_dep,cc_symtypes_c)
 
 # C (.c) files
@@ -198,14 +198,13 @@ define rule_cc_o_c
 endef
 
 # Built-in and composite module parts
-
-%.o: %.c FORCE
+$(obj)/%.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
-$(single-used-m): %.o: %.c FORCE
+$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
        @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
@@ -215,7 +214,7 @@ quiet_cmd_cc_lst_c = MKLST   $@
                     $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
                                     System.map $(OBJDUMP) > $@
 
-%.lst: %.c FORCE
+$(obj)/%.lst: $(src)/%.c FORCE
        $(call if_changed_dep,cc_lst_c)
 
 # Compile assembler sources (.S)
@@ -229,13 +228,13 @@ $(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
 quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
 cmd_as_s_S       = $(CPP) $(a_flags)   -o $@ $< 
 
-%.s: %.S FORCE
+$(obj)/%.s: $(src)/%.S FORCE
        $(call if_changed_dep,as_s_S)
 
 quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
 cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 
-%.o: %.S FORCE
+$(obj)/%.o: $(src)/%.S FORCE
        $(call if_changed_dep,as_o_S)
 
 targets += $(real-objs-y) $(real-objs-m) $(lib-y)
@@ -246,7 +245,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(always)
 quiet_cmd_cpp_lds_S = LDS     $@
       cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
 
-%.lds: %.lds.S FORCE
+$(obj)/%.lds: $(src)/%.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
 # Build the compiled-in targets
index 575afbe..6943a7a 100644 (file)
@@ -114,7 +114,7 @@ hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)
 quiet_cmd_host-csingle         = HOSTCC  $@
       cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
                $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-csingle): %: %.c FORCE
+$(host-csingle): $(obj)/%: $(src)/%.c FORCE
        $(call if_changed_dep,host-csingle)
 
 # Link an executable based on list of .o files, all plain c
@@ -123,14 +123,14 @@ quiet_cmd_host-cmulti     = HOSTLD  $@
       cmd_host-cmulti  = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
                          $(addprefix $(obj)/,$($(@F)-objs)) \
                          $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
+$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE
        $(call if_changed,host-cmulti)
 
 # Create .o file from a single .c file
 # host-cobjs -> .o
 quiet_cmd_host-cobjs   = HOSTCC  $@
       cmd_host-cobjs   = $(HOSTCC) $(hostc_flags) -c -o $@ $<
-$(host-cobjs): %.o: %.c FORCE
+$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE
        $(call if_changed_dep,host-cobjs)
 
 # Link an executable based on list of .o files, a mixture of .c and .cc
@@ -140,20 +140,20 @@ quiet_cmd_host-cxxmulti   = HOSTLD  $@
                          $(foreach o,objs cxxobjs,\
                          $(addprefix $(obj)/,$($(@F)-$(o)))) \
                          $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
+$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
        $(call if_changed,host-cxxmulti)
 
 # Create .o file from a single .cc (C++) file
 quiet_cmd_host-cxxobjs = HOSTCXX $@
       cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
-$(host-cxxobjs): %.o: %.cc FORCE
+$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
        $(call if_changed_dep,host-cxxobjs)
 
 # Compile .c file, create position independent .o file
 # host-cshobjs -> .o
 quiet_cmd_host-cshobjs = HOSTCC  -fPIC $@
       cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
-$(host-cshobjs): %.o: %.c FORCE
+$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE
        $(call if_changed_dep,host-cshobjs)
 
 # Link a shared library, based on position independent .o files
@@ -162,7 +162,7 @@ quiet_cmd_host-cshlib       = HOSTLLD -shared $@
       cmd_host-cshlib  = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
                          $(addprefix $(obj)/,$($(@F:.so=-objs))) \
                          $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cshlib): %: $(host-cshobjs) FORCE
+$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE
        $(call if_changed,host-cshlib)
 
 targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
index 65e0a79..d5bbbcc 100644 (file)
@@ -63,16 +63,16 @@ quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
        $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
        $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
        $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
-       $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
-       $(wildcard vmlinux) $(filter-out FORCE,$^)
+       $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
 
 PHONY += __modpost
 __modpost: $(modules:.ko=.o) FORCE
-       $(call cmd,modpost)
+       $(call cmd,modpost) $(wildcard vmlinux) $(filter-out FORCE,$^)
 
 quiet_cmd_kernel-mod = MODPOST $@
-      cmd_kernel-mod = $(cmd_modpost)
+      cmd_kernel-mod = $(cmd_modpost) $(KBUILD_VMLINUX_OBJS)
 
+PHONY += vmlinux
 vmlinux: FORCE
        $(call cmd,kernel-mod)
 
index 6bc7e7c..8912c0f 100644 (file)
@@ -249,6 +249,8 @@ void parse_config_file(char *map, size_t len)
        found:
                if (!memcmp(q - 7, "_MODULE", 7))
                        q -= 7;
+               if( (q-p-7) < 0 )
+                       continue;
                use_config(p+7, q-p-7);
        }
 }
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
new file mode 100755 (executable)
index 0000000..f98171f
--- /dev/null
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# Check if current architecture are missing any function calls compared
+# to i386.
+# i386 define a number of legacy system calls that are i386 specific
+# and listed below so they are ignored.
+#
+# Usage:
+# syscallchk gcc gcc-options
+#
+
+ignore_list() {
+cat << EOF
+#include <asm/types.h>
+#include <asm/unistd.h>
+
+/* System calls for 32-bit kernels only */
+#if BITS_PER_LONG == 64
+#define __IGNORE_sendfile64
+#define __IGNORE_ftruncate64
+#define __IGNORE_truncate64
+#define __IGNORE_stat64
+#define __IGNORE_lstat64
+#define __IGNORE_fstat64
+#define __IGNORE_fcntl64
+#define __IGNORE_fadvise64_64
+#define __IGNORE_fstatat64
+#define __IGNORE_fstatfs64
+#define __IGNORE_statfs64
+#endif
+
+/* i386-specific or historical system calls */
+#define __IGNORE_break
+#define __IGNORE_stty
+#define __IGNORE_gtty
+#define __IGNORE_ftime
+#define __IGNORE_prof
+#define __IGNORE_lock
+#define __IGNORE_mpx
+#define __IGNORE_ulimit
+#define __IGNORE_profil
+#define __IGNORE_ioperm
+#define __IGNORE_iopl
+#define __IGNORE_idle
+#define __IGNORE_modify_ldt
+#define __IGNORE_ugetrlimit
+#define __IGNORE_mmap2
+#define __IGNORE_vm86
+#define __IGNORE_vm86old
+#define __IGNORE_set_thread_area
+#define __IGNORE_get_thread_area
+#define __IGNORE_madvise1
+#define __IGNORE_oldstat
+#define __IGNORE_oldfstat
+#define __IGNORE_oldlstat
+#define __IGNORE_oldolduname
+#define __IGNORE_olduname
+#define __IGNORE_umount2
+#define __IGNORE_umount
+#define __IGNORE_waitpid
+#define __IGNORE_stime
+#define __IGNORE_nice
+#define __IGNORE_signal
+#define __IGNORE_sigaction
+#define __IGNORE_sgetmask
+#define __IGNORE_sigsuspend
+#define __IGNORE_sigpending
+#define __IGNORE_ssetmask
+#define __IGNORE_readdir
+#define __IGNORE_socketcall
+#define __IGNORE_ipc
+#define __IGNORE_sigreturn
+#define __IGNORE_sigprocmask
+#define __IGNORE_bdflush
+#define __IGNORE__llseek
+#define __IGNORE__newselect
+#define __IGNORE_create_module
+#define __IGNORE_delete_module
+#define __IGNORE_query_module
+#define __IGNORE_get_kernel_syms
+/* ... including the "new" 32-bit uid syscalls */
+#define __IGNORE_lchown32
+#define __IGNORE_getuid32
+#define __IGNORE_getgid32
+#define __IGNORE_geteuid32
+#define __IGNORE_getegid32
+#define __IGNORE_setreuid32
+#define __IGNORE_setregid32
+#define __IGNORE_getgroups32
+#define __IGNORE_setgroups32
+#define __IGNORE_fchown32
+#define __IGNORE_setresuid32
+#define __IGNORE_getresuid32
+#define __IGNORE_setresgid32
+#define __IGNORE_getresgid32
+#define __IGNORE_chown32
+#define __IGNORE_setuid32
+#define __IGNORE_setgid32
+#define __IGNORE_setfsuid32
+#define __IGNORE_setfsgid32
+
+/* Unmerged syscalls for AFS, STREAMS, etc. */
+#define __IGNORE_afs_syscall
+#define __IGNORE_getpmsg
+#define __IGNORE_putpmsg
+#define __IGNORE_vserver
+EOF
+}
+
+syscall_list() {
+sed -n -e '/^\#define/ { s/[^_]*__NR_\([^[:space:]]*\).*/\
+\#if !defined \(__NR_\1\) \&\& !defined \(__IGNORE_\1\)\
+\#warning syscall \1 not implemented\
+\#endif/p }' $1
+}
+
+(ignore_list && syscall_list ${srctree}/include/asm-i386/unistd.h) | \
+$* -E -x c - > /dev/null
diff --git a/scripts/cleanfile b/scripts/cleanfile
new file mode 100755 (executable)
index 0000000..f1ba8aa
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/perl -w
+#
+# Clean a text file -- or directory of text files -- of stealth whitespace.
+# WARNING: this can be a highly destructive operation.  Use with caution.
+#
+
+use bytes;
+use File::Basename;
+
+#
+# Clean up space-tab sequences, either by removing spaces or
+# replacing them with tabs.
+sub clean_space_tabs($)
+{
+    no bytes;                  # Tab alignment depends on characters
+
+    my($li) = @_;
+    my($lo) = '';
+    my $pos = 0;
+    my $nsp = 0;
+    my($i, $c);
+
+    for ($i = 0; $i < length($li); $i++) {
+       $c = substr($li, $i, 1);
+       if ($c eq "\t") {
+           my $npos = ($pos+$nsp+8) & ~7;
+           my $ntab = ($npos >> 3) - ($pos >> 3);
+           $lo .= "\t" x $ntab;
+           $pos = $npos;
+           $nsp = 0;
+       } elsif ($c eq "\n" || $c eq "\r") {
+           $lo .= " " x $nsp;
+           $pos += $nsp;
+           $nsp = 0;
+           $lo .= $c;
+           $pos = 0;
+       } elsif ($c eq " ") {
+           $nsp++;
+       } else {
+           $lo .= " " x $nsp;
+           $pos += $nsp;
+           $nsp = 0;
+           $lo .= $c;
+           $pos++;
+       }
+    }
+    $lo .= " " x $nsp;
+    return $lo;
+}
+
+$name = basename($0);
+
+foreach $f ( @ARGV ) {
+    print STDERR "$name: $f\n";
+
+    if (! -f $f) {
+       print STDERR "$f: not a file\n";
+       next;
+    }
+
+    if (!open(FILE, '+<', $f)) {
+       print STDERR "$name: Cannot open file: $f: $!\n";
+       next;
+    }
+
+    binmode FILE;
+
+    # First, verify that it is not a binary file; consider any file
+    # with a zero byte to be a binary file.  Is there any better, or
+    # additional, heuristic that should be applied?
+    $is_binary = 0;
+
+    while (read(FILE, $data, 65536) > 0) {
+       if ($data =~ /\0/) {
+           $is_binary = 1;
+           last;
+       }
+    }
+
+    if ($is_binary) {
+       print STDERR "$name: $f: binary file\n";
+       next;
+    }
+
+    seek(FILE, 0, 0);
+
+    $in_bytes = 0;
+    $out_bytes = 0;
+    $blank_bytes = 0;
+
+    @blanks = ();
+    @lines  = ();
+
+    while ( defined($line = <FILE>) ) {
+       $in_bytes += length($line);
+       $line =~ s/[ \t\r]*$//;         # Remove trailing spaces
+       $line = clean_space_tabs($line);
+
+       if ( $line eq "\n" ) {
+           push(@blanks, $line);
+           $blank_bytes += length($line);
+       } else {
+           push(@lines, @blanks);
+           $out_bytes += $blank_bytes;
+           push(@lines, $line);
+           $out_bytes += length($line);
+           @blanks = ();
+           $blank_bytes = 0;
+       }
+    }
+
+    # Any blanks at the end of the file are discarded
+
+    if ($in_bytes != $out_bytes) {
+       # Only write to the file if changed
+       seek(FILE, 0, 0);
+       print FILE @lines;
+
+       if ( !defined($where = tell(FILE)) ||
+            !truncate(FILE, $where) ) {
+           die "$name: Failed to truncate modified file: $f: $!\n";
+       }
+    }
+
+    close(FILE);
+}
diff --git a/scripts/cleanpatch b/scripts/cleanpatch
new file mode 100755 (executable)
index 0000000..a53f987
--- /dev/null
@@ -0,0 +1,206 @@
+#!/usr/bin/perl -w
+#
+# Clean a patch file -- or directory of patch files -- of stealth whitespace.
+# WARNING: this can be a highly destructive operation.  Use with caution.
+#
+
+use bytes;
+use File::Basename;
+
+#
+# Clean up space-tab sequences, either by removing spaces or
+# replacing them with tabs.
+sub clean_space_tabs($)
+{
+    no bytes;                  # Tab alignment depends on characters
+
+    my($li) = @_;
+    my($lo) = '';
+    my $pos = 0;
+    my $nsp = 0;
+    my($i, $c);
+
+    for ($i = 0; $i < length($li); $i++) {
+       $c = substr($li, $i, 1);
+       if ($c eq "\t") {
+           my $npos = ($pos+$nsp+8) & ~7;
+           my $ntab = ($npos >> 3) - ($pos >> 3);
+           $lo .= "\t" x $ntab;
+           $pos = $npos;
+           $nsp = 0;
+       } elsif ($c eq "\n" || $c eq "\r") {
+           $lo .= " " x $nsp;
+           $pos += $nsp;
+           $nsp = 0;
+           $lo .= $c;
+           $pos = 0;
+       } elsif ($c eq " ") {
+           $nsp++;
+       } else {
+           $lo .= " " x $nsp;
+           $pos += $nsp;
+           $nsp = 0;
+           $lo .= $c;
+           $pos++;
+       }
+    }
+    $lo .= " " x $nsp;
+    return $lo;
+}
+
+$name = basename($0);
+
+foreach $f ( @ARGV ) {
+    print STDERR "$name: $f\n";
+
+    if (! -f $f) {
+       print STDERR "$f: not a file\n";
+       next;
+    }
+
+    if (!open(FILE, '+<', $f)) {
+       print STDERR "$name: Cannot open file: $f: $!\n";
+       next;
+    }
+
+    binmode FILE;
+
+    # First, verify that it is not a binary file; consider any file
+    # with a zero byte to be a binary file.  Is there any better, or
+    # additional, heuristic that should be applied?
+    $is_binary = 0;
+
+    while (read(FILE, $data, 65536) > 0) {
+       if ($data =~ /\0/) {
+           $is_binary = 1;
+           last;
+       }
+    }
+
+    if ($is_binary) {
+       print STDERR "$name: $f: binary file\n";
+       next;
+    }
+
+    seek(FILE, 0, 0);
+
+    $in_bytes = 0;
+    $out_bytes = 0;
+
+    @lines  = ();
+
+    $in_hunk = 0;
+    $err = 0;
+
+    while ( defined($line = <FILE>) ) {
+       $in_bytes += length($line);
+
+       if (!$in_hunk) {
+           if ($line =~ /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@/) {
+               $minus_lines = $2;
+               $plus_lines = $4;
+               if ($minus_lines || $plus_lines) {
+                   $in_hunk = 1;
+                   @hunk_lines = ($line);
+               }
+           } else {
+               push(@lines, $line);
+               $out_bytes += length($line);
+           }
+       } else {
+           # We're in a hunk
+
+           if ($line =~ /^\+/) {
+               $plus_lines--;
+
+               $text = substr($line, 1);
+               $text =~ s/[ \t\r]*$//;         # Remove trailing spaces
+               $text = clean_space_tabs($text);
+
+               push(@hunk_lines, '+'.$text);
+           } elsif ($line =~ /^\-/) {
+               $minus_lines--;
+               push(@hunk_lines, $line);
+           } elsif ($line =~ /^ /) {
+               $plus_lines--;
+               $minus_lines--;
+               push(@hunk_lines, $line);
+           } else {
+               print STDERR "$name: $f: malformed patch\n";
+               $err = 1;
+               last;
+           }
+
+           if ($plus_lines < 0 || $minus_lines < 0) {
+               print STDERR "$name: $f: malformed patch\n";
+               $err = 1;
+               last;
+           } elsif ($plus_lines == 0 && $minus_lines == 0) {
+               # End of a hunk.  Process this hunk.
+               my $i;
+               my $l;
+               my @h = ();
+               my $adj = 0;
+               my $done = 0;
+
+               for ($i = scalar(@hunk_lines)-1; $i > 0; $i--) {
+                   $l = $hunk_lines[$i];
+                   if (!$done && $l eq "+\n") {
+                       $adj++; # Skip this line
+                   } elsif ($l =~ /^[ +]/) {
+                       $done = 1;
+                       unshift(@h, $l);
+                   } else {
+                       unshift(@h, $l);
+                   }
+               }
+
+               $l = $hunk_lines[0];  # Hunk header
+               undef @hunk_lines;    # Free memory
+
+               if ($adj) {
+                   die unless
+                       ($l =~ /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@(.*)$/);
+                   my $mstart = $1;
+                   my $mlin = $2;
+                   my $pstart = $3;
+                   my $plin = $4;
+                   my $tail = $5; # doesn't include the final newline
+
+                   $l = sprintf("@@ -%d,%d +%d,%d @@%s\n",
+                                $mstart, $mlin, $pstart, $plin-$adj,
+                                $tail);
+               }
+               unshift(@h, $l);
+
+               # Transfer to the output array
+               foreach $l (@h) {
+                   $out_bytes += length($l);
+                   push(@lines, $l);
+               }
+
+               $in_hunk = 0;
+           }
+       }
+    }
+
+    if ($in_hunk) {
+       print STDERR "$name: $f: malformed patch\n";
+       $err = 1;
+    }
+
+    if (!$err) {
+       if ($in_bytes != $out_bytes) {
+           # Only write to the file if changed
+           seek(FILE, 0, 0);
+           print FILE @lines;
+
+           if ( !defined($where = tell(FILE)) ||
+                !truncate(FILE, $where) ) {
+               die "$name: Failed to truncate modified file: $f: $!\n";
+           }
+       }
+    }
+
+    close(FILE);
+}
index 43f75d6..683eb12 100644 (file)
@@ -171,7 +171,7 @@ dir_filelist() {
        ${dep_list}header "$1"
 
        srcdir=$(echo "$1" | sed -e 's://*:/:g')
-       dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
+       dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n")
 
        # If $dirlist is only one line, then the directory is empty
        if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
@@ -191,9 +191,10 @@ input_file() {
        source="$1"
        if [ -f "$1" ]; then
                ${dep_list}header "$1"
-               is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
+               is_cpio="$(echo "$1" | sed 's/^.*\.cpio\(\..*\)\?/cpio/')"
                if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
                        cpio_file=$1
+                       echo "$1" | grep -q '^.*\.cpio\..*' && is_cpio_compressed="compressed"
                        [ ! -z ${dep_list} ] && echo "$1"
                        return 0
                fi
@@ -223,6 +224,7 @@ cpio_file=
 cpio_list=
 output="/dev/stdout"
 output_file=""
+is_cpio_compressed=
 
 arg="$1"
 case "$arg" in
@@ -282,7 +284,11 @@ if [ ! -z ${output_file} ]; then
                cpio_tfile=${cpio_file}
        fi
        rm ${cpio_list}
-       cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
+       if [ "${is_cpio_compressed}" = "compressed" ]; then
+               cat ${cpio_tfile} > ${output_file}
+       else
+               cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
+       fi
        [ -z ${cpio_file} ] && rm ${cpio_tfile}
 fi
 exit 0
index b038182..511023b 100644 (file)
@@ -516,7 +516,8 @@ int main(int argc, char **argv)
                        genksyms_usage();
                        return 1;
                }
-       if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0))
+       if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0)
+           || (strcmp(arch, "blackfin") == 0))
                mod_prefix = "_";
        {
                extern int yydebug;
index 7e7e147..fb2bb30 100644 (file)
@@ -140,6 +140,7 @@ endif
 
 clean-files    := lkc_defs.h qconf.moc .tmp_qtcheck \
                   .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
+clean-files     += mconf qconf gconf
 
 # Needed for systems without gettext
 KBUILD_HAVE_NLS := $(shell \
@@ -183,8 +184,8 @@ $(obj)/.tmp_qtcheck:
          done; \
          if [ -z "$$dir" ]; then \
            echo "*"; \
-           echo "* Unable to find the QT installation. Please make sure that"; \
-           echo "* the QT development package is correctly installed and"; \
+           echo "* Unable to find the QT3 installation. Please make sure that"; \
+           echo "* the QT3 development package is correctly installed and"; \
            echo "* either install pkg-config or set the QTDIR environment"; \
            echo "* variable to the correct location."; \
            echo "*"; \
index 124b341..1199baf 100644 (file)
@@ -558,6 +558,7 @@ int main(int ac, char **av)
                if (stat(".config", &tmpstat)) {
                        printf(_("***\n"
                                "*** You have not yet configured your kernel!\n"
+                               "*** (missing kernel .config file)\n"
                                "***\n"
                                "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
                                "*** \"make menuconfig\" or \"make xconfig\").\n"
index 800f8c7..0fdc904 100644 (file)
@@ -2264,7 +2264,7 @@ FILE *zconf_fopen(const char *name)
        FILE *f;
 
        f = fopen(name, "r");
-       if (!f && name[0] != '/') {
+       if (!f && name != NULL && name[0] != '/') {
                env = getenv(SRCTREE);
                if (env) {
                        sprintf(fullname, "%s/%s", env, name);
index 9b2706a..8a07ee4 100644 (file)
@@ -64,6 +64,7 @@ int zconf_lineno(void);
 char *zconf_curname(void);
 
 /* confdata.c */
+const char *conf_get_configname(void);
 char *conf_get_default_confname(void);
 void sym_set_change_count(int count);
 void sym_add_change_count(int count);
index fd695e1..7e17eba 100644 (file)
@@ -188,6 +188,7 @@ int on_key_esc(WINDOW *win);
 int on_key_resize(void);
 
 void init_dialog(const char *backtitle);
+void set_dialog_backtitle(const char *backtitle);
 void reset_dialog(void);
 void end_dialog(void);
 void attr_clear(WINDOW * win, int height, int width, chtype attr);
index d54440f..a1bddef 100644 (file)
@@ -272,6 +272,11 @@ void init_dialog(const char *backtitle)
        color_setup(getenv("MENUCONFIG_COLOR"));
 }
 
+void set_dialog_backtitle(const char *backtitle)
+{
+       dlg.backtitle = backtitle;
+}
+
 void reset_dialog(void)
 {
        initscr();              /* Init curses */
@@ -336,7 +341,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
                newl = 1;
                word = tempstr;
                while (word && *word) {
-                       sp = index(word, ' ');
+                       sp = strchr(word, ' ');
                        if (sp)
                                *sp++ = 0;
 
@@ -348,7 +353,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
                        if (wlen > room ||
                            (newl && wlen < 4 && sp
                             && wlen + 1 + strlen(sp) > room
-                            && (!(sp2 = index(sp, ' '))
+                            && (!(sp2 = strchr(sp, ' '))
                                 || wlen + 1 + (sp2 - sp) > room))) {
                                cur_y++;
                                cur_x = x;
index 3f9a132..d0e4fa5 100644 (file)
@@ -26,7 +26,6 @@
 #include "lkc.h"
 #include "lxdialog/dialog.h"
 
-static char menu_backtitle[128];
 static const char mconf_readme[] = N_(
 "Overview\n"
 "--------\n"
@@ -271,7 +270,6 @@ search_help[] = N_(
        "          USB$ => find all CONFIG_ symbols ending with USB\n"
        "\n");
 
-static char filename[PATH_MAX+1] = ".config";
 static int indent;
 static struct termios ios_org;
 static int rows = 0, cols = 0;
@@ -395,6 +393,28 @@ static struct gstr get_relations_str(struct symbol **sym_arr)
        return res;
 }
 
+static char filename[PATH_MAX+1];
+static void set_config_filename(const char *config_filename)
+{
+       static char menu_backtitle[PATH_MAX+128];
+       int size;
+       struct symbol *sym;
+
+       sym = sym_lookup("KERNELVERSION", 0);
+       sym_calc_value(sym);
+       size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+                       _("%s - Linux Kernel v%s Configuration"),
+                       config_filename, sym_get_string_value(sym));
+       if (size >= sizeof(menu_backtitle))
+               menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+       set_dialog_backtitle(menu_backtitle);
+
+       size = snprintf(filename, sizeof(filename), "%s", config_filename);
+       if (size >= sizeof(filename))
+               filename[sizeof(filename)-1] = '\0';
+}
+
+
 static void search_conf(void)
 {
        struct symbol **sym_arr;
@@ -816,8 +836,10 @@ static void conf_load(void)
                case 0:
                        if (!dialog_input_result[0])
                                return;
-                       if (!conf_read(dialog_input_result))
+                       if (!conf_read(dialog_input_result)) {
+                               set_config_filename(dialog_input_result);
                                return;
+                       }
                        show_textbox(NULL, _("File does not exist!"), 5, 38);
                        break;
                case 1:
@@ -840,8 +862,10 @@ static void conf_save(void)
                case 0:
                        if (!dialog_input_result[0])
                                return;
-                       if (!conf_write(dialog_input_result))
+                       if (!conf_write(dialog_input_result)) {
+                               set_config_filename(dialog_input_result);
                                return;
+                       }
                        show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60);
                        break;
                case 1:
@@ -860,7 +884,6 @@ static void conf_cleanup(void)
 
 int main(int ac, char **av)
 {
-       struct symbol *sym;
        char *mode;
        int res;
 
@@ -871,11 +894,6 @@ int main(int ac, char **av)
        conf_parse(av[1]);
        conf_read(NULL);
 
-       sym = sym_lookup("KERNELVERSION", 0);
-       sym_calc_value(sym);
-       sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"),
-               sym_get_string_value(sym));
-
        mode = getenv("MENUCONFIG_MODE");
        if (mode) {
                if (!strcasecmp(mode, "single_menu"))
@@ -886,7 +904,8 @@ int main(int ac, char **av)
        atexit(conf_cleanup);
        init_wsize();
        reset_dialog();
-       init_dialog(menu_backtitle);
+       init_dialog(NULL);
+       set_config_filename(conf_get_configname());
        do {
                conf(&rootmenu);
                dialog_clear();
@@ -903,7 +922,7 @@ int main(int ac, char **av)
 
        switch (res) {
        case 0:
-               if (conf_write(NULL)) {
+               if (conf_write(filename)) {
                        fprintf(stderr, _("\n\n"
                                "Error during writing of the kernel configuration.\n"
                                "Your kernel configuration changes were NOT saved."
index c86c27f..f14aeac 100644 (file)
@@ -203,7 +203,7 @@ void sym_check_prop(struct symbol *sym)
                        else if (sym2->type == S_UNKNOWN)
                                prop_warn(prop,
                                    "'select' used by config symbol '%s' "
-                                   "refer to undefined symbol '%s'",
+                                   "refers to undefined symbol '%s'",
                                    sym->name, sym2->name);
                        else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
                                prop_warn(prop,
index 512c2f5..f2a23a9 100644 (file)
@@ -1182,7 +1182,7 @@ void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
        Parent::contentsContextMenuEvent(e);
 }
 
-ConfigSearchWindow::ConfigSearchWindow(QWidget* parent, const char *name)
+ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
        : Parent(parent, name), result(NULL)
 {
        setCaption("Search Config");
@@ -1206,6 +1206,9 @@ ConfigSearchWindow::ConfigSearchWindow(QWidget* parent, const char *name)
        info = new ConfigInfoView(split, name);
        connect(list->list, SIGNAL(menuChanged(struct menu *)),
                info, SLOT(setInfo(struct menu *)));
+       connect(list->list, SIGNAL(menuChanged(struct menu *)),
+               parent, SLOT(setMenuLink(struct menu *)));
+
        layout1->addWidget(split);
 
        if (name) {
index 6fc1c5f..b3b5657 100644 (file)
@@ -279,7 +279,7 @@ class ConfigSearchWindow : public QDialog {
        Q_OBJECT
        typedef class QDialog Parent;
 public:
-       ConfigSearchWindow(QWidget* parent, const char *name = 0);
+       ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0);
 
 public slots:
        void saveSettings(void);
index 8f06c47..c35dcc5 100644 (file)
@@ -786,13 +786,15 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
        return NULL;
 }
 
+/* return NULL when dependencies are OK */
 struct symbol *sym_check_deps(struct symbol *sym)
 {
        struct symbol *sym2;
        struct property *prop;
 
        if (sym->flags & SYMBOL_CHECK) {
-               printf("Warning! Found recursive dependency: %s", sym->name);
+               fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
+                       sym->prop->file->name, sym->prop->lineno, sym->name);
                return sym;
        }
        if (sym->flags & SYMBOL_CHECKED)
@@ -816,13 +818,8 @@ struct symbol *sym_check_deps(struct symbol *sym)
                        goto out;
        }
 out:
-       if (sym2) {
-               printf(" %s", sym->name);
-               if (sym2 == sym) {
-                       printf("\n");
-                       sym2 = NULL;
-               }
-       }
+       if (sym2)
+               fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": "");
        sym->flags &= ~SYMBOL_CHECK;
        return sym2;
 }
index cfa4607..187d38c 100644 (file)
@@ -265,7 +265,7 @@ FILE *zconf_fopen(const char *name)
        FILE *f;
 
        f = fopen(name, "r");
-       if (!f && name[0] != '/') {
+       if (!f && name != NULL && name[0] != '/') {
                env = getenv(SRCTREE);
                if (env) {
                        sprintf(fullname, "%s/%s", env, name);
index d777fe8..9a06b67 100644 (file)
@@ -2132,9 +2132,11 @@ void conf_parse(const char *name)
        }
        menu_finalize(&rootmenu);
        for_all_symbols(i, sym) {
-               sym_check_deps(sym);
+               if (sym_check_deps(sym))
+                       zconfnerrs++;
         }
-
+       if (zconfnerrs)
+               exit(1);
        sym_set_change_count(1);
 }
 
index 04a5864..92eb02b 100644 (file)
@@ -501,9 +501,11 @@ void conf_parse(const char *name)
        }
        menu_finalize(&rootmenu);
        for_all_symbols(i, sym) {
-               sym_check_deps(sym);
+               if (sym_check_deps(sym))
+                       zconfnerrs++;
         }
-
+       if (zconfnerrs)
+               exit(1);
        sym_set_change_count(1);
 }
 
index 82d0af4..a8740df 100755 (executable)
@@ -18,19 +18,32 @@ fi
 # Do not expand names
 set -f
 
-if [ -r .version ]; then
-  VERSION=`cat .version`
+# Fix the language to get consistent output
+LC_ALL=C
+export LC_ALL
+
+if [ -z "$KBUILD_BUILD_VERSION" ]; then
+       if [ -r .version ]; then
+               VERSION=`cat .version`
+       else
+               VERSION=0
+               echo 0 > .version
+       fi
 else
-  VERSION=0
-  echo 0 > .version
+       VERSION=$KBUILD_BUILD_VERSION
 fi
 
+if [ -z "$KBUILD_BUILD_TIMESTAMP" ]; then
+       TIMESTAMP=`date`
+else
+       TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
+fi
 
 UTS_VERSION="#$VERSION"
 CONFIG_FLAGS=""
 if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
 if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
-UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS `LC_ALL=C LANG=C date`"
+UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
 
 # Truncate to maximum length
 
@@ -46,7 +59,7 @@ UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
 
   echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
 
-  echo \#define LINUX_COMPILE_TIME \"`LC_ALL=C LANG=C date +%T`\"
+  echo \#define LINUX_COMPILE_TIME \"`date +%T`\"
   echo \#define LINUX_COMPILE_BY \"`whoami`\"
   echo \#define LINUX_COMPILE_HOST \"`hostname | $UTS_TRUNCATE`\"
 
@@ -58,7 +71,7 @@ UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
     echo \#define LINUX_COMPILE_DOMAIN
   fi
 
-  echo \#define LINUX_COMPILER \"`LC_ALL=C LANG=C $CC -v 2>&1 | tail -n 1`\"
+  echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
 ) > .tmpcompile
 
 # Only replace the real compile.h if the new one is different,
index 4b06c5e..2e3d3cd 100755 (executable)
@@ -4,7 +4,7 @@
 # Build U-Boot image when `mkimage' tool is available.
 #
 
-MKIMAGE=$(type -path ${CROSS_COMPILE}mkimage)
+MKIMAGE=$(type -path "${CROSS_COMPILE}mkimage")
 
 if [ -z "${MKIMAGE}" ]; then
        MKIMAGE=$(type -path mkimage)
index b2f73ff..ed1244d 100644 (file)
@@ -37,7 +37,6 @@ typedef unsigned char __u8;
  * even potentially has different endianness and word sizes, since
  * we handle those differences explicitly below */
 #include "../../include/linux/mod_devicetable.h"
-#include "../../include/linux/input.h"
 
 #define ADD(str, sep, cond, field)                              \
 do {                                                            \
@@ -416,31 +415,33 @@ static int do_input_entry(const char *filename, struct input_device_id *id,
 
        sprintf(alias + strlen(alias), "-e*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
-               do_input(alias, id->evbit, 0, EV_MAX);
+               do_input(alias, id->evbit, 0, INPUT_DEVICE_ID_EV_MAX);
        sprintf(alias + strlen(alias), "k*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
-               do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+               do_input(alias, id->keybit,
+                        INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
+                        INPUT_DEVICE_ID_KEY_MAX);
        sprintf(alias + strlen(alias), "r*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
-               do_input(alias, id->relbit, 0, REL_MAX);
+               do_input(alias, id->relbit, 0, INPUT_DEVICE_ID_REL_MAX);
        sprintf(alias + strlen(alias), "a*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
-               do_input(alias, id->absbit, 0, ABS_MAX);
+               do_input(alias, id->absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
        sprintf(alias + strlen(alias), "m*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
-               do_input(alias, id->mscbit, 0, MSC_MAX);
+               do_input(alias, id->mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
        sprintf(alias + strlen(alias), "l*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
-               do_input(alias, id->ledbit, 0, LED_MAX);
+               do_input(alias, id->ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
        sprintf(alias + strlen(alias), "s*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
-               do_input(alias, id->sndbit, 0, SND_MAX);
+               do_input(alias, id->sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
        sprintf(alias + strlen(alias), "f*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
-               do_input(alias, id->ffbit, 0, FF_MAX);
+               do_input(alias, id->ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
        sprintf(alias + strlen(alias), "w*");
        if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
-               do_input(alias, id->swbit, 0, SW_MAX);
+               do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX);
        return 1;
 }
 
index 725d61c..db3881f 100644 (file)
@@ -55,7 +55,8 @@ main(int argc, char **argv)
        else
                exit(1);
 
-       if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0))
+       if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)
+           || (strcmp(argv[1], "blackfin") == 0))
                printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
        else
                printf("#define MODULE_SYMBOL_PREFIX \"\"\n");
index 65bdfdb..4ab36de 100644 (file)
@@ -55,6 +55,17 @@ void warn(const char *fmt, ...)
        va_end(arglist);
 }
 
+void merror(const char *fmt, ...)
+{
+       va_list arglist;
+
+       fprintf(stderr, "ERROR: ");
+
+       va_start(arglist, fmt);
+       vfprintf(stderr, fmt, arglist);
+       va_end(arglist);
+}
+
 static int is_vmlinux(const char *modname)
 {
        const char *myname;
@@ -333,10 +344,10 @@ void release_file(void *file, unsigned long size)
        munmap(file, size);
 }
 
-static void parse_elf(struct elf_info *info, const char *filename)
+static int parse_elf(struct elf_info *info, const char *filename)
 {
        unsigned int i;
-       Elf_Ehdr *hdr = info->hdr;
+       Elf_Ehdr *hdr;
        Elf_Shdr *sechdrs;
        Elf_Sym  *sym;
 
@@ -346,9 +357,18 @@ static void parse_elf(struct elf_info *info, const char *filename)
                exit(1);
        }
        info->hdr = hdr;
-       if (info->size < sizeof(*hdr))
-               goto truncated;
-
+       if (info->size < sizeof(*hdr)) {
+               /* file too small, assume this is an empty .o file */
+               return 0;
+       }
+       /* Is this a valid ELF file? */
+       if ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||
+           (hdr->e_ident[EI_MAG1] != ELFMAG1) ||
+           (hdr->e_ident[EI_MAG2] != ELFMAG2) ||
+           (hdr->e_ident[EI_MAG3] != ELFMAG3)) {
+               /* Not an ELF file - silently ignore it */
+               return 0;
+       }
        /* Fix endianness in ELF header */
        hdr->e_shoff    = TO_NATIVE(hdr->e_shoff);
        hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
@@ -371,8 +391,10 @@ static void parse_elf(struct elf_info *info, const char *filename)
                        = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
                const char *secname;
 
-               if (sechdrs[i].sh_offset > info->size)
-                       goto truncated;
+               if (sechdrs[i].sh_offset > info->size) {
+                       fatal("%s is truncated. sechdrs[i].sh_offset=%u > sizeof(*hrd)=%ul\n", filename, (unsigned int)sechdrs[i].sh_offset, sizeof(*hdr));
+                       return 0;
+               }
                secname = secstrings + sechdrs[i].sh_name;
                if (strcmp(secname, ".modinfo") == 0) {
                        info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
@@ -407,10 +429,7 @@ static void parse_elf(struct elf_info *info, const char *filename)
                sym->st_value = TO_NATIVE(sym->st_value);
                sym->st_size  = TO_NATIVE(sym->st_size);
        }
-       return;
-
- truncated:
-       fatal("%s is truncated.\n", filename);
+       return 1;
 }
 
 static void parse_elf_finish(struct elf_info *info)
@@ -581,9 +600,17 @@ static int strrcmp(const char *s, const char *sub)
  *   the pattern is identified by:
  *   tosec   = .init.text | .exit.text | .init.data
  *   fromsec = .data
- *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
+ *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console
  *
  * Pattern 3:
+ *   Whitelist all references from .pci_fixup* section to .init.text
+ *   This is part of the PCI init when built-in
+ *
+ * Pattern 4:
+ *   Whitelist all refereces from .text.head to .init.data
+ *   Whitelist all refereces from .text.head to .init.text
+ *
+ * Pattern 5:
  *   Some symbols belong to init section but still it is ok to reference
  *   these from non-init sections as these symbols don't have any memory
  *   allocated for them and symbol address and value are same. So even
@@ -591,6 +618,30 @@ static int strrcmp(const char *s, const char *sub)
  *   For ex. symbols marking the init section boundaries.
  *   This pattern is identified by
  *   refsymname = __init_begin, _sinittext, _einittext
+ *
+ * Pattern 6:
+ *   During the early init phase we have references from .init.text to
+ *   .text we have an intended section mismatch - do not warn about it.
+ *   See kernel_init() in init/main.c
+ *   tosec   = .init.text
+ *   fromsec = .text
+ *   atsym = kernel_init
+ *
+ * Pattern 7:
+ *  Logos used in drivers/video/logo reside in __initdata but the
+ *  funtion that references them are EXPORT_SYMBOL() so cannot be
+ *  marker __init. So we whitelist them here.
+ *  The pattern is:
+ *  tosec      = .init.data
+ *  fromsec    = .text*
+ *  refsymname = logo_
+ *
+ * Pattern 8:
+ *  Symbols contained in .paravirtprobe may safely reference .init.text.
+ *  The pattern is:
+ *  tosec   = .init.text
+ *  fromsec  = .paravirtprobe
+ *
  **/
 static int secref_whitelist(const char *modname, const char *tosec,
                            const char *fromsec, const char *atsym,
@@ -606,6 +657,7 @@ static int secref_whitelist(const char *modname, const char *tosec,
                "_probe",
                "_probe_one",
                "_console",
+               "apic_es7000",
                NULL
        };
 
@@ -641,25 +693,39 @@ static int secref_whitelist(const char *modname, const char *tosec,
        if (f1 && f2)
                return 1;
 
-       /* Whitelist all references from .pci_fixup section if vmlinux
-        * Whitelist all refereces from .text.head to .init.data if vmlinux
-        * Whitelist all refereces from .text.head to .init.text if vmlinux
-        */
-       if (is_vmlinux(modname)) {
-               if ((strcmp(fromsec, ".pci_fixup") == 0) &&
-                   (strcmp(tosec, ".init.text") == 0))
+       /* Check for pattern 3 */
+       if ((strncmp(fromsec, ".pci_fixup", strlen(".pci_fixup")) == 0) &&
+           (strcmp(tosec, ".init.text") == 0))
+       return 1;
+
+       /* Check for pattern 4 */
+       if ((strcmp(fromsec, ".text.head") == 0) &&
+               ((strcmp(tosec, ".init.data") == 0) ||
+               (strcmp(tosec, ".init.text") == 0)))
+       return 1;
+
+       /* Check for pattern 5 */
+       for (s = pat3refsym; *s; s++)
+               if (strcmp(refsymname, *s) == 0)
+                       return 1;
+
+       /* Check for pattern 6 */
+       if ((strcmp(tosec, ".init.text") == 0) &&
+           (strcmp(fromsec, ".text") == 0) &&
+           (strcmp(refsymname, "kernel_init") == 0))
                return 1;
 
-               if ((strcmp(fromsec, ".text.head") == 0) &&
-                       ((strcmp(tosec, ".init.data") == 0) ||
-                       (strcmp(tosec, ".init.text") == 0)))
+       /* Check for pattern 7 */
+       if ((strcmp(tosec, ".init.data") == 0) &&
+           (strncmp(fromsec, ".text", strlen(".text")) == 0) &&
+           (strncmp(refsymname, "logo_", strlen("logo_")) == 0))
+               return 1;
+
+       /* Check for pattern 8 */
+       if ((strcmp(tosec, ".init.text") == 0) &&
+           (strcmp(fromsec, ".paravirtprobe") == 0))
                return 1;
 
-               /* Check for pattern 3 */
-               for (s = pat3refsym; *s; s++)
-                       if (strcmp(refsymname, *s) == 0)
-                               return 1;
-       }
        return 0;
 }
 
@@ -1089,7 +1155,8 @@ static void read_symbols(char *modname)
        struct elf_info info = { };
        Elf_Sym *sym;
 
-       parse_elf(&info, modname);
+       if (!parse_elf(&info, modname))
+               return;
 
        mod = new_module(modname);
 
@@ -1264,9 +1331,14 @@ static int add_versions(struct buffer *b, struct module *mod)
                exp = find_symbol(s->name);
                if (!exp || exp->module == mod) {
                        if (have_vmlinux && !s->weak) {
-                               warn("\"%s\" [%s.ko] undefined!\n",
-                                    s->name, mod->name);
-                               err = warn_unresolved ? 0 : 1;
+                               if (warn_unresolved) {
+                                       warn("\"%s\" [%s.ko] undefined!\n",
+                                            s->name, mod->name);
+                               } else {
+                                       merror("\"%s\" [%s.ko] undefined!\n",
+                                                 s->name, mod->name);
+                                       err = 1;
+                               }
                        }
                        continue;
                }
@@ -1317,6 +1389,7 @@ static void add_depends(struct buffer *b, struct module *mod,
        buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n");
        buf_printf(b, "\"depends=");
        for (s = mod->unres; s; s = s->next) {
+               const char *p;
                if (!s->module)
                        continue;
 
@@ -1324,8 +1397,11 @@ static void add_depends(struct buffer *b, struct module *mod,
                        continue;
 
                s->module->seen = 1;
-               buf_printf(b, "%s%s", first ? "" : ",",
-                          strrchr(s->module->name, '/') + 1);
+               if ((p = strrchr(s->module->name, '/')) != NULL)
+                       p++;
+               else
+                       p = s->module->name;
+               buf_printf(b, "%s%s", first ? "" : ",", p);
                first = 0;
        }
        buf_printf(b, "\";\n");
index d398c61..0858caa 100644 (file)
@@ -145,3 +145,4 @@ void release_file(void *file, unsigned long size);
 
 void fatal(const char *fmt, ...);
 void warn(const char *fmt, ...);
+void merror(const char *fmt, ...);
index 8a28756..6873d5a 100644 (file)
@@ -397,10 +397,9 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
                (int) strlen(basename) - 2, basename);
 
        file = grab_file(filelist, &len);
-       if (!file) {
-               warn("could not find versions for %s\n", filelist);
+       if (!file)
+               /* not a module or .mod file missing - ignore */
                return;
-       }
 
        sources = strchr(file, '\n');
        if (!sources) {
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 7ea9acc..b493660 100644 (file)
@@ -104,7 +104,7 @@ static void dac_audio_set_rate(void)
        unsigned long interval;
        struct clk *clk;
 
-       clk = clk_get("module_clk");
+       clk = clk_get(NULL, "module_clk");
        interval = (clk_get_rate(clk) / 4) / rate;
        clk_put(clk);
        ctrl_outl(interval, TMU1_TCOR);
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);
        }
 }
 
index 07727f3..86cecb5 100644 (file)
@@ -17,7 +17,7 @@ config INITRAMFS_SOURCE
          When multiple directories and files are specified then the
          initramfs image will be the aggregate of all of them.
 
-         See <file:Documentation/early-userspace/README for more details.
+         See <file:Documentation/early-userspace/README> for more details.
 
          If you are not sure, leave it blank.